From 6db8b1cd21ece15a59cea743014e91bbc20eacad Mon Sep 17 00:00:00 2001 From: Alice Gaudon Date: Sun, 14 Jun 2020 18:10:01 +0200 Subject: [PATCH] Add size and owner fields to files --- src/controllers/FileController.ts | 13 ++++++++++--- src/migrations/CreateFilesTable.ts | 2 ++ src/models/FileModel.ts | 9 +++++++++ views/file-manager.njk | 10 ++++++++-- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/controllers/FileController.ts b/src/controllers/FileController.ts index 41b4feb..d1ef990 100644 --- a/src/controllers/FileController.ts +++ b/src/controllers/FileController.ts @@ -1,7 +1,7 @@ import Controller from "wms-core/Controller"; import {REQUIRE_AUTH_MIDDLEWARE} from "wms-core/auth/AuthComponent"; import {Request, Response, Router} from "express"; -import {BadRequestError, NotFoundHttpError, ServerError} from "wms-core/HttpError"; +import {BadRequestError, ForbiddenHttpError, NotFoundHttpError, ServerError} from "wms-core/HttpError"; import FileModel from "../models/FileModel"; import {cryptoRandomDictionary} from "wms-core/Utils"; import config from "config"; @@ -19,10 +19,10 @@ export default class FileController extends Controller { this.get('/files/:page?', this.getFileManager, 'file-manager', REQUIRE_AUTH_MIDDLEWARE); this.get('/files/delete/:slug', this.deleteFile, 'delete-file-frontend', REQUIRE_AUTH_MIDDLEWARE); - this.get('/:slug', this.downloadFile, 'get-file'); this.post('/', this.postFile, 'post-file', REQUIRE_AUTH_MIDDLEWARE); + this.delete('/delete/:slug', this.deleteFile, 'delete-file', REQUIRE_AUTH_MIDDLEWARE); + this.get('/:slug', this.downloadFile, 'get-file'); this.put('/:slug', this.putFile, 'put-file', REQUIRE_AUTH_MIDDLEWARE); - this.delete('/:slug', this.deleteFile, 'delete-file', REQUIRE_AUTH_MIDDLEWARE); } protected async getFileManager(req: Request, res: Response): Promise { @@ -33,6 +33,7 @@ export default class FileController extends Controller { } protected async downloadFile(req: Request, res: Response): Promise { + console.log('heeey'); const file = await FileModel.getBySlug(req.params.slug); if (!file || file.shouldBeDeleted()) throw new NotFoundHttpError('File', req.url); @@ -71,10 +72,12 @@ export default class FileController extends Controller { else if (req.body.expire_after_days !== undefined) ttl = parseInt(req.body.expire_after_days) * 24 * 3600; const file = new FileModel({ + user_id: req.models.user!.id, slug: slug, real_name: upload.originalname, storage_type: 'local', storage_path: 'storage/uploads/' + slug, + size: upload.size, ttl: ttl, }); @@ -94,8 +97,12 @@ export default class FileController extends Controller { } protected async deleteFile(req: Request, res: Response): Promise { + const slug = req.params.slug; + if (!slug) throw new BadRequestError('Cannot delete nothing.', 'Please provide a slug.', req.url); + const file = await FileModel.getBySlug(req.params.slug); if (!file) throw new NotFoundHttpError('File', req.url); + if (!file.canDelete(req.models.user!.id!)) throw new ForbiddenHttpError('file', req.url); switch (file.storage_type) { case 'local': diff --git a/src/migrations/CreateFilesTable.ts b/src/migrations/CreateFilesTable.ts index 6d575db..c372df3 100644 --- a/src/migrations/CreateFilesTable.ts +++ b/src/migrations/CreateFilesTable.ts @@ -5,10 +5,12 @@ export default class CreateFilesTable extends Migration { public async install(connection: Connection): Promise { await this.query('CREATE TABLE files(' + 'id INT NOT NULL AUTO_INCREMENT,' + + 'user_id INT NOT NULL,' + 'slug VARCHAR(259) UNIQUE NOT NULL,' + 'real_name VARCHAR(259) NOT NULL,' + 'storage_type VARCHAR(64) NOT NULL,' + 'storage_path VARCHAR(1745) NOT NULL,' + + 'size INT UNSIGNED NOT NULL,' + 'created_at DATETIME NOT NULL DEFAULT NOW(),' + 'ttl INT UNSIGNED NOT NULL,' + 'PRIMARY KEY (id)' + diff --git a/src/models/FileModel.ts b/src/models/FileModel.ts index ba7060e..7d73dfa 100644 --- a/src/models/FileModel.ts +++ b/src/models/FileModel.ts @@ -2,6 +2,7 @@ import Model from "wms-core/db/Model"; import Validator from "wms-core/db/Validator"; import Controller from "wms-core/Controller"; import config from "config"; +import User from "wms-core/auth/models/User"; export default class FileModel extends Model { public static get table(): string { @@ -13,18 +14,22 @@ export default class FileModel extends Model { return models.length > 0 ? models[0] : null; } + public readonly user_id!: number; public readonly slug!: string; public readonly real_name!: string; public readonly storage_type!: FileStorage; public readonly storage_path!: string; + public readonly size!: number; public created_at?: Date; public readonly ttl!: number; protected defineProperties() { + this.defineProperty('user_id', new Validator().defined().exists(User, 'id')); this.defineProperty('slug', new Validator().defined().minLength(1).maxLength(259).unique(this, 'slug')); this.defineProperty('real_name', new Validator().defined().minLength(1).maxLength(259)); this.defineProperty('storage_type', new Validator().defined().maxLength(64)); this.defineProperty('storage_path', new Validator().defined().maxLength(1745)); + this.defineProperty('size', new Validator().defined().min(0)); this.defineProperty('created_at', new Validator()); this.defineProperty('ttl', new Validator().defined().min(0).max(4294967295)); } @@ -47,6 +52,10 @@ export default class FileModel extends Model { if (!expirationDate) return false; return new Date().getTime() >= expirationDate.getTime(); } + + public canDelete(user_id: number): boolean { + return this.user_id === user_id; + } } export type FileStorage = 'local'; diff --git a/views/file-manager.njk b/views/file-manager.njk index a6348d8..9e7491b 100644 --- a/views/file-manager.njk +++ b/views/file-manager.njk @@ -34,9 +34,11 @@ # - url - name + URL + Name + Size Expires at + Actions @@ -51,8 +53,12 @@ {{ file.real_name }} + {{ (file.size / (1024 * 1024)).toFixed(2) }}MB {% set expires_at = file.getExpirationDate() %} {% if expires_at %}{{ expires_at.toISOString() }}{% else %}Never{% endif %} + + Delete + {% endfor %}