Add size and owner fields to files
This commit is contained in:
parent
f6d9db6243
commit
6db8b1cd21
@ -1,7 +1,7 @@
|
|||||||
import Controller from "wms-core/Controller";
|
import Controller from "wms-core/Controller";
|
||||||
import {REQUIRE_AUTH_MIDDLEWARE} from "wms-core/auth/AuthComponent";
|
import {REQUIRE_AUTH_MIDDLEWARE} from "wms-core/auth/AuthComponent";
|
||||||
import {Request, Response, Router} from "express";
|
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 FileModel from "../models/FileModel";
|
||||||
import {cryptoRandomDictionary} from "wms-core/Utils";
|
import {cryptoRandomDictionary} from "wms-core/Utils";
|
||||||
import config from "config";
|
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/:page?', this.getFileManager, 'file-manager', REQUIRE_AUTH_MIDDLEWARE);
|
||||||
this.get('/files/delete/:slug', this.deleteFile, 'delete-file-frontend', 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.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.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<void> {
|
protected async getFileManager(req: Request, res: Response): Promise<void> {
|
||||||
@ -33,6 +33,7 @@ export default class FileController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async downloadFile(req: Request, res: Response): Promise<void> {
|
protected async downloadFile(req: Request, res: Response): Promise<void> {
|
||||||
|
console.log('heeey');
|
||||||
const file = await FileModel.getBySlug(req.params.slug);
|
const file = await FileModel.getBySlug(req.params.slug);
|
||||||
if (!file || file.shouldBeDeleted()) throw new NotFoundHttpError('File', req.url);
|
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;
|
else if (req.body.expire_after_days !== undefined) ttl = parseInt(req.body.expire_after_days) * 24 * 3600;
|
||||||
|
|
||||||
const file = new FileModel({
|
const file = new FileModel({
|
||||||
|
user_id: req.models.user!.id,
|
||||||
slug: slug,
|
slug: slug,
|
||||||
real_name: upload.originalname,
|
real_name: upload.originalname,
|
||||||
storage_type: 'local',
|
storage_type: 'local',
|
||||||
storage_path: 'storage/uploads/' + slug,
|
storage_path: 'storage/uploads/' + slug,
|
||||||
|
size: upload.size,
|
||||||
ttl: ttl,
|
ttl: ttl,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -94,8 +97,12 @@ export default class FileController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async deleteFile(req: Request, res: Response): Promise<void> {
|
protected async deleteFile(req: Request, res: Response): Promise<void> {
|
||||||
|
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);
|
const file = await FileModel.getBySlug(req.params.slug);
|
||||||
if (!file) throw new NotFoundHttpError('File', req.url);
|
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) {
|
switch (file.storage_type) {
|
||||||
case 'local':
|
case 'local':
|
||||||
|
@ -5,10 +5,12 @@ export default class CreateFilesTable extends Migration {
|
|||||||
public async install(connection: Connection): Promise<void> {
|
public async install(connection: Connection): Promise<void> {
|
||||||
await this.query('CREATE TABLE files(' +
|
await this.query('CREATE TABLE files(' +
|
||||||
'id INT NOT NULL AUTO_INCREMENT,' +
|
'id INT NOT NULL AUTO_INCREMENT,' +
|
||||||
|
'user_id INT NOT NULL,' +
|
||||||
'slug VARCHAR(259) UNIQUE NOT NULL,' +
|
'slug VARCHAR(259) UNIQUE NOT NULL,' +
|
||||||
'real_name VARCHAR(259) NOT NULL,' +
|
'real_name VARCHAR(259) NOT NULL,' +
|
||||||
'storage_type VARCHAR(64) NOT NULL,' +
|
'storage_type VARCHAR(64) NOT NULL,' +
|
||||||
'storage_path VARCHAR(1745) NOT NULL,' +
|
'storage_path VARCHAR(1745) NOT NULL,' +
|
||||||
|
'size INT UNSIGNED NOT NULL,' +
|
||||||
'created_at DATETIME NOT NULL DEFAULT NOW(),' +
|
'created_at DATETIME NOT NULL DEFAULT NOW(),' +
|
||||||
'ttl INT UNSIGNED NOT NULL,' +
|
'ttl INT UNSIGNED NOT NULL,' +
|
||||||
'PRIMARY KEY (id)' +
|
'PRIMARY KEY (id)' +
|
||||||
|
@ -2,6 +2,7 @@ import Model from "wms-core/db/Model";
|
|||||||
import Validator from "wms-core/db/Validator";
|
import Validator from "wms-core/db/Validator";
|
||||||
import Controller from "wms-core/Controller";
|
import Controller from "wms-core/Controller";
|
||||||
import config from "config";
|
import config from "config";
|
||||||
|
import User from "wms-core/auth/models/User";
|
||||||
|
|
||||||
export default class FileModel extends Model {
|
export default class FileModel extends Model {
|
||||||
public static get table(): string {
|
public static get table(): string {
|
||||||
@ -13,18 +14,22 @@ export default class FileModel extends Model {
|
|||||||
return models.length > 0 ? models[0] : null;
|
return models.length > 0 ? models[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly user_id!: number;
|
||||||
public readonly slug!: string;
|
public readonly slug!: string;
|
||||||
public readonly real_name!: string;
|
public readonly real_name!: string;
|
||||||
public readonly storage_type!: FileStorage;
|
public readonly storage_type!: FileStorage;
|
||||||
public readonly storage_path!: string;
|
public readonly storage_path!: string;
|
||||||
|
public readonly size!: number;
|
||||||
public created_at?: Date;
|
public created_at?: Date;
|
||||||
public readonly ttl!: number;
|
public readonly ttl!: number;
|
||||||
|
|
||||||
protected defineProperties() {
|
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('slug', new Validator().defined().minLength(1).maxLength(259).unique(this, 'slug'));
|
||||||
this.defineProperty('real_name', new Validator().defined().minLength(1).maxLength(259));
|
this.defineProperty('real_name', new Validator().defined().minLength(1).maxLength(259));
|
||||||
this.defineProperty('storage_type', new Validator().defined().maxLength(64));
|
this.defineProperty('storage_type', new Validator().defined().maxLength(64));
|
||||||
this.defineProperty('storage_path', new Validator().defined().maxLength(1745));
|
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('created_at', new Validator());
|
||||||
this.defineProperty('ttl', new Validator().defined().min(0).max(4294967295));
|
this.defineProperty('ttl', new Validator().defined().min(0).max(4294967295));
|
||||||
}
|
}
|
||||||
@ -47,6 +52,10 @@ export default class FileModel extends Model {
|
|||||||
if (!expirationDate) return false;
|
if (!expirationDate) return false;
|
||||||
return new Date().getTime() >= expirationDate.getTime();
|
return new Date().getTime() >= expirationDate.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public canDelete(user_id: number): boolean {
|
||||||
|
return this.user_id === user_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FileStorage = 'local';
|
export type FileStorage = 'local';
|
||||||
|
@ -34,9 +34,11 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>#</th>
|
<th>#</th>
|
||||||
<th>url</th>
|
<th>URL</th>
|
||||||
<th>name</th>
|
<th>Name</th>
|
||||||
|
<th>Size</th>
|
||||||
<th>Expires at</th>
|
<th>Expires at</th>
|
||||||
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
@ -51,8 +53,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ file.real_name }}</td>
|
<td>{{ file.real_name }}</td>
|
||||||
|
<td>{{ (file.size / (1024 * 1024)).toFixed(2) }}MB</td>
|
||||||
{% set expires_at = file.getExpirationDate() %}
|
{% set expires_at = file.getExpirationDate() %}
|
||||||
<td>{% if expires_at %}{{ expires_at.toISOString() }}{% else %}Never{% endif %}</td>
|
<td>{% if expires_at %}{{ expires_at.toISOString() }}{% else %}Never{% endif %}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ route('delete-file-frontend', file.slug) }}" class="button danger"><i data-feather="trash"></i> Delete</a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
Loading…
Reference in New Issue
Block a user