diff --git a/.gitignore b/.gitignore index 20682d0..39540d4 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,7 @@ package.lock.json # vercel .vercel -# draconic +# void .vscode/ .idea/ config.toml diff --git a/package.json b/package.json index 1c70240..a917c8d 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "draconic", + "name": "void", "version": "0.2.2", "private": true, "engines": { diff --git a/prisma/migrations/20211001063325_void/migration.sql b/prisma/migrations/20211001063325_void/migration.sql new file mode 100644 index 0000000..b539189 --- /dev/null +++ b/prisma/migrations/20211001063325_void/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "User" ALTER COLUMN "embedSiteName" SET DEFAULT E'Void'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 00ca538..1bac1d2 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -14,7 +14,7 @@ model User { token String @unique isAdmin Boolean @default(false) useEmbed Boolean? @default(false) - embedSiteName String? @default("Draconic") + embedSiteName String? @default("Void") embedTitle String? embedColor String @default("#B794F4") embedDesc String? diff --git a/public/banner.png b/public/banner.png index 737b964..18b39d9 100644 Binary files a/public/banner.png and b/public/banner.png differ diff --git a/public/favicon.ico b/public/favicon.ico index 4e5f80c..47602af 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/logo.png b/public/logo.png index 746774f..e6ab6cf 100644 Binary files a/public/logo.png and b/public/logo.png differ diff --git a/public/rounded.png b/public/rounded.png deleted file mode 100644 index 368be9c..0000000 Binary files a/public/rounded.png and /dev/null differ diff --git a/readme.md b/readme.md index 7c05bcc..d8e97db 100644 --- a/readme.md +++ b/readme.md @@ -1,12 +1,12 @@
- + A self-hosted file hosting service based on Zipline with many features. -![Build stable](https://img.shields.io/github/workflow/status/AlphaNecron/Draconic/CI:%20Build/v0?color=%2368D391&label=stable&logo=github&style=for-the-badge) -![Build stable](https://img.shields.io/github/workflow/status/AlphaNecron/Draconic/CI:%20Build/dev?color=%2368D391&label=dev&logo=github&style=for-the-badge) -![Stars](https://img.shields.io/github/stars/AlphaNecron/Draconic?color=%23B794F4&logo=github&style=for-the-badge) -![Version](https://img.shields.io/github/package-json/v/AlphaNecron/Draconic/v0?color=%23B794F4&label=latest&logo=react&logoColor=ffffff&style=for-the-badge) -![Last commit](https://img.shields.io/github/last-commit/AlphaNecron/Draconic/dev?color=%234FD1C5&logo=github&style=for-the-badge) +![Build stable](https://img.shields.io/github/workflow/status/AlphaNecron/Void/CI:%20Build/v0?color=%2368D391&label=stable&logo=github&style=for-the-badge) +![Build stable](https://img.shields.io/github/workflow/status/AlphaNecron/Void/CI:%20Build/dev?color=%2368D391&label=dev&logo=github&style=for-the-badge) +![Stars](https://img.shields.io/github/stars/AlphaNecron/Void?color=%23B794F4&logo=github&style=for-the-badge) +![Version](https://img.shields.io/github/package-json/v/AlphaNecron/Void/v0?color=%23B794F4&label=latest&logo=react&logoColor=ffffff&style=for-the-badge) +![Last commit](https://img.shields.io/github/last-commit/AlphaNecron/Void/dev?color=%234FD1C5&logo=github&style=for-the-badge)
### Requirements @@ -16,8 +16,8 @@ A self-hosted file hosting service based on Zipline with many features. ### Installation / Deployment ```sh - git clone https://github.com/AlphaNecron/Draconic.git - cd Draconic + git clone https://github.com/AlphaNecron/Void.git + cd Void yarn install # or npm install cp config.example.toml config.toml nano config.toml # edit the config file @@ -50,8 +50,8 @@ A self-hosted file hosting service based on Zipline with many features. [core] secure = false # Whether to use https or not secret = 'supersecretpassphrase' # The secret used to sign cookie - host = '0.0.0.0' # The host Draconic should run on - port = 3000 # The port Draconic should run on + host = '0.0.0.0' # The host Void should run on + port = 3000 # The port Void should run on database_url = 'postgres://username:password@localhost:5432/db_name' # PostgreSQL database url [bot] diff --git a/server/index.js b/server/index.js index a9c7959..6625b95 100644 --- a/server/index.js +++ b/server/index.js @@ -11,7 +11,7 @@ const mimes = require('../src/lib/mimetype'); const deployDb = require('../scripts/deployDb'); const { join } = require('path'); -info('SERVER', 'Starting Draconic server'); +info('SERVER', 'Starting Void server'); const dev = process.env.NODE_ENV === 'development'; diff --git a/src/components/ShareXDialog.tsx b/src/components/ShareXDialog.tsx index d448427..d36d862 100644 --- a/src/components/ShareXDialog.tsx +++ b/src/components/ShareXDialog.tsx @@ -4,7 +4,7 @@ import { Download, X } from 'react-feather'; export default function ShareXDialog({ open, onClose, token }) { const ref = React.useRef(); - const [name, setName] = useState('Draconic'); + const [name, setName] = useState('Void'); const [generator, setGenerator] = useState('random'); const [preserveFileName, setPreserveFileName] = useState(false); const generateConfig = shortener => { @@ -64,7 +64,7 @@ export default function ShareXDialog({ open, onClose, token }) { setName(n.target.value)} - placeholder='Draconic' + placeholder='Void' size='sm' /> URL generator diff --git a/src/components/pages/Upload.tsx b/src/components/pages/Upload.tsx index aea9152..66cb2d6 100644 --- a/src/components/pages/Upload.tsx +++ b/src/components/pages/Upload.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Checkbox, Flex, Heading, HStack, Select, Text, useColorModeValue, useToast, VStack } from '@chakra-ui/react'; +import { Button, Center, Checkbox, Heading, HStack, Select, Text, useColorModeValue, useToast, VStack } from '@chakra-ui/react'; import copy from 'copy-to-clipboard'; import { useStoreSelector } from 'lib/redux/store'; import React, { useState } from 'react'; @@ -55,48 +55,42 @@ export default function Upload() { const bg = useColorModeValue('gray.100', 'gray.700'); const shadow = useColorModeValue('outline', 'dark-lg'); return ( - - + - - Upload a file - - - setPreserve(p.target.checked)}>Preserve filename - - - - - - + shadow={shadow}> + Upload a file + + + setPreserve(p.target.checked)}>Preserve filename + + + + + ); } \ No newline at end of file diff --git a/src/lib/middleware/withDraconic.ts b/src/lib/middleware/withVoid.ts similarity index 96% rename from src/lib/middleware/withDraconic.ts rename to src/lib/middleware/withVoid.ts index 3b3714d..d0e0006 100644 --- a/src/lib/middleware/withDraconic.ts +++ b/src/lib/middleware/withVoid.ts @@ -40,7 +40,7 @@ export type NextApiRes = NextApiResponse & { setCookie: (name: string, value: unknown, options: CookieSerializeOptions) => void; } -export const withDraconic = (handler: (req: NextApiRequest, res: NextApiResponse) => unknown) => (req: NextApiReq, res: NextApiRes) => { +export const withVoid = (handler: (req: NextApiRequest, res: NextApiResponse) => unknown) => (req: NextApiReq, res: NextApiRes) => { res.error = (message: string) => { res.setHeader('Content-Type', 'application/json'); res.status(400); diff --git a/src/pages/[...id].tsx b/src/pages/[...id].tsx index e767aaa..f65df20 100644 --- a/src/pages/[...id].tsx +++ b/src/pages/[...id].tsx @@ -17,24 +17,15 @@ export default function Embed({ file, embed, username, content = undefined, misc a.href = misc.src; a.click(); }; - const replace = text => { - const time = new Date(file.uploadedAt); - return (text ?? '').replace(/{size}/ig, misc.size) - .replace(/{filename}/ig, file.fileName) - .replace(/{orig}/ig, file.origFileName) - .replace(/{date}/ig, time.toLocaleDateString()) - .replace(/{time}/ig, time.toLocaleTimeString()) - .replace(/{author}/ig, username); - }; return ( <> <> {embed.enabled && ( <> - - - + + + )} @@ -58,11 +49,10 @@ export default function Embed({ file, embed, username, content = undefined, misc Uploaded by {username} -
+
{ embedDesc: true } }); + const embed = { + enabled, + siteName, + title, + color, + desc + }; const ext = file.fileName.split('.').pop(); const type = file.mimetype.split('/').shift(); const src = `${config.uploader.raw_route}/${file.fileName}`; const url = `http${config.core.secure ? 's' : ''}://${context.req.headers.host}/${config.uploader.raw_route}`; const isCode = Object.keys(languages).some(name => languages[name] === ext); + const replace = size => { + const time = new Date(file.uploadedAt); + const replace = text => { + return (text ?? '').replace(/{size}/ig, size) + .replace(/{filename}/ig, file.fileName) + .replace(/{orig}/ig, file.origFileName) + .replace(/{date}/ig, time.toLocaleDateString()) + .replace(/{time}/ig, time.toLocaleTimeString()) + .replace(/{author}/ig, username); + }; + ['siteName', 'title', 'desc'].forEach(prop => embed[prop] = replace(embed[prop])); + }; if (file.mimetype.startsWith('text') || isCode) { const res = await fetch(`${url}/${file.fileName}`); if (!res.ok) return { notFound: true }; const content = await res.text(); const size = bytesToHr(res.headers.get('content-length')); + replace(size); + delete file.uploadedAt; return { props: { file, - embed: { - enabled, - siteName, - title, - color, - desc - }, + embed, username, misc: { ext, type, - language: isCode ? ext : 'text', - size + language: isCode ? ext : 'text' }, content } }; }; const size = bytesToHr((await fetch(`${url}/${file.fileName}`)).headers.get('content-length')); + replace(size); + delete file.uploadedAt; return { props: { file, - embed: { - enabled, - siteName, - title, - color, - desc - }, + embed, username, misc: { ext, type, - src, - size + src } } }; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 7ab1b0e..78a1204 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -4,7 +4,7 @@ import Head from 'next/head'; import React from 'react'; import { Provider } from 'react-redux'; -export default function Draconic({ Component, pageProps }) { +export default function Void({ Component, pageProps }) { const store = useStore(); return ( diff --git a/src/pages/_error.tsx b/src/pages/_error.tsx new file mode 100644 index 0000000..01ba845 --- /dev/null +++ b/src/pages/_error.tsx @@ -0,0 +1,50 @@ +import { Button, Center, Heading, VStack } from '@chakra-ui/react'; +import React from 'react'; +import Link from 'next/link'; +import { ArrowLeftCircle } from 'react-feather'; + +export default function Error({ code }) { + const errors = { + '400': 'Bad Request', + '401': 'Unauthorized', + '402': 'Payment Required', + '403': 'Forbidden', + '404': 'Not Found', + '405': 'Method Not Allowed', + '406': 'Not Acceptable', + '407': 'Proxy Authentication Required', + '408': 'Request Timeout', + '409': 'Conflict', + '410': 'Gone', + '411': 'Length Required', + '412': 'Precondition Required', + '413': 'Request Entry Too Large', + '414': 'Request-URI Too Long', + '415': 'Unsupported Media Type', + '416': 'Requested Range Not Satisfiable', + '417': 'Expectation Failed', + '418': 'I\'m a teapot', + '429': 'Too Many Requests', + '500': 'Internal Server Error', + '501': 'Not Implemented', + '502': 'Bad Gateway', + '503': 'Service Unavailable', + '504': 'Gateway Timeout', + '505': 'HTTP Version Not Supported' + }; + return ( +
+ + {code}: {errors[String(code)]} + + + + +
+ ); +} + +Error.getInitialProps = ({ res, err }) => { + const code = res ? res.statusCode : err ? err.statusCode : 404; + return { code }; +}; \ No newline at end of file diff --git a/src/pages/api/auth/login.ts b/src/pages/api/auth/login.ts index 796eda9..caa6578 100644 --- a/src/pages/api/auth/login.ts +++ b/src/pages/api/auth/login.ts @@ -1,7 +1,7 @@ import { info } from 'lib/logger'; import prisma from 'lib/prisma'; import { checkPassword, createToken, hashPassword } from 'lib/utils'; -import { NextApiReq, NextApiRes, withDraconic } from 'middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'middleware/withVoid'; async function handler(req: NextApiReq, res: NextApiRes) { if (req.method !== 'POST') return res.status(405).end(); @@ -11,12 +11,12 @@ async function handler(req: NextApiReq, res: NextApiRes) { const user = await prisma.user.create({ data: { username: 'admin', - password: await hashPassword('draconicuser'), + password: await hashPassword('voiduser'), token: createToken(), isAdmin: true } }); - info('SEED', `Created default user with username "${user.username}" and password "draconicuser"`); + info('SEED', `Created default user with username "${user.username}" and password "voiduser"`); } const user = await prisma.user.findFirst({ where: { @@ -31,4 +31,4 @@ async function handler(req: NextApiReq, res: NextApiRes) { return res.json({ success: true }); } -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/api/auth/logout.ts b/src/pages/api/auth/logout.ts index 03ee58c..c2b6d7e 100644 --- a/src/pages/api/auth/logout.ts +++ b/src/pages/api/auth/logout.ts @@ -1,5 +1,5 @@ import { info } from 'lib/logger'; -import { NextApiReq, NextApiRes, withDraconic } from 'middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'middleware/withVoid'; async function handler(req: NextApiReq, res: NextApiRes) { const user = await req.user(); @@ -9,4 +9,4 @@ async function handler(req: NextApiReq, res: NextApiRes) { return res.json({ success: true }); } -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/api/delete.ts b/src/pages/api/delete.ts index 89b06ae..16fa110 100644 --- a/src/pages/api/delete.ts +++ b/src/pages/api/delete.ts @@ -2,7 +2,7 @@ import { rm } from 'fs/promises'; import { join } from 'path'; import cfg from '../../lib/config'; import { info } from '../../lib/logger'; -import { NextApiReq, NextApiRes, withDraconic } from '../../lib/middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from '../../lib/middleware/withVoid'; import prisma from '../../lib/prisma'; async function handler(req: NextApiReq, res: NextApiRes) { @@ -47,4 +47,4 @@ export const config = { }, }; -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/api/shorten.ts b/src/pages/api/shorten.ts index b277e51..2ee59ea 100644 --- a/src/pages/api/shorten.ts +++ b/src/pages/api/shorten.ts @@ -1,7 +1,7 @@ import { default as cfg, default as config } from 'lib/config'; import generate from 'lib/generators'; import { info } from 'lib/logger'; -import { NextApiReq, NextApiRes, withDraconic } from 'lib/middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'lib/middleware/withVoid'; import prisma from 'lib/prisma'; async function handler(req: NextApiReq, res: NextApiRes) { @@ -38,4 +38,4 @@ async function handler(req: NextApiReq, res: NextApiRes) { }); } -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/api/stats.ts b/src/pages/api/stats.ts index 24c5ee0..b4a15b4 100644 --- a/src/pages/api/stats.ts +++ b/src/pages/api/stats.ts @@ -1,7 +1,7 @@ import config from 'lib/config'; import prisma from 'lib/prisma'; import { bytesToHr, sizeOfDir } from 'lib/utils'; -import { NextApiReq, NextApiRes, withDraconic } from 'middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'middleware/withVoid'; import { join } from 'path'; async function handler(req: NextApiReq, res: NextApiRes) { @@ -69,4 +69,4 @@ async function handler(req: NextApiReq, res: NextApiRes) { }); } -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/api/upload.ts b/src/pages/api/upload.ts index 9d97648..6c2f078 100644 --- a/src/pages/api/upload.ts +++ b/src/pages/api/upload.ts @@ -2,7 +2,7 @@ import { writeFile } from 'fs/promises'; import cfg from 'lib/config'; import generate, { emoji, zws } from 'lib/generators'; import { info } from 'lib/logger'; -import { NextApiReq, NextApiRes, withDraconic } from 'lib/middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'lib/middleware/withVoid'; import mimetypes from 'lib/mimetype'; import prisma from 'lib/prisma'; import multer from 'multer'; @@ -82,7 +82,7 @@ function run(middleware: any) { export default async function handlers(req, res) { await run(uploader.single('file'))(req, res); - return withDraconic(handler)(req, res); + return withVoid(handler)(req, res); }; export const config = { diff --git a/src/pages/api/user/files.ts b/src/pages/api/user/files.ts index 21899ce..bdd028e 100644 --- a/src/pages/api/user/files.ts +++ b/src/pages/api/user/files.ts @@ -1,6 +1,6 @@ import config from 'lib/config'; import prisma from 'lib/prisma'; -import { NextApiReq, NextApiRes, withDraconic } from 'middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'middleware/withVoid'; async function handler(req: NextApiReq, res: NextApiRes) { const user = await req.user(); @@ -35,4 +35,4 @@ async function handler(req: NextApiReq, res: NextApiRes) { } } -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/api/user/index.ts b/src/pages/api/user/index.ts index 434e220..f00c3b3 100644 --- a/src/pages/api/user/index.ts +++ b/src/pages/api/user/index.ts @@ -1,7 +1,7 @@ import { info } from 'lib/logger'; import prisma from 'lib/prisma'; import { hashPassword } from 'lib/utils'; -import { NextApiReq, NextApiRes, withDraconic } from 'middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'middleware/withVoid'; async function handler(req: NextApiReq, res: NextApiRes) { const user = await req.user(); @@ -74,4 +74,4 @@ async function handler(req: NextApiReq, res: NextApiRes) { } } -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/api/user/token.ts b/src/pages/api/user/token.ts index 9ba3b1c..90874b7 100644 --- a/src/pages/api/user/token.ts +++ b/src/pages/api/user/token.ts @@ -1,7 +1,7 @@ import { info } from 'lib/logger'; import prisma from 'lib/prisma'; import { createToken } from 'lib/utils'; -import { NextApiReq, NextApiRes, withDraconic } from 'middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'middleware/withVoid'; async function handler(req: NextApiReq, res: NextApiRes) { const user = await req.user(); @@ -23,4 +23,4 @@ async function handler(req: NextApiReq, res: NextApiRes) { } } -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/api/user/urls.ts b/src/pages/api/user/urls.ts index 9429737..9a13a62 100644 --- a/src/pages/api/user/urls.ts +++ b/src/pages/api/user/urls.ts @@ -1,7 +1,7 @@ import config from 'lib/config'; import { info } from 'lib/logger'; import prisma from 'lib/prisma'; -import { NextApiReq, NextApiRes, withDraconic } from 'middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'middleware/withVoid'; async function handler(req: NextApiReq, res: NextApiRes) { const user = await req.user(); @@ -37,4 +37,4 @@ async function handler(req: NextApiReq, res: NextApiRes) { } } -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/api/users.ts b/src/pages/api/users.ts index bc53953..69418a3 100644 --- a/src/pages/api/users.ts +++ b/src/pages/api/users.ts @@ -1,7 +1,7 @@ import { info } from 'lib/logger'; import prisma from 'lib/prisma'; import { createToken, hashPassword } from 'lib/utils'; -import { NextApiReq, NextApiRes, withDraconic } from 'middleware/withDraconic'; +import { NextApiReq, NextApiRes, withVoid } from 'middleware/withVoid'; async function handler(req: NextApiReq, res: NextApiRes) { const user = await req.user(); @@ -62,4 +62,4 @@ async function handler(req: NextApiReq, res: NextApiRes) { } } -export default withDraconic(handler); \ No newline at end of file +export default withVoid(handler); \ No newline at end of file diff --git a/src/pages/auth/login.tsx b/src/pages/auth/login.tsx index c702c8e..ee2364c 100644 --- a/src/pages/auth/login.tsx +++ b/src/pages/auth/login.tsx @@ -67,7 +67,7 @@ export default function Login() { {props => (
- Draconic + Void {({ field, form }) => ( diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 2ef5408..70e7d31 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -9,7 +9,7 @@ export default function Index() { }, [router]); return ( - + ); diff --git a/tsconfig.json b/tsconfig.json index 0c421d6..b4945bb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -36,7 +36,7 @@ }, "include": [ "next-env.d.ts", - "draconic-env.d.ts", + "void-env.d.ts", "**/*.ts", "**/*.tsx", "twilight/**/*.ts" diff --git a/draconic-env.d.ts b/void-env.d.ts similarity index 100% rename from draconic-env.d.ts rename to void-env.d.ts