From d2dd7f6b0c709a08b804fb1a593dd1f0f0527a89 Mon Sep 17 00:00:00 2001 From: dicedtomatoreal Date: Sat, 24 Oct 2020 15:07:58 -0700 Subject: [PATCH] log --- .github/workflows/node.js.yml | 2 +- package.json | 5 +++- src/controllers/ImagesController.ts | 7 ++---- src/controllers/RootController.ts | 13 +++++++--- src/controllers/URLSController.ts | 5 +++- src/controllers/UserController.ts | 37 +++++++++++++++++++++++------ src/index.ts | 27 ++++++++++++++++----- src/lib/ConsoleFormatter.ts | 8 ------- src/lib/Util.ts | 4 +--- src/lib/logger/Console.ts | 6 ++--- src/lib/logger/Formatter.ts | 31 ++++++++++++++++++------ src/pages/urls.tsx | 20 +++++++++++----- 12 files changed, 114 insertions(+), 51 deletions(-) delete mode 100644 src/lib/ConsoleFormatter.ts diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index d6391ecf..2fbe6a8d 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: - node-version: [14.x] + node-version: [15.x] steps: - uses: actions/checkout@v1 diff --git a/package.json b/package.json index e50c5af8..83336e4e 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "fastify-multipart": "^3.2.0", "fastify-static": "^3.2.1", "fastify-typeorm-plugin": "^2.1.2", + "figlet": "^1.5.0", "next": "^9.5.4", "pg": "^8.4.1", "react": "^16.13.1", @@ -35,8 +36,10 @@ "format": "prettier --write .", "lint": "eslint .", "dev": "ts-node src", + "dev:verbose": "VERBOSE=true ts-node src", "build": "next build && tsc -p .", - "start": "NODE_ENV=production node dist" + "start": "NODE_ENV=production node dist", + "start:verbose": "NODE_ENV=production VERBOSE=true node dist" }, "devDependencies": { "@types/bcrypt": "^3.0.0", diff --git a/src/controllers/ImagesController.ts b/src/controllers/ImagesController.ts index 7cd9886d..69f0b7af 100644 --- a/src/controllers/ImagesController.ts +++ b/src/controllers/ImagesController.ts @@ -9,12 +9,9 @@ import { import { Repository } from 'typeorm'; import { Image } from '../entities/Image'; import { LoginError } from '../lib/api/APIErrors'; -import { Configuration } from '../lib/Config'; +import { Console } from '../lib/logger'; import { readBaseCookie } from '../lib/Util'; -const config = Configuration.readConfig(); -if (!config) process.exit(0); - @Controller('/api/images') export class ImagesController { @Inject(FastifyInstanceToken) @@ -54,7 +51,7 @@ export class ImagesController { this.images.delete({ id: req.params.id, }); - + Console.logger(Image).info(`image ${image.id} was deleted`); return reply.send(image); } diff --git a/src/controllers/RootController.ts b/src/controllers/RootController.ts index 785c7b11..61dcf98f 100644 --- a/src/controllers/RootController.ts +++ b/src/controllers/RootController.ts @@ -17,11 +17,10 @@ import { User } from '../entities/User'; import { AuthError } from '../lib/api/APIErrors'; import { Configuration } from '../lib/Config'; import { createRandomId } from '../lib/Util'; +import { Console } from '../lib/logger'; const pump = promisify(pipeline); - const config = Configuration.readConfig(); -if (!config) process.exit(0); @Controller('/api') export class RootController { @@ -108,9 +107,17 @@ export class RootController { config.uploader.original ? data.filename : `${fileName}.${ext}` ); - this.images.save(new Image(fileName, ext, user.id)); + Console.logger(Image).verbose(`attempting to save ${fileName} to db`); + const image = await this.images.save(new Image(fileName, ext, user.id)); + Console.logger(Image).verbose(`saved image ${image.id} to db`); + Console.logger(Image).verbose(`attempting to save file ${path}`); await pump(data.file, createWriteStream(path)); + Console.logger(Image).verbose(`saved ${path}`); + + Console.logger(Image).info( + `image ${fileName}.${ext} was uploaded by ${user.username} (${user.id})` + ); reply.send( `${req.protocol}://${req.hostname}${config.uploader.route}/${fileName}.${ext}` ); diff --git a/src/controllers/URLSController.ts b/src/controllers/URLSController.ts index c02ce712..34022088 100644 --- a/src/controllers/URLSController.ts +++ b/src/controllers/URLSController.ts @@ -12,10 +12,10 @@ import { URL } from '../entities/URL'; import { User } from '../entities/User'; import { LoginError } from '../lib/api/APIErrors'; import { Configuration } from '../lib/Config'; +import { Console } from '../lib/logger'; import { createRandomId, readBaseCookie } from '../lib/Util'; const config = Configuration.readConfig(); -if (!config) process.exit(0); @Controller('/api/urls') export class URLSController { @@ -54,10 +54,13 @@ export class URLSController { if (!url) throw new Error('No url'); + Console.logger(URL).verbose(`attempting to delete url ${url.id}`); this.urls.delete({ id: req.params.id, }); + Console.logger(URL).verbose(`deleted url ${url.id}`); + Console.logger(URL).info(`url ${url.id} was deleted`); return reply.send(url); } diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 4669e413..e5e770b2 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -16,6 +16,7 @@ import { LoginError, UserExistsError, } from '../lib/api/APIErrors'; +import { Console } from '../lib/logger'; import { checkPassword, createBaseCookie, @@ -30,6 +31,7 @@ export class UserController { private instance!: FastifyInstance; private users: Repository = this.instance.orm.getRepository(User); + private logger: Console = Console.logger(User); @GET('/login-status') async loginStatus(req: FastifyRequest, reply: FastifyReply) { @@ -65,9 +67,11 @@ export class UserController { }); if (!user) throw new UserExistsError('User doesn\'t exist'); + this.logger.verbose(`attempting to save ${user.username} (${user.id})`); user.username = req.body.username; user.password = encryptPassword(req.body.password); - this.users.save(user); + await this.users.save(user); + this.logger.verbose(`saved ${user.username} (${user.id})`); delete user.password; return reply.send(user); @@ -88,14 +92,23 @@ export class UserController { }, }); - if (!user) throw new UserNotFoundError(`User "${req.body.username}" was not found.`); - if (!checkPassword(req.body.password, user.password)) throw new LoginError('Wrong credentials!'); + if (!user) + throw new UserNotFoundError(`User "${req.body.username}" was not found.`); + if (!checkPassword(req.body.password, user.password)) { + this.logger.error( + `${user.username} (${user.id}) tried to login but failed` + ); + throw new LoginError('Wrong credentials!'); + } delete user.password; + this.logger.verbose(`set cookie for ${user.username} (${user.id})`); reply.setCookie('zipline', createBaseCookie(user.id), { path: '/', maxAge: 1036800000, }); + + this.logger.info(`${user.username} (${user.id}) logged in`); return reply.send(user); } @@ -122,8 +135,12 @@ export class UserController { if (!user) throw new UserNotFoundError('User was not found.'); + this.logger.verbose( + `attempting to reset token ${user.username} (${user.id})` + ); user.token = createToken(); - this.users.save(user); + await this.users.save(user); + this.logger.info(`reset token ${user.username} (${user.id})`); return reply.send({ updated: true }); } @@ -144,6 +161,7 @@ export class UserController { if (existing) throw new UserExistsError('User exists already'); try { + this.logger.verbose(`attempting to create ${req.body.username}`); const user = await this.users.save( new User( req.body.username, @@ -152,6 +170,7 @@ export class UserController { req.body.administrator || false ) ); + this.logger.info(`created user ${user.username} (${user.id})`); delete user.password; return reply.send(user); } catch (e) { @@ -163,8 +182,8 @@ export class UserController { async delete( req: FastifyRequest<{ Params: { - id: string - } + id: string; + }; }>, reply: FastifyReply ) { @@ -174,9 +193,13 @@ export class UserController { if (!existing) throw new UserExistsError('User doesnt exist'); try { + this.logger.verbose( + `attempting to delete ${existing.username} (${existing.id})` + ); await this.users.delete({ - id: existing.id + id: existing.id, }); + this.logger.info(`deleted ${existing.username} (${existing.id})`); return reply.send({ ok: true }); } catch (e) { throw new Error(`Could not delete user: ${e.message}`); diff --git a/src/index.ts b/src/index.ts index 176e9075..cb8eeb01 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import next from 'next'; +import { textSync as text } from 'figlet'; import fastify, { FastifyReply, FastifyRequest } from 'fastify'; import fastifyTypeorm from 'fastify-typeorm-plugin'; import fastifyCookies from 'fastify-cookie'; @@ -8,8 +9,7 @@ import fastifyFavicon from 'fastify-favicon'; import { bootstrap } from 'fastify-decorators'; import { Console } from './lib/logger'; import { AddressInfo } from 'net'; -import { ConsoleFormatter } from './lib/ConsoleFormatter'; -import { bold, green, reset } from '@dicedtomato/colors'; +import { magenta, bold, green, reset, blue, red } from '@dicedtomato/colors'; import { Configuration } from './lib/Config'; import { UserController } from './controllers/UserController'; import { RootController } from './controllers/RootController'; @@ -17,19 +17,34 @@ import { join } from 'path'; import { ImagesController } from './controllers/ImagesController'; import { URLSController } from './controllers/URLSController'; import { URL } from './entities/URL'; +const dev = process.env.NODE_ENV !== 'production'; -Console.setFormatter(new ConsoleFormatter()); +console.log(` +${magenta(text('Zipline'))} +GitHub : ${blue('https://github.com/ZiplineProject/zipline')} +Issues : ${blue('https://github.com/ZiplineProject/zipline/issues')} +Docs : ${blue('https://zipline.diced.wtf/')} +Mode : ${bold(dev ? red('dev') : green('production'))} +Verbose : ${bold(process.env.VERBOSE ? red('yes') : green('no'))} +`); + +Console.logger(Configuration).verbose('searching for config...'); const config = Configuration.readConfig(); -if (!config) process.exit(0); +if (!config) { + Console.logger(Configuration).error( + `could not find a Zipline.toml file in ${process.cwd()}` + ); + process.exit(0); +} const server = fastify({}); -const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev, quiet: dev }); const handle = app.getRequestHandler(); -Console.logger('Next').info('Preparing app'); +Console.logger('Next').info('Preparing app...'); app.prepare(); +Console.logger('Next').verbose('Prepared app'); if (dev) server.get('/_next/*', async (req, reply) => { diff --git a/src/lib/ConsoleFormatter.ts b/src/lib/ConsoleFormatter.ts deleted file mode 100644 index 9d4b2c87..00000000 --- a/src/lib/ConsoleFormatter.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { bold, magenta, reset } from '@dicedtomato/colors'; -import { Formatter } from './logger'; - -export class ConsoleFormatter implements Formatter { - format(message: string, origin: string): string { - return `${bold(magenta(origin))} ${bold('>')} ${reset(message)}`; - } -} diff --git a/src/lib/Util.ts b/src/lib/Util.ts index 205dbc00..0aa6c284 100644 --- a/src/lib/Util.ts +++ b/src/lib/Util.ts @@ -1,10 +1,8 @@ import aes from 'crypto-js/aes'; import { compareSync, hashSync } from 'bcrypt'; import { Configuration } from './Config'; -import { Repository } from 'typeorm'; const config = Configuration.readConfig(); -if (!config) process.exit(0); export function createRandomId( length: number, @@ -36,4 +34,4 @@ export function createBaseCookie(id: number) { export function readBaseCookie(data) { return Buffer.from(data, 'base64').toString(); -} \ No newline at end of file +} diff --git a/src/lib/logger/Console.ts b/src/lib/logger/Console.ts index 1e570e41..d7830c33 100644 --- a/src/lib/logger/Console.ts +++ b/src/lib/logger/Console.ts @@ -16,7 +16,7 @@ export enum ConsoleLevel { ERROR, INFO, TRACE, - WARN, + VERBOSE, } export class Console { @@ -42,8 +42,8 @@ export class Console { return this.log(ConsoleLevel.TRACE, message); } - public warn(message: string): string { - return this.log(ConsoleLevel.WARN, message); + public verbose(message: string): string { + if (process.env.VERBOSE) return this.log(ConsoleLevel.VERBOSE, message); } public log(level: ConsoleLevel, message: string): string { diff --git a/src/lib/logger/Formatter.ts b/src/lib/logger/Formatter.ts index 925192ef..936f6def 100644 --- a/src/lib/logger/Formatter.ts +++ b/src/lib/logger/Formatter.ts @@ -1,5 +1,12 @@ -import { ConsoleLevel } from './Console'; -import { brightGreen, blue } from '@dicedtomato/colors'; +import { ConsoleLevel } from '.'; +import { + blue, + red, + reset, + white, + yellow +} from '@dicedtomato/colors'; + export interface Formatter { format( @@ -11,14 +18,24 @@ export interface Formatter { } export class DefaultFormatter implements Formatter { - public format( + formatLevel(level: ConsoleLevel) { + return { + 0: yellow('debug') + ':', + 1: red('error') + ':', + 2: blue('info') + ':', + 3: white('trace') + ':', + 4: yellow('verbose') + ':', + }[level]; + } + + format( message: string, origin: string, level: ConsoleLevel, time: Date ): string { - return `[${time.toLocaleString()}] ${brightGreen(origin)} - ${blue( - ConsoleLevel[level] - )}: ${message}`; + return `[${time.toLocaleString().replace(',', '')}] ${this.formatLevel( + level + )} ${reset(message)}`; } -} +} \ No newline at end of file diff --git a/src/pages/urls.tsx b/src/pages/urls.tsx index e40e94f5..da9c9b31 100644 --- a/src/pages/urls.tsx +++ b/src/pages/urls.tsx @@ -40,7 +40,6 @@ export default function Urls({ config }: { config: ConfigUploader }) { if (typeof window === 'undefined') return ; else { - const doUrls = async () => { const d = await (await fetch('/api/urls')).json(); if (!d.error) { @@ -49,10 +48,14 @@ export default function Urls({ config }: { config: ConfigUploader }) { } }; - useEffect(() => { (async () => doUrls())(); }, []); + useEffect(() => { + (async () => doUrls())(); + }, []); const deleteUrl = async (u: URLEntity) => { - const d = await (await fetch('/api/urls/' + u.id, { method: 'DELETE' })).json(); + const d = await ( + await fetch('/api/urls/' + u.id, { method: 'DELETE' }) + ).json(); if (!d.error) doUrls(); }; @@ -88,10 +91,15 @@ export default function Urls({ config }: { config: ConfigUploader }) { action={
- copy(url.toString())} /> + copy(url.toString())} + /> - - deleteUrl(u)} /> + deleteUrl(u)} + > +
}