diff --git a/package.json b/package.json index 23ef390..47c1456 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zip3", - "version": "3.2.0", + "version": "3.2.1", "scripts": { "prepare": "husky install", "dev": "NODE_ENV=development node server", @@ -20,7 +20,7 @@ "@material-ui/data-grid": "^4.0.0-alpha.32", "@material-ui/icons": "^5.0.0-alpha.37", "@material-ui/styles": "^5.0.0-alpha.35", - "@prisma/client": "^2.30.0", + "@prisma/client": "^2.30.3", "@reduxjs/toolkit": "^1.6.0", "argon2": "^0.28.2", "colorette": "^1.2.2", @@ -29,8 +29,8 @@ "fecha": "^4.2.1", "formik": "^2.2.9", "multer": "^1.4.2", - "next": "11.1.0", - "prisma": "^2.30.0", + "next": "11.1.1", + "prisma": "^2.30.3", "react": "17.0.2", "react-dom": "17.0.2", "react-dropzone": "^11.3.2", diff --git a/prisma/migrations/20210901024501_embed_image/migration.sql b/prisma/migrations/20210901024501_embed_image/migration.sql new file mode 100644 index 0000000..57a7e68 --- /dev/null +++ b/prisma/migrations/20210901024501_embed_image/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Image" ADD COLUMN "embed" BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 44bbafb..5c1db86 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -43,6 +43,7 @@ model Image { created_at DateTime @default(now()) views Int @default(0) favorite Boolean @default(false) + embed Boolean @default(false) invisible InvisibleImage? user User @relation(fields: [userId], references: [id]) userId Int diff --git a/server/index.js b/server/index.js index f521949..980e533 100644 --- a/server/index.js +++ b/server/index.js @@ -60,14 +60,16 @@ function shouldUseYarn() { const prisma = new PrismaClient(); const srv = createServer(async (req, res) => { - if (req.url.startsWith(config.uploader.route)) { + if (req.url.startsWith('/raw')) { const parts = req.url.split('/'); if (!parts[2] || parts[2] === '') return; let image = await prisma.image.findFirst({ where: { - OR: { file: parts[2] }, - OR: { invisible: { invis: decodeURI(parts[2]) } } + OR: [ + { file: parts[2] }, + { invisible:{ invis: decodeURI(parts[2]) } } + ] }, select: { mimetype: true, diff --git a/server/validateConfig.js b/server/validateConfig.js index f8f2fc7..2ce5e2d 100644 --- a/server/validateConfig.js +++ b/server/validateConfig.js @@ -14,7 +14,6 @@ module.exports = async config => { path('core.port', 'number'), path('core.database_url', 'string'), path('uploader.route', 'string'), - path('uploader.embed_route', 'string'), path('uploader.length', 'number'), path('uploader.directory', 'string'), path('uploader.admin_limit', 'number'), diff --git a/src/lib/readConfig.js b/src/lib/readConfig.js index 8c36773..a47a839 100644 --- a/src/lib/readConfig.js +++ b/src/lib/readConfig.js @@ -11,12 +11,11 @@ const envValues = [ e('PORT', 'number', (c, v) => c.core.port = v), e('DATABASE_URL', 'string', (c, v) => c.core.database_url = v), e('UPLOADER_ROUTE', 'string', (c, v) => c.uploader.route = v), - e('UPLOADER_EMBED_ROUTE', 'string', (c, v) => c.uploader.embed_route = v), e('UPLOADER_LENGTH', 'number', (c, v) => c.uploader.length = v), e('UPLOADER_DIRECTORY', 'string', (c, v) => c.uploader.directory = v), e('UPLOADER_ADMIN_LIMIT', 'number', (c, v) => c.uploader.admin_limit = v), e('UPLOADER_USER_LIMIT', 'number', (c, v) => c.uploader.user_limit = v), - e('UPLOADER_DISABLED_EXTS', 'array', (c, v) => c.uploader.disabled_extentions = v), + e('UPLOADER_DISABLED_EXTS', 'array', (c, v) => v ? c.uploader.disabled_extentions = v : c.uploader.disabled_extentions = [], false), ]; module.exports = () => { @@ -43,7 +42,6 @@ function tryReadEnv() { }, uploader: { route: undefined, - embed_route: undefined, length: undefined, directory: undefined, admin_limit: undefined, @@ -63,10 +61,12 @@ function tryReadEnv() { } envValues[i].fn(config, value); - if (envValue.type === 'number') value = parseToNumber(value); - else if (envValue.type === 'boolean') value = parseToBoolean(value); - else if (envValue.type === 'array') value = parseToArray(value); - envValues[i].fn(config, value); + if (envValue.required) { + if (envValue.type === 'number') value = parseToNumber(value); + else if (envValue.type === 'boolean') value = parseToBoolean(value); + else if (envValue.type === 'array') value = parseToArray(value); + envValues[i].fn(config, value); + } } return config; diff --git a/src/pages/[...id].tsx b/src/pages/[...id].tsx index 8a0f09b..07edb00 100644 --- a/src/pages/[...id].tsx +++ b/src/pages/[...id].tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import Head from 'next/head'; import { GetServerSideProps } from 'next'; import { Box } from '@material-ui/core'; @@ -8,31 +8,47 @@ import prisma from 'lib/prisma'; export default function EmbeddedImage({ image, title, username, color, normal, embed }) { const dataURL = (route: string) => `${route}/${image.file}`; + const updateImage = () => { + const original = new Image; + original.src = dataURL('/raw'); + + const imageEl = document.getElementById('image_content') as HTMLImageElement; + imageEl.width = Math.floor(original.width * Math.min((innerHeight / original.height), (innerWidth / original.width))); + imageEl.height = innerHeight; + }; + + if (typeof window !== 'undefined') window.onresize = () => updateImage(); + + useEffect(() => updateImage(), []); + return ( <> - {title ? ( + {embed && ( <> - - + {title ? ( + <> + + + + ) : ( + + )} + + + + - ) : ( - )} - - - - {image.file} - - {dataURL(normal)}/ + {dataURL('/raw')} ); @@ -41,24 +57,28 @@ export default function EmbeddedImage({ image, title, username, color, normal, e export const getServerSideProps: GetServerSideProps = async (context) => { const id = context.params.id[1]; const route = context.params.id[0]; - if (route !== config.uploader.embed_route.substr(1)) return { + if (route !== config.uploader.route.substring(1)) return { notFound: true }; const image = await prisma.image.findFirst({ where: { - file: id + OR: [ + { file: id }, + { invisible: { invis: id } } + ] }, select: { - file: true, mimetype: true, - userId: true + id: true, + file: true, + invisible: true, + userId: true, + embed: true } }); - if (!image) return { - notFound: true - }; + if (!image) return { notFound: true }; const user = await prisma.user.findFirst({ select: { @@ -74,7 +94,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { if (!image.mimetype.startsWith('image')) return { redirect: { permanent: true, - destination: `${config.uploader.route}/${image.file}`, + destination: `raw/${image.file}`, } }; @@ -85,7 +105,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { color: user.embedColor, username: user.username, normal: config.uploader.route, - embed: config.uploader.embed_route + embed: image.embed } }; }; diff --git a/src/pages/api/upload.ts b/src/pages/api/upload.ts index 161e50f..074f939 100644 --- a/src/pages/api/upload.ts +++ b/src/pages/api/upload.ts @@ -33,7 +33,8 @@ async function handler(req: NextApiReq, res: NextApiRes) { data: { file: `${rand}.${ext}`, mimetype: req.file.mimetype, - userId: user.id + userId: user.id, + embed: !!req.headers.embed } }); @@ -44,7 +45,7 @@ async function handler(req: NextApiReq, res: NextApiRes) { Logger.get('image').info(`User ${user.username} (${user.id}) uploaded an image ${image.file} (${image.id})`); return res.json({ - url: `${zconfig.core.secure ? 'https' : 'http'}://${req.headers.host}${req.headers.embed ? zconfig.uploader.embed_route : zconfig.uploader.route}/${invis ? invis.invis : image.file}` + url: `${zconfig.core.secure ? 'https' : 'http'}://${req.headers.host}${zconfig.uploader.route}/${invis ? invis.invis : image.file}` }); } diff --git a/yarn.lock b/yarn.lock index e50d451..b2984e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -599,22 +599,22 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353" integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q== -"@prisma/client@^2.30.0": - version "2.30.0" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-2.30.0.tgz#b0ed9db67405f619e428577f2d45843104142e00" - integrity sha512-tjJNHVfgyNOwS2F+AkjMMCJGPnXzHuUCrOnAMJyidAu4aNzxbJ8jWwjt96rRMpyrg9Hwen3xqqQ2oA+ikK7nhQ== +"@prisma/client@^2.30.3": + version "2.30.3" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-2.30.3.tgz#49c1015e2cec26a44b20c62eb2fd738cb0bb043b" + integrity sha512-Ey2miZ+Hne12We3rA8XrlPoAF0iuKEhw5IK2nropaelSt0Ju3b2qSz9Qt50a/1Mx3+7yRSu/iSXt8y9TUMl/Yw== dependencies: - "@prisma/engines-version" "2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb" + "@prisma/engines-version" "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20" -"@prisma/engines-version@2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb": - version "2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb.tgz#1360113dc19e1d43d4442e3b638ccfa0e1711943" - integrity sha512-oThNpx7HtJ0eEmnvrWARYcNCs6dqFdAK3Smt2bJVDD6Go4HLuuhjx028osP+rHaFrGOTx7OslLZYtvvFlAXRDA== +"@prisma/engines-version@2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20": + version "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20.tgz#d5ef55c92beeba56e52bba12b703af0bfd30530d" + integrity sha512-/iDRgaoSQC77WN2oDsOM8dn61fykm6tnZUAClY+6p+XJbOEgZ9gy4CKuKTBgrjSGDVjtQ/S2KGcYd3Ring8xaw== -"@prisma/engines@2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb": - version "2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb.tgz#b4d91ff876662b1de83e0cc913149a1c088becc7" - integrity sha512-LPKq88lIbYezvX0OOc1PU42hHdTsSMPJWmK8lusaHK7DaLHyXjDp/551LbsVapypbjW6N3Jx/If6GoMDASSMSw== +"@prisma/engines@2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20": + version "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20.tgz#2df768aa7c9f84acaa1f35c970417822233a9fb1" + integrity sha512-WPnA/IUrxDihrRhdP6+8KAVSwsc0zsh8ioPYsLJjOhzVhwpRbuFH2tJDRIAbc+qFh+BbTIZbeyBYt8fpNXaYQQ== "@reduxjs/toolkit@^1.6.0": version "1.6.0" @@ -4426,12 +4426,12 @@ prepend-http@^1.0.1: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= -prisma@^2.30.0: - version "2.30.0" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-2.30.0.tgz#5b12091c480d538540b898d364b73651d44b4a01" - integrity sha512-2XYpSibcVpMd1JDxYypGDU/JKq0W2f/HI1itdddr4Pfg+q6qxt/ItWKcftv4/lqN6u/BVlQ2gDzXVEjpHeO5kQ== +prisma@^2.30.3: + version "2.30.3" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-2.30.3.tgz#e4a770e1f52151e72c1c5be0aa2e75222a0135c4" + integrity sha512-48qYba2BIyUmXuosBZs0g3kYGrxKvo4VkSHYOuLlDdDirmKyvoY2hCYMUYHSx3f++8ovfgs+MX5KmNlP+iAZrQ== dependencies: - "@prisma/engines" "2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb" + "@prisma/engines" "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20" process-nextick-args@~2.0.0: version "2.0.1"