From a8020ecebe80cedebeb95d17e3c0741e4870db71 Mon Sep 17 00:00:00 2001 From: diced Date: Sun, 15 Jan 2023 13:39:07 -0800 Subject: [PATCH] refactor: many columns/tables in prisma --- package.json | 8 +- .../migration.sql | 8 + .../migration.sql | 2 + .../migration.sql | 2 + .../migration.sql | 5 + .../migration.sql | 19 +++ prisma/schema.prisma | 50 +++--- src/components/File.tsx | 24 +-- src/components/Type.tsx | 17 +- src/components/pages/Dashboard/index.tsx | 2 +- src/components/pages/Invites.tsx | 12 +- src/components/pages/Stats/Graphs.tsx | 6 +- src/components/pages/Upload/File.tsx | 12 +- src/components/pages/Upload/Text.tsx | 4 +- src/components/pages/Urls/URLCard.tsx | 4 +- src/lib/discord.ts | 12 +- src/lib/queries/files.ts | 12 +- src/lib/queries/stats.ts | 2 +- src/lib/queries/url.ts | 2 +- src/lib/util.ts | 12 +- src/lib/utils/exif.ts | 12 +- src/lib/utils/parser.ts | 4 +- src/pages/api/admin/clear.ts | 4 +- src/pages/api/auth/image.ts | 12 +- src/pages/api/auth/invite.ts | 12 +- src/pages/api/exif.ts | 10 +- src/pages/api/stats.ts | 8 +- src/pages/api/upload.ts | 76 ++++----- src/pages/api/user/[id].ts | 8 +- src/pages/api/user/export.ts | 8 +- src/pages/api/user/files.ts | 44 ++--- src/pages/api/user/index.ts | 2 +- src/pages/api/user/paged.ts | 20 +-- src/pages/api/user/recent.ts | 20 +-- src/pages/api/user/urls.ts | 4 +- src/pages/auth/register.tsx | 2 +- src/pages/code/[id].tsx | 10 +- src/pages/view/[id].tsx | 106 ++++++------ src/scripts/import-dir.ts | 2 +- src/server/decorators/dbFile.ts | 14 +- src/server/decorators/postFile.ts | 14 +- src/server/decorators/preFile.ts | 14 +- src/server/index.ts | 2 +- src/server/routes/raw.ts | 14 +- src/server/routes/uploads.ts | 10 +- src/server/util.ts | 8 +- yarn.lock | 155 +++++++++--------- 47 files changed, 424 insertions(+), 386 deletions(-) create mode 100644 prisma/migrations/20230115193136_rename_fields_image/migration.sql create mode 100644 prisma/migrations/20230115195550_rename_fields_url/migration.sql create mode 100644 prisma/migrations/20230115195803_rename_fields_stats/migration.sql create mode 100644 prisma/migrations/20230115195906_rename_fields_invite/migration.sql create mode 100644 prisma/migrations/20230115200747_rename_image_file/migration.sql diff --git a/package.json b/package.json index 6c51cfd8..c5365f3d 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,9 @@ "@mantine/notifications": "^5.9.2", "@mantine/nprogress": "^5.9.2", "@mantine/prism": "^5.9.2", - "@prisma/client": "^4.7.1", - "@prisma/internals": "^4.7.1", - "@prisma/migrate": "^4.7.1", + "@prisma/client": "^4.8.1", + "@prisma/internals": "^4.8.1", + "@prisma/migrate": "^4.8.1", "@sapphire/shapeshift": "^3.7.1", "@tanstack/react-query": "^4.19.1", "argon2": "^0.30.2", @@ -59,7 +59,7 @@ "multer": "^1.4.5-lts.1", "next": "^13.0.6", "otplib": "^12.0.1", - "prisma": "^4.7.1", + "prisma": "^4.8.1", "prismjs": "^1.29.0", "qrcode": "^1.5.1", "react": "^18.2.0", diff --git a/prisma/migrations/20230115193136_rename_fields_image/migration.sql b/prisma/migrations/20230115193136_rename_fields_image/migration.sql new file mode 100644 index 00000000..6187e47b --- /dev/null +++ b/prisma/migrations/20230115193136_rename_fields_image/migration.sql @@ -0,0 +1,8 @@ +-- AlterTable +ALTER TABLE "Image" RENAME COLUMN "created_at" TO "createdAt"; + +-- AlterTable +ALTER TABLE "Image" RENAME COLUMN "expires_at" TO "expiresAt"; + +-- AlterTable +ALTER TABLE "Image" RENAME COLUMN "file" TO "name"; \ No newline at end of file diff --git a/prisma/migrations/20230115195550_rename_fields_url/migration.sql b/prisma/migrations/20230115195550_rename_fields_url/migration.sql new file mode 100644 index 00000000..b7f95adf --- /dev/null +++ b/prisma/migrations/20230115195550_rename_fields_url/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Url" RENAME COLUMN "created_at" TO "createdAt"; \ No newline at end of file diff --git a/prisma/migrations/20230115195803_rename_fields_stats/migration.sql b/prisma/migrations/20230115195803_rename_fields_stats/migration.sql new file mode 100644 index 00000000..086cc412 --- /dev/null +++ b/prisma/migrations/20230115195803_rename_fields_stats/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Stats" RENAME COLUMN "created_at" TO "createdAt"; diff --git a/prisma/migrations/20230115195906_rename_fields_invite/migration.sql b/prisma/migrations/20230115195906_rename_fields_invite/migration.sql new file mode 100644 index 00000000..a9c1a333 --- /dev/null +++ b/prisma/migrations/20230115195906_rename_fields_invite/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "Invite" RENAME COLUMN "created_at" TO "createdAt"; + +-- AlterTable +ALTER TABLE "Invite" RENAME COLUMN "expires_at" TO "expiresAt"; \ No newline at end of file diff --git a/prisma/migrations/20230115200747_rename_image_file/migration.sql b/prisma/migrations/20230115200747_rename_image_file/migration.sql new file mode 100644 index 00000000..d1ad76a3 --- /dev/null +++ b/prisma/migrations/20230115200747_rename_image_file/migration.sql @@ -0,0 +1,19 @@ +-- AlterEnum +ALTER TYPE "ImageFormat" RENAME TO "FileNameFormat"; + +-- AlterTable +ALTER TABLE "Image" RENAME TO "File"; + +-- AlterTable +ALTER TABLE "InvisibleImage" RENAME TO "InvisibleFile"; + +-- AlterTable +ALTER TABLE "InvisibleFile" RENAME COLUMN "imageId" TO "fileId"; + +-- AlterForeignKey +ALTER TABLE "InvisibleFile" RENAME CONSTRAINT "InvisibleImage_imageId_fkey" TO "InvisibleFile_fileId_fkey"; +ALTER INDEX "InvisibleImage_imageId_key" RENAME TO "InvisibleFile_fileId_key"; + +-- AlterForeignKey +ALTER TABLE "InvisibleFile" RENAME CONSTRAINT "InvisibleImage_pkey" TO "InvisibleFile_pkey"; +ALTER TABLE "File" RENAME CONSTRAINT "Image_pkey" TO "File_pkey"; \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index cf39d495..8df53dc4 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -21,47 +21,49 @@ model User { totpSecret String? domains String[] oauth OAuth[] - images Image[] + files File[] urls Url[] Invite Invite[] } -enum ImageFormat { +enum FileNameFormat { UUID DATE RANDOM NAME } -model Image { - id Int @id @default(autoincrement()) - file String - mimetype String @default("image/png") - created_at DateTime @default(now()) - expires_at DateTime? - maxViews Int? - views Int @default(0) - favorite Boolean @default(false) - embed Boolean @default(false) - password String? - invisible InvisibleImage? - format ImageFormat @default(RANDOM) - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - userId Int? +model File { + id Int @id @default(autoincrement()) + name String + mimetype String @default("image/png") + createdAt DateTime @default(now()) + expiresAt DateTime? + maxViews Int? + views Int @default(0) + favorite Boolean @default(false) + embed Boolean @default(false) + password String? + invisible InvisibleFile? + format FileNameFormat @default(RANDOM) + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + userId Int? } -model InvisibleImage { +model InvisibleFile { id Int @id @default(autoincrement()) invis String @unique - imageId Int @unique - image Image @relation(fields: [imageId], references: [id], onDelete: Cascade) + // imageId Int @unique + fileId Int @unique + // image File @relation(fields: [imageId], references: [id], onDelete: Cascade) + file File @relation(fields: [fileId], references: [id], onDelete: Cascade) } model Url { id String @id @unique destination String vanity String? - created_at DateTime @default(now()) + createdAt DateTime @default(now()) maxViews Int? views Int @default(0) invisible InvisibleUrl? @@ -78,15 +80,15 @@ model InvisibleUrl { model Stats { id Int @id @default(autoincrement()) - created_at DateTime @default(now()) + createdAt DateTime @default(now()) data Json } model Invite { id Int @id @default(autoincrement()) code String @unique - created_at DateTime @default(now()) - expires_at DateTime? + createdAt DateTime @default(now()) + expiresAt DateTime? used Boolean @default(false) createdBy User @relation(fields: [createdById], references: [id], onDelete: Cascade) createdById Int diff --git a/src/components/File.tsx b/src/components/File.tsx index 762d6ac5..399f71d0 100644 --- a/src/components/File.tsx +++ b/src/components/File.tsx @@ -127,13 +127,13 @@ export default function File({ image, disableMediaPreview, exifEnabled }) { return ( <> - setOpen(false)} title={{image.file}} size='xl'> + setOpen(false)} title={{image.name}} size='xl'> - + {image.maxViews && ( @@ -164,15 +164,15 @@ export default function File({ image, disableMediaPreview, exifEnabled }) { - {image.expires_at && ( + {image.expiresAt && ( )} @@ -229,7 +229,7 @@ export default function File({ image, disableMediaPreview, exifEnabled }) { window.open(`/r/${image.file}?download=true`, '_blank')} + onClick={() => window.open(`/r/${image.name}?download=true`, '_blank')} > @@ -267,8 +267,8 @@ export default function File({ image, disableMediaPreview, exifEnabled }) { width: '100%', cursor: 'pointer', }} - src={`/r/${image.file}`} - alt={image.file} + src={`/r/${image.name}`} + alt={image.name} onClick={() => setOpen(true)} disableMediaPreview={disableMediaPreview} /> diff --git a/src/components/Type.tsx b/src/components/Type.tsx index 2c401ce7..b66aedac 100644 --- a/src/components/Type.tsx +++ b/src/components/Type.tsx @@ -41,20 +41,19 @@ export default function Type({ file, popup = false, disableMediaPreview, ...prop (file.type ?? file.mimetype) === '' ? file.name.split('.').pop() : (file.type ?? file.mimetype).split('/')[0]; - const name = file.name ?? file.file; const media = /^(video|audio|image|text)/.test(type); const [text, setText] = useState(''); - const shouldRenderMarkdown = name.endsWith('.md'); - const shouldRenderTex = name.endsWith('.tex'); + const shouldRenderMarkdown = file.name.endsWith('.md'); + const shouldRenderTex = file.name.endsWith('.tex'); const [loading, setLoading] = useState(type === 'text' && popup); if (type === 'text' && popup) { useEffect(() => { (async () => { - const res = await fetch('/r/' + name); + const res = await fetch('/r/' + file.name); const text = await res.text(); setText(text); @@ -112,7 +111,7 @@ export default function Type({ file, popup = false, disableMediaPreview, ...prop ) : ( <> {(shouldRenderMarkdown || shouldRenderTex) && renderRenderAlert()} - + )} @@ -123,17 +122,17 @@ export default function Type({ file, popup = false, disableMediaPreview, ...prop ) ) : media ? ( { - video: , + video: , image: ( } {...props} /> ), - audio: , - text: , + audio: , + text: , }[type] ) : ( - + ); } diff --git a/src/components/pages/Dashboard/index.tsx b/src/components/pages/Dashboard/index.tsx index 112ef85e..8195c457 100644 --- a/src/components/pages/Dashboard/index.tsx +++ b/src/components/pages/Dashboard/index.tsx @@ -146,7 +146,7 @@ export default function Dashboard({ disableMediaPreview, exifEnabled }) { filterFn: stringFilterFn, }, { - accessorKey: 'created_at', + accessorKey: 'createdAt', header: 'Date', filterFn: dateFilterFn, }, diff --git a/src/components/pages/Invites.tsx b/src/components/pages/Invites.tsx index bc505a5c..823116f2 100644 --- a/src/components/pages/Invites.tsx +++ b/src/components/pages/Invites.tsx @@ -38,7 +38,7 @@ function CreateInviteModal({ open, setOpen, updateInvites }) { if (!expires.includes(values.expires)) return form.setFieldError('expires', 'Invalid expiration'); if (values.count < 1 || values.count > 100) return form.setFieldError('count', 'Must be between 1 and 100'); - const expires_at = + const expiresAt = values.expires === 'never' ? null : new Date( @@ -57,7 +57,7 @@ function CreateInviteModal({ open, setOpen, updateInvites }) { setOpen(false); const res = await useFetch('/api/auth/invite', 'POST', { - expires_at, + expiresAt, count: values.count, }); @@ -201,14 +201,14 @@ export default function Invites() { {invite.code} {invite.used && <> (Used)} - +
- Created {relativeTime(new Date(invite.created_at))} + Created {relativeTime(new Date(invite.createdAt))}
- +
- {expireText(invite.expires_at)} + {expireText(invite.expiresAt)}
diff --git a/src/components/pages/Stats/Graphs.tsx b/src/components/pages/Stats/Graphs.tsx index 5bd45772..18876632 100644 --- a/src/components/pages/Stats/Graphs.tsx +++ b/src/components/pages/Stats/Graphs.tsx @@ -16,17 +16,17 @@ export default function Graphs() { const data = Array.from(historicalStats.data).reverse(); const views = data.map((stat) => ({ - date: new Date(stat.created_at).toLocaleDateString(), + date: new Date(stat.createdAt).toLocaleDateString(), views: stat.data.views_count, })); const uploads = data.map((stat) => ({ - date: new Date(stat.created_at).toLocaleDateString(), + date: new Date(stat.createdAt).toLocaleDateString(), uploads: stat.data.count, })); const storage = data.map((stat) => ({ - date: new Date(stat.created_at).toLocaleDateString(), + date: new Date(stat.createdAt).toLocaleDateString(), bytes: stat.data.size_num, })); diff --git a/src/components/pages/Upload/File.tsx b/src/components/pages/Upload/File.tsx index 00139d86..61c8fe22 100644 --- a/src/components/pages/Upload/File.tsx +++ b/src/components/pages/Upload/File.tsx @@ -50,7 +50,7 @@ export default function File({ chunks: chunks_config }) { }); }); - const handleChunkedFiles = async (expires_at: Date, toChunkFiles: File[]) => { + const handleChunkedFiles = async (expiresAt: Date, toChunkFiles: File[]) => { for (let i = 0; i !== toChunkFiles.length; ++i) { const file = toChunkFiles[i]; const identifier = randomChars(4); @@ -153,7 +153,7 @@ export default function File({ chunks: chunks_config }) { req.setRequestHeader('X-Zipline-Partial-MimeType', file.type); req.setRequestHeader('X-Zipline-Partial-Identifier', identifier); req.setRequestHeader('X-Zipline-Partial-LastChunk', j === chunks.length - 1 ? 'true' : 'false'); - options.expires !== 'never' && req.setRequestHeader('Expires-At', 'date=' + expires_at.toISOString()); + options.expires !== 'never' && req.setRequestHeader('Expires-At', 'date=' + expiresAt.toISOString()); options.password.trim() !== '' && req.setRequestHeader('Password', options.password); options.maxViews && options.maxViews !== 0 && @@ -172,7 +172,7 @@ export default function File({ chunks: chunks_config }) { }; const handleUpload = async () => { - const expires_at = options.expires === 'never' ? null : expireReadToDate(options.expires); + const expiresAt = options.expires === 'never' ? null : expireReadToDate(options.expires); setProgress(0); setLoading(true); @@ -199,7 +199,7 @@ export default function File({ chunks: chunks_config }) { autoClose: false, }); - return handleChunkedFiles(expires_at, toChunkFiles); + return handleChunkedFiles(expiresAt, toChunkFiles); } showNotification({ @@ -245,7 +245,7 @@ export default function File({ chunks: chunks_config }) { autoClose: false, }); - return handleChunkedFiles(expires_at, toChunkFiles); + return handleChunkedFiles(expiresAt, toChunkFiles); } } else { updateNotification({ @@ -264,7 +264,7 @@ export default function File({ chunks: chunks_config }) { if (bodyLength !== 0) { req.open('POST', '/api/upload'); req.setRequestHeader('Authorization', user.token); - options.expires !== 'never' && req.setRequestHeader('Expires-At', 'date=' + expires_at.toISOString()); + options.expires !== 'never' && req.setRequestHeader('Expires-At', 'date=' + expiresAt.toISOString()); options.password.trim() !== '' && req.setRequestHeader('Password', options.password); options.maxViews && options.maxViews !== 0 && diff --git a/src/components/pages/Upload/Text.tsx b/src/components/pages/Upload/Text.tsx index ddfe0ab5..9dfd871b 100644 --- a/src/components/pages/Upload/Text.tsx +++ b/src/components/pages/Upload/Text.tsx @@ -31,7 +31,7 @@ export default function Text() { const handleUpload = async () => { const file = new File([value], 'text.' + lang); - const expires_at = options.expires === 'never' ? null : expireReadToDate(options.expires); + const expiresAt = options.expires === 'never' ? null : expireReadToDate(options.expires); showNotification({ id: 'upload-text', @@ -63,7 +63,7 @@ export default function Text() { req.setRequestHeader('Authorization', user.token); req.setRequestHeader('UploadText', 'true'); - options.expires !== 'never' && req.setRequestHeader('Expires-At', 'date=' + expires_at.toISOString()); + options.expires !== 'never' && req.setRequestHeader('Expires-At', 'date=' + expiresAt.toISOString()); options.password.trim() !== '' && req.setRequestHeader('Password', options.password); options.maxViews && options.maxViews !== 0 && req.setRequestHeader('Max-Views', String(options.maxViews)); options.compression !== 'none' && req.setRequestHeader('Image-Compression-Percent', options.compression); diff --git a/src/components/pages/Urls/URLCard.tsx b/src/components/pages/Urls/URLCard.tsx index fdc49edf..add84150 100644 --- a/src/components/pages/Urls/URLCard.tsx +++ b/src/components/pages/Urls/URLCard.tsx @@ -51,9 +51,9 @@ export default function URLCard({ url }: { url: URLResponse }) { {url.vanity ?? url.id} - +
- Created: {relativeTime(new Date(url.created_at))} + Created: {relativeTime(new Date(url.createdAt))}
{url.vanity && ID: {url.id}} diff --git a/src/lib/discord.ts b/src/lib/discord.ts index fc914aaf..b8967138 100644 --- a/src/lib/discord.ts +++ b/src/lib/discord.ts @@ -1,4 +1,4 @@ -import { Image, Url, User } from '@prisma/client'; +import { File, Url, User } from '@prisma/client'; import config from 'lib/config'; import { ConfigDiscordContent } from 'config/Config'; import Logger from 'lib/logger'; @@ -27,17 +27,17 @@ export function parseContent( }; } -export async function sendUpload(user: User, image: Image, raw_link: string, link: string) { +export async function sendUpload(user: User, file: File, raw_link: string, link: string) { if (!config.discord.upload) return; const parsed = parseContent(config.discord.upload, { - file: image, + file, user, link, raw_link, }); - const isImage = image.mimetype.startsWith('image/'); + const isImage = file.mimetype.startsWith('image/'); const body = JSON.stringify({ username: config.discord.username, @@ -49,7 +49,7 @@ export async function sendUpload(user: User, image: Image, raw_link: string, lin title: parsed.embed.title ?? null, description: parsed.embed.description ?? null, url: parsed.url ?? null, - timestamp: parsed.embed.timestamp ? image.created_at.toISOString() : null, + timestamp: parsed.embed.timestamp ? file.createdAt.toISOString() : null, color: parsed.embed.color ?? null, footer: parsed.embed.footer ? { @@ -111,7 +111,7 @@ export async function sendShorten(user: User, url: Url, link: string) { title: parsed.embed.title ?? null, description: parsed.embed.description ?? null, url: parsed.url ?? null, - timestamp: parsed.embed.timestamp ? url.created_at.toISOString() : null, + timestamp: parsed.embed.timestamp ? url.createdAt.toISOString() : null, color: parsed.embed.color ?? null, footer: parsed.embed.footer ? { diff --git a/src/lib/queries/files.ts b/src/lib/queries/files.ts index 66ab9382..c009d45a 100644 --- a/src/lib/queries/files.ts +++ b/src/lib/queries/files.ts @@ -2,9 +2,9 @@ import { useMutation, useQuery } from '@tanstack/react-query'; import queryClient from './client'; export type UserFilesResponse = { - created_at: string; - expires_at?: string; - file: string; + createdAt: string; + expiresAt?: string; + name: string; mimetype: string; id: string; favorite: boolean; @@ -23,7 +23,7 @@ export const useFiles = (query: { [key: string]: string } = {}) => { ? data : data.map((x) => ({ ...x, - created_at: new Date(x.created_at).toLocaleString(), + createdAt: new Date(x.createdAt).toLocaleString(), })) ); }); @@ -39,7 +39,7 @@ export const usePaginatedFiles = (page?: number, filter: string = 'media', favor return useQuery(['files', queryString], async () => { return fetch('/api/user/paged?' + queryString) .then((res) => res.json() as Promise) - .then((data) => data.map((x) => ({ ...x, created_at: new Date(x.created_at).toLocaleString() }))); + .then((data) => data.map((x) => ({ ...x, createdAt: new Date(x.createdAt).toLocaleString() }))); }); }; @@ -50,7 +50,7 @@ export const useRecent = (filter?: string) => { .then((data) => data.map((x) => ({ ...x, - created_at: new Date(x.created_at).toLocaleString(), + createdAt: new Date(x.createdAt).toLocaleString(), })) ); }); diff --git a/src/lib/queries/stats.ts b/src/lib/queries/stats.ts index 6e7503af..bb75dbe2 100644 --- a/src/lib/queries/stats.ts +++ b/src/lib/queries/stats.ts @@ -6,7 +6,7 @@ type StatsTypesCount = { }; export type Stats = { - created_at: string; + createdAt: string; id: number; data: { count: number; diff --git a/src/lib/queries/url.ts b/src/lib/queries/url.ts index a7fa9711..aa26f312 100644 --- a/src/lib/queries/url.ts +++ b/src/lib/queries/url.ts @@ -2,7 +2,7 @@ import { useMutation, useQuery } from '@tanstack/react-query'; import queryClient from './client'; export type URLResponse = { - created_at: string; + createdAt: string; destination: string; id: string; url: string; diff --git a/src/lib/util.ts b/src/lib/util.ts index 1369af1a..c4c4fc00 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -1,4 +1,4 @@ -import { InvisibleImage, InvisibleUrl } from '@prisma/client'; +import { InvisibleFile, InvisibleUrl } from '@prisma/client'; import { hash, verify } from 'argon2'; import { randomBytes } from 'crypto'; import { readdir, stat } from 'fs/promises'; @@ -60,11 +60,11 @@ export function randomInvis(length: number) { .concat(invisibleCharset[0]); } -export function createInvisImage(length: number, imageId: number) { - const retry = async (): Promise => { +export function createInvisImage(length: number, fileId: number) { + const retry = async (): Promise => { const invis = randomInvis(length); - const existing = await prisma.invisibleImage.findUnique({ + const existing = await prisma.invisibleFile.findUnique({ where: { invis, }, @@ -72,10 +72,10 @@ export function createInvisImage(length: number, imageId: number) { if (existing) return retry(); - const inv = await prisma.invisibleImage.create({ + const inv = await prisma.invisibleFile.create({ data: { invis, - imageId, + fileId, }, }); diff --git a/src/lib/utils/exif.ts b/src/lib/utils/exif.ts index d55fd274..b3a29af3 100644 --- a/src/lib/utils/exif.ts +++ b/src/lib/utils/exif.ts @@ -1,4 +1,4 @@ -import { Image } from '@prisma/client'; +import { File } from '@prisma/client'; import { createWriteStream } from 'fs'; import { ExifTool, Tags } from 'exiftool-vendored'; import datasource from 'lib/datasource'; @@ -32,12 +32,12 @@ export async function readMetadata(filePath: string): Promise { return exif; } -export async function removeGPSData(image: Image): Promise { +export async function removeGPSData(image: File): Promise { const exiftool = new ExifTool({ cleanupChildProcs: false }); - const file = join(tmpdir(), `zipline-exif-remove-${Date.now()}-${image.file}`); + const file = join(tmpdir(), `zipline-exif-remove-${Date.now()}-${image.name}`); logger.debug(`writing temp file to remove GPS data: ${file}`); - const stream = await datasource.get(image.file); + const stream = await datasource.get(image.name); const writeStream = createWriteStream(file); stream.pipe(writeStream); @@ -80,9 +80,9 @@ export async function removeGPSData(image: Image): Promise { GPSTrackRef: null, }); - logger.debug(`reading file to upload to datasource: ${file} -> ${image.file}`); + logger.debug(`reading file to upload to datasource: ${file} -> ${image.name}`); const buffer = await readFile(file); - await datasource.save(image.file, buffer); + await datasource.save(image.name, buffer); logger.debug(`removing temp file: ${file}`); await unlink(file); diff --git a/src/lib/utils/parser.ts b/src/lib/utils/parser.ts index 0361ae51..2d0e3661 100644 --- a/src/lib/utils/parser.ts +++ b/src/lib/utils/parser.ts @@ -1,7 +1,7 @@ -import type { Image, User, Url } from '@prisma/client'; +import type { File, User, Url } from '@prisma/client'; export type ParseValue = { - file?: Image; + file?: File; url?: Url; user?: User; diff --git a/src/pages/api/admin/clear.ts b/src/pages/api/admin/clear.ts index ce46c45b..50a35321 100644 --- a/src/pages/api/admin/clear.ts +++ b/src/pages/api/admin/clear.ts @@ -7,8 +7,8 @@ const logger = Logger.get('admin'); async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { try { - const { count } = await prisma.image.deleteMany({}); - logger.info(`User ${user.username} (${user.id}) cleared the database of ${count} images`); + const { count } = await prisma.file.deleteMany({}); + logger.info(`User ${user.username} (${user.id}) cleared the database of ${count} files`); if (req.body.datasource) { await datasource.clear(); diff --git a/src/pages/api/auth/image.ts b/src/pages/api/auth/image.ts index 9531ff1c..b2ae5d7e 100644 --- a/src/pages/api/auth/image.ts +++ b/src/pages/api/auth/image.ts @@ -8,24 +8,24 @@ import { extname } from 'path'; async function handler(req: NextApiReq, res: NextApiRes) { const { id, password } = req.query; - const image = await prisma.image.findFirst({ + const file = await prisma.file.findFirst({ where: { id: Number(id), }, }); - if (!image) return res.notFound('image not found'); + if (!file) return res.notFound('image not found'); if (!password) return res.badRequest('no password provided'); - const valid = await checkPassword(password as string, image.password); + const valid = await checkPassword(password as string, file.password); if (!valid) return res.badRequest('wrong password'); - const data = await datasource.get(image.file); + const data = await datasource.get(file.name); if (!data) return res.notFound('image not found'); - const size = await datasource.size(image.file); + const size = await datasource.size(file.name); - const mimetype = await guess(extname(image.file)); + const mimetype = await guess(extname(file.name)); res.setHeader('Content-Type', mimetype); res.setHeader('Content-Length', size); diff --git a/src/pages/api/auth/invite.ts b/src/pages/api/auth/invite.ts index c3496dbf..ab02b61f 100644 --- a/src/pages/api/auth/invite.ts +++ b/src/pages/api/auth/invite.ts @@ -10,12 +10,12 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { if (!config.features.invites) return res.badRequest('invites are disabled'); if (req.method === 'POST') { - const { expires_at, count } = req.body as { - expires_at: string; + const { expiresAt, count } = req.body as { + expiresAt: string; count: number; }; - const expiry = expires_at ? new Date(expires_at) : null; + const expiry = expiresAt ? new Date(expiresAt) : null; if (expiry) { if (!expiry.getTime()) return res.badRequest('invalid date'); if (expiry.getTime() < Date.now()) return res.badRequest('date is in the past'); @@ -28,7 +28,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { data.push({ code: randomChars(config.features.invites_length), createdById: user.id, - expires_at: expiry, + expiresAt: expiry, }); } @@ -48,7 +48,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { data: { code: randomChars(config.features.invites_length), createdById: user.id, - expires_at: expiry, + expiresAt: expiry, }, }); @@ -78,7 +78,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { } else { const invites = await prisma.invite.findMany({ orderBy: { - created_at: 'desc', + createdAt: 'desc', }, }); diff --git a/src/pages/api/exif.ts b/src/pages/api/exif.ts index 86af8899..f42b54b0 100644 --- a/src/pages/api/exif.ts +++ b/src/pages/api/exif.ts @@ -17,7 +17,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { const { id } = req.query as { id: string }; if (!id) return res.badRequest('no id'); - const image = await prisma.image.findFirst({ + const image = await prisma.file.findFirst({ where: { id: Number(id), userId: user.id, @@ -27,11 +27,11 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { if (!image) return res.notFound('image not found'); logger.info( - `${user.username} (${user.id}) requested to read exif metadata for image ${image.file} (${image.id})` + `${user.username} (${user.id}) requested to read exif metadata for image ${image.name} (${image.id})` ); if (config.datasource.type === 'local') { - const filePath = join(config.datasource.local.directory, image.file); + const filePath = join(config.datasource.local.directory, image.name); logger.debug(`attemping to read exif metadata from ${filePath}`); if (!existsSync(filePath)) return res.notFound('image not found on fs'); @@ -41,10 +41,10 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { return res.json(data); } else { - const file = join(tmpdir(), `zipline-exif-read-${Date.now()}-${image.file}`); + const file = join(tmpdir(), `zipline-exif-read-${Date.now()}-${image.name}`); logger.debug(`writing temp file to view metadata: ${file}`); - const stream = await datasource.get(image.file); + const stream = await datasource.get(image.name); const writeStream = createWriteStream(file); stream.pipe(writeStream); diff --git a/src/pages/api/stats.ts b/src/pages/api/stats.ts index c3ae15e0..f9303bbf 100644 --- a/src/pages/api/stats.ts +++ b/src/pages/api/stats.ts @@ -27,12 +27,12 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { let stats: Stats[] = await prisma.$queryRaw` SELECT * FROM "Stats" as t JOIN - (SELECT MAX(t2."created_at") as max_timestamp + (SELECT MAX(t2."createdAt") as max_timestamp FROM "Stats" t2 - GROUP BY date(t2."created_at") + GROUP BY date(t2."createdAt") ) t2 - ON t."created_at" = t2.max_timestamp - ORDER BY t."created_at" DESC + ON t."createdAt" = t2.max_timestamp + ORDER BY t."createdAt" DESC LIMIT ${amount} `; diff --git a/src/pages/api/upload.ts b/src/pages/api/upload.ts index d713011f..8916adb7 100644 --- a/src/pages/api/upload.ts +++ b/src/pages/api/upload.ts @@ -1,4 +1,4 @@ -import { ImageFormat, InvisibleImage } from '@prisma/client'; +import { FileNameFormat, InvisibleFile } from '@prisma/client'; import { randomUUID } from 'crypto'; import dayjs from 'dayjs'; import { readdir, readFile, unlink, writeFile } from 'fs/promises'; @@ -37,15 +37,15 @@ async function handler(req: NextApiReq, res: NextApiRes) { }); }); - const response: { files: string[]; expires_at?: Date; removed_gps?: boolean } = { files: [] }; - const expires_at = req.headers['expires-at'] as string; + const response: { files: string[]; expiresAt?: Date; removed_gps?: boolean } = { files: [] }; + const expiresAt = req.headers['expires-at'] as string; let expiry: Date; - if (expires_at) { - expiry = parseExpiry(expires_at); + if (expiresAt) { + expiry = parseExpiry(expiresAt); if (!expiry) return res.badRequest('invalid date'); else { - response.expires_at = expiry; + response.expiresAt = expiry; } } @@ -55,7 +55,7 @@ async function handler(req: NextApiReq, res: NextApiRes) { } const rawFormat = ((req.headers.format || '') as string).toUpperCase() || zconfig.uploader.default_format; - const format: ImageFormat = Object.keys(ImageFormat).includes(rawFormat) && ImageFormat[rawFormat]; + const format: FileNameFormat = Object.keys(FileNameFormat).includes(rawFormat) && FileNameFormat[rawFormat]; const imageCompressionPercent = req.headers['image-compression-percent'] ? Number(req.headers['image-compression-percent']) @@ -127,16 +127,16 @@ async function handler(req: NextApiReq, res: NextApiRes) { let fileName: string; switch (format) { - case ImageFormat.RANDOM: + case FileNameFormat.RANDOM: fileName = randomChars(zconfig.uploader.length); break; - case ImageFormat.DATE: + case FileNameFormat.DATE: fileName = dayjs().format(zconfig.uploader.format_date); break; - case ImageFormat.UUID: + case FileNameFormat.UUID: fileName = randomUUID({ disableEntropyCache: true }); break; - case ImageFormat.NAME: + case FileNameFormat.NAME: fileName = filename.split('.')[0]; break; default: @@ -150,38 +150,38 @@ async function handler(req: NextApiReq, res: NextApiRes) { } const compressionUsed = imageCompressionPercent && mimetype.startsWith('image/'); - let invis: InvisibleImage; + let invis: InvisibleFile; - const file = await prisma.image.create({ + const file = await prisma.file.create({ data: { - file: `${fileName}${compressionUsed ? '.jpg' : `${ext ? '.' : ''}${ext}`}`, + name: `${fileName}${compressionUsed ? '.jpg' : `${ext ? '.' : ''}${ext}`}`, mimetype, userId: user.id, embed: !!req.headers.embed, format, password, - expires_at: expiry, + expiresAt: expiry, maxViews: fileMaxViews, }, }); if (req.headers.zws) invis = await createInvisImage(zconfig.uploader.length, file.id); - await datasource.save(file.file, Buffer.from(chunks)); + await datasource.save(file.name, Buffer.from(chunks)); - logger.info(`User ${user.username} (${user.id}) uploaded ${file.file} (${file.id}) (chunked)`); + logger.info(`User ${user.username} (${user.id}) uploaded ${file.name} (${file.id}) (chunked)`); if (user.domains.length) { const domain = user.domains[Math.floor(Math.random() * user.domains.length)]; response.files.push( `${domain}${zconfig.uploader.route === '/' ? '' : zconfig.uploader.route}/${ - invis ? invis.invis : file.file + invis ? invis.invis : file.name }` ); } else { response.files.push( `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${ zconfig.uploader.route === '/' ? '' : zconfig.uploader.route - }/${invis ? invis.invis : file.file}` + }/${invis ? invis.invis : file.name}` ); } @@ -190,11 +190,11 @@ async function handler(req: NextApiReq, res: NextApiRes) { user, file, `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}/r/${ - invis ? invis.invis : file.file + invis ? invis.invis : file.name }`, `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${ zconfig.uploader.route === '/' ? '' : zconfig.uploader.route - }/${invis ? invis.invis : file.file}` + }/${invis ? invis.invis : file.name}` ); } @@ -255,24 +255,24 @@ async function handler(req: NextApiReq, res: NextApiRes) { let fileName: string; switch (format) { - case ImageFormat.RANDOM: + case FileNameFormat.RANDOM: fileName = randomChars(zconfig.uploader.length); break; - case ImageFormat.DATE: + case FileNameFormat.DATE: fileName = dayjs().format(zconfig.uploader.format_date); break; - case ImageFormat.UUID: + case FileNameFormat.UUID: fileName = randomUUID({ disableEntropyCache: true }); break; - case ImageFormat.NAME: + case FileNameFormat.NAME: fileName = file.originalname.split('.')[0]; break; default: if (req.headers['x-zipline-filename']) { fileName = req.headers['x-zipline-filename'] as string; - const existing = await prisma.image.findFirst({ + const existing = await prisma.file.findFirst({ where: { - file: fileName, + name: fileName, }, }); if (existing) return res.badRequest(`file[${i}]: filename already exists: '${fileName}'`); @@ -289,16 +289,16 @@ async function handler(req: NextApiReq, res: NextApiRes) { } const compressionUsed = imageCompressionPercent && file.mimetype.startsWith('image/'); - let invis: InvisibleImage; - const image = await prisma.image.create({ + let invis: InvisibleFile; + const image = await prisma.file.create({ data: { - file: `${fileName}${compressionUsed ? '.jpg' : `${ext ? '.' : ''}${ext}`}`, + name: `${fileName}${compressionUsed ? '.jpg' : `${ext ? '.' : ''}${ext}`}`, mimetype: req.headers.uploadtext ? 'text/plain' : compressionUsed ? 'image/jpeg' : file.mimetype, userId: user.id, embed: !!req.headers.embed, format, password, - expires_at: expiry, + expiresAt: expiry, maxViews: fileMaxViews, }, }); @@ -307,27 +307,27 @@ async function handler(req: NextApiReq, res: NextApiRes) { if (compressionUsed) { const buffer = await sharp(file.buffer).jpeg({ quality: imageCompressionPercent }).toBuffer(); - await datasource.save(image.file, buffer); + await datasource.save(image.name, buffer); logger.info( `User ${user.username} (${user.id}) compressed image from ${file.buffer.length} -> ${buffer.length} bytes` ); } else { - await datasource.save(image.file, file.buffer); + await datasource.save(image.name, file.buffer); } - logger.info(`User ${user.username} (${user.id}) uploaded ${image.file} (${image.id})`); + logger.info(`User ${user.username} (${user.id}) uploaded ${image.name} (${image.id})`); if (user.domains.length) { const domain = user.domains[Math.floor(Math.random() * user.domains.length)]; response.files.push( `${domain}${zconfig.uploader.route === '/' ? '' : zconfig.uploader.route}/${ - invis ? invis.invis : image.file + invis ? invis.invis : image.name }` ); } else { response.files.push( `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${ zconfig.uploader.route === '/' ? '' : zconfig.uploader.route - }/${invis ? invis.invis : image.file}` + }/${invis ? invis.invis : image.name}` ); } @@ -338,11 +338,11 @@ async function handler(req: NextApiReq, res: NextApiRes) { user, image, `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}/r/${ - invis ? invis.invis : image.file + invis ? invis.invis : image.name }`, `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${ zconfig.uploader.route === '/' ? '' : zconfig.uploader.route - }/${invis ? invis.invis : image.file}` + }/${invis ? invis.invis : image.name}` ); } diff --git a/src/pages/api/user/[id].ts b/src/pages/api/user/[id].ts index e871410d..5e02a01b 100644 --- a/src/pages/api/user/[id].ts +++ b/src/pages/api/user/[id].ts @@ -31,7 +31,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { if (req.body.delete_files) { logger.debug(`attempting to delete ${newTarget.id}'s files`); - const files = await prisma.image.findMany({ + const files = await prisma.file.findMany({ where: { userId: newTarget.id, }, @@ -39,13 +39,13 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { for (let i = 0; i !== files.length; ++i) { try { - await datasource.delete(files[i].file); + await datasource.delete(files[i].name); } catch { - logger.debug(`failed to find file ${files[i].file} to delete`); + logger.debug(`failed to find file ${files[i].name} to delete`); } } - const { count } = await prisma.image.deleteMany({ + const { count } = await prisma.file.deleteMany({ where: { userId: newTarget.id, }, diff --git a/src/pages/api/user/export.ts b/src/pages/api/user/export.ts index 691e23fe..cee763d7 100644 --- a/src/pages/api/user/export.ts +++ b/src/pages/api/user/export.ts @@ -12,7 +12,7 @@ const logger = Logger.get('user::export'); async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { if (req.method === 'POST') { - const files = await prisma.image.findMany({ + const files = await prisma.file.findMany({ where: { userId: user.id, }, @@ -92,9 +92,9 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { for (let i = 0; i !== files.length; ++i) { const file = files[i]; - const stream = await datasource.get(file.file); + const stream = await datasource.get(file.name); if (stream) { - const def = new ZipPassThrough(file.file); + const def = new ZipPassThrough(file.name); zip.add(def); onBackpressure(def, stream, (shouldApplyBackpressure) => { if (shouldApplyBackpressure) { @@ -106,7 +106,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { stream.on('data', (c) => def.push(c)); stream.on('end', () => def.push(new Uint8Array(0), true)); } else { - logger.debug(`couldn't find stream for ${file.file}`); + logger.debug(`couldn't find stream for ${file.name}`); } } diff --git a/src/pages/api/user/files.ts b/src/pages/api/user/files.ts index 7cac9a9b..8ee1f953 100644 --- a/src/pages/api/user/files.ts +++ b/src/pages/api/user/files.ts @@ -9,17 +9,17 @@ const logger = Logger.get('files'); async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { if (req.method === 'DELETE') { if (req.body.all) { - const files = await prisma.image.findMany({ + const files = await prisma.file.findMany({ where: { userId: user.id, }, }); for (let i = 0; i !== files.length; ++i) { - await datasource.delete(files[i].file); + await datasource.delete(files[i].name); } - const { count } = await prisma.image.deleteMany({ + const { count } = await prisma.file.deleteMany({ where: { userId: user.id, }, @@ -30,18 +30,18 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { } else { if (!req.body.id) return res.badRequest('no file id'); - const image = await prisma.image.delete({ + const file = await prisma.file.delete({ where: { id: req.body.id, }, }); - await datasource.delete(image.file); + await datasource.delete(file.name); - logger.info(`User ${user.username} (${user.id}) deleted an image ${image.file} (${image.id})`); + logger.info(`User ${user.username} (${user.id}) deleted an image ${file.name} (${file.id})`); - delete image.password; - return res.json(image); + delete file.password; + return res.json(file); } } else if (req.method === 'PATCH') { if (!req.body.id) return res.badRequest('no file id'); @@ -49,7 +49,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { let image; if (req.body.favorite !== null) - image = await prisma.image.update({ + image = await prisma.file.update({ where: { id: req.body.id }, data: { favorite: req.body.favorite, @@ -59,27 +59,27 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { delete image.password; return res.json(image); } else { - let images: { + let files: { favorite: boolean; - created_at: Date; + createdAt: Date; id: number; - file: string; + name: string; mimetype: string; - expires_at: Date; + expiresAt: Date; maxViews: number; views: number; - }[] = await prisma.image.findMany({ + }[] = await prisma.file.findMany({ where: { userId: user.id, favorite: !!req.query.favorite, }, orderBy: { - created_at: 'desc', + createdAt: 'desc', }, select: { - created_at: true, - expires_at: true, - file: true, + createdAt: true, + expiresAt: true, + name: true, mimetype: true, id: true, favorite: true, @@ -88,14 +88,14 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { }, }); - for (let i = 0; i !== images.length; ++i) { - (images[i] as unknown as { url: string }).url = `${config.uploader.route}/${images[i].file}`; + for (let i = 0; i !== files.length; ++i) { + (files[i] as unknown as { url: string }).url = `${config.uploader.route}/${files[i].name}`; } if (req.query.filter && req.query.filter === 'media') - images = images.filter((x) => /^(video|audio|image|text)/.test(x.mimetype)); + files = files.filter((x) => /^(video|audio|image|text)/.test(x.mimetype)); - return res.json(images); + return res.json(files); } } diff --git a/src/pages/api/user/index.ts b/src/pages/api/user/index.ts index bd546182..e18bde6f 100644 --- a/src/pages/api/user/index.ts +++ b/src/pages/api/user/index.ts @@ -212,7 +212,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { administrator: true, embed: true, id: true, - images: false, + files: false, password: false, systemTheme: true, token: true, diff --git a/src/pages/api/user/paged.ts b/src/pages/api/user/paged.ts index 8c2e6ac1..4fd590c9 100644 --- a/src/pages/api/user/paged.ts +++ b/src/pages/api/user/paged.ts @@ -35,7 +35,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { }; if (count) { - const count = await prisma.image.count({ + const count = await prisma.file.count({ where, }); @@ -49,22 +49,22 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { let files: { favorite: boolean; - created_at: Date; + createdAt: Date; id: number; - file: string; + name: string; mimetype: string; - expires_at: Date; + expiresAt: Date; maxViews: number; views: number; - }[] = await prisma.image.findMany({ + }[] = await prisma.file.findMany({ where, orderBy: { - created_at: 'desc', + createdAt: 'desc', }, select: { - created_at: true, - expires_at: true, - file: true, + createdAt: true, + expiresAt: true, + name: true, mimetype: true, id: true, favorite: true, @@ -78,7 +78,7 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { for (let i = 0; i !== files.length; ++i) { (files[i] as unknown as { url: string }).url = `${ config.uploader.route === '/' ? '/' : `${config.uploader.route}/` - }${files[i].file}`; + }${files[i].name}`; } return res.json(files); diff --git a/src/pages/api/user/recent.ts b/src/pages/api/user/recent.ts index 31abd471..be1b6cf5 100644 --- a/src/pages/api/user/recent.ts +++ b/src/pages/api/user/recent.ts @@ -7,18 +7,18 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { if (take >= 50) return res.badRequest("take can't be more than 50"); - let images = await prisma.image.findMany({ + let files = await prisma.file.findMany({ take, where: { userId: user.id, }, orderBy: { - created_at: 'desc', + createdAt: 'desc', }, select: { - created_at: true, - expires_at: true, - file: true, + createdAt: true, + expiresAt: true, + name: true, mimetype: true, id: true, views: true, @@ -26,16 +26,16 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { }, }); - for (let i = 0; i !== images.length; ++i) { - (images[i] as unknown as { url: string }).url = `${ + for (let i = 0; i !== files.length; ++i) { + (files[i] as unknown as { url: string }).url = `${ config.uploader.route === '/' ? '/' : `${config.uploader.route}/` - }${images[i].file}`; + }${files[i].name}`; } if (req.query.filter && req.query.filter === 'media') - images = images.filter((x) => /^(video|audio|image)/.test(x.mimetype)); + files = files.filter((x) => /^(video|audio|image)/.test(x.mimetype)); - return res.json(images); + return res.json(files); } export default withZipline(handler, { diff --git a/src/pages/api/user/urls.ts b/src/pages/api/user/urls.ts index bb9a3443..ad72f25b 100644 --- a/src/pages/api/user/urls.ts +++ b/src/pages/api/user/urls.ts @@ -22,10 +22,10 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) { userId: user.id, }, orderBy: { - created_at: 'desc', + createdAt: 'desc', }, select: { - created_at: true, + createdAt: true, id: true, destination: true, vanity: true, diff --git a/src/pages/auth/register.tsx b/src/pages/auth/register.tsx index f123552f..1c617e96 100644 --- a/src/pages/auth/register.tsx +++ b/src/pages/auth/register.tsx @@ -178,7 +178,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { if (!invite) return { notFound: true }; if (invite.used) return { notFound: true }; - if (invite.expires_at && invite.expires_at < new Date()) { + if (invite.expiresAt && invite.expiresAt < new Date()) { logger.debug(`restricting access to ${JSON.stringify(invite)} as it has expired`); return { notFound: true }; diff --git a/src/pages/code/[id].tsx b/src/pages/code/[id].tsx index 3f1462f7..e4cbc99e 100644 --- a/src/pages/code/[id].tsx +++ b/src/pages/code/[id].tsx @@ -86,9 +86,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => { notFound: true, }; - const file = await prisma.image.findFirst({ + const file = await prisma.file.findFirst({ where: { - file: context.params.id as string, + name: context.params.id as string, }, }); if (!file) return { notFound: true }; @@ -107,9 +107,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => { let renderType; - if (file.file.endsWith('.md')) { + if (file.name.endsWith('.md')) { renderType = 'markdown'; - } else if (file.file.endsWith('.tex')) { + } else if (file.name.endsWith('.tex')) { renderType = 'tex'; } else { renderType = null; @@ -120,7 +120,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { code: await streamToString(data), id: context.params.id as string, title: config.website.title, - render: file.file.endsWith('.md') || file.file.endsWith('.tex'), + render: file.name.endsWith('.md') || file.name.endsWith('.tex'), renderType, }, }; diff --git a/src/pages/view/[id].tsx b/src/pages/view/[id].tsx index d02bc703..3b569916 100644 --- a/src/pages/view/[id].tsx +++ b/src/pages/view/[id].tsx @@ -1,5 +1,5 @@ import { Box, Button, Modal, PasswordInput } from '@mantine/core'; -import type { Image } from '@prisma/client'; +import type { File } from '@prisma/client'; import Link from 'components/Link'; import exts from 'lib/exts'; import prisma from 'lib/prisma'; @@ -11,17 +11,17 @@ import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; export default function EmbeddedFile({ - image, + file, user, pass, prismRender, }: { - image: Image; + file: File; user: UserExtended; pass: boolean; prismRender: boolean; }) { - const dataURL = (route: string) => `${route}/${image.file}`; + const dataURL = (route: string) => `${route}/${file.name}`; const router = useRouter(); const [opened, setOpened] = useState(pass); @@ -29,15 +29,15 @@ export default function EmbeddedFile({ const [error, setError] = useState(''); // reapply date from workaround - image.created_at = new Date(image ? image.created_at : 0); + file.createdAt = new Date(file ? file.createdAt : 0); const check = async () => { - const res = await fetch(`/api/auth/image?id=${image.id}&password=${password}`); + const res = await fetch(`/api/auth/image?id=${file.id}&password=${password}`); if (res.ok) { setError(''); - if (prismRender) return router.push(`/code/${image.file}?password=${password}`); - updateImage(`/api/auth/image?id=${image.id}&password=${password}`); + if (prismRender) return router.push(`/code/${file.name}?password=${password}`); + updateImage(`/api/auth/image?id=${file.id}&password=${password}`); setOpened(false); } else { setError('Invalid password'); @@ -73,53 +73,53 @@ export default function EmbeddedFile({ return ( <> - {user.embed.title && image.embed && ( - + {user.embed.title && file.embed && ( + )} - {user.embed.description && image.embed && ( + {user.embed.description && file.embed && ( )} - {user.embed.siteName && image.embed && ( - + {user.embed.siteName && file.embed && ( + )} - {user.embed.color && image.embed && ( - + {user.embed.color && file.embed && ( + )} - {image.mimetype.startsWith('image') && ( + {file.mimetype.startsWith('image') && ( <> - + )} - {image.mimetype.startsWith('video') && ( + {file.mimetype.startsWith('video') && ( <> - + - - + + - - - - - + + + + + )} - {!image.mimetype.startsWith('video') && !image.mimetype.startsWith('image') && ( - + {!file.mimetype.startsWith('video') && !file.mimetype.startsWith('image') && ( + )} - {image.file} + {file.name} - {image.mimetype.startsWith('image') && ( + {file.mimetype.startsWith('image') && ( {dataURL('/r')} )} - {image.mimetype.startsWith('video') && ( + {file.mimetype.startsWith('video') && (