Merge file/url creating form and manager
This commit is contained in:
parent
a2a9d20994
commit
a5729af3c1
@ -18,7 +18,7 @@ export default class AuthTokenController extends Controller {
|
|||||||
});
|
});
|
||||||
await authToken.save();
|
await authToken.save();
|
||||||
req.flash('success', 'Successfully created auth token.');
|
req.flash('success', 'Successfully created auth token.');
|
||||||
res.redirect(req.getPreviousUrl() || Controller.route('file-upload'));
|
res.redirect(req.getPreviousUrl() || Controller.route('file-uploader'));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async postRevokeAuthToken(req: Request, res: Response): Promise<void> {
|
protected async postRevokeAuthToken(req: Request, res: Response): Promise<void> {
|
||||||
@ -34,6 +34,6 @@ export default class AuthTokenController extends Controller {
|
|||||||
await authToken.delete();
|
await authToken.delete();
|
||||||
|
|
||||||
req.flash('success', 'Successfully deleted auth token.');
|
req.flash('success', 'Successfully deleted auth token.');
|
||||||
res.redirect(req.getPreviousUrl() || Controller.route('file-upload'));
|
res.redirect(req.getPreviousUrl() || Controller.route('file-uploader'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,7 @@ import {BadRequestError, ForbiddenHttpError, ServerError} from "swaf/HttpError";
|
|||||||
import FileModel from "../models/FileModel";
|
import FileModel from "../models/FileModel";
|
||||||
import config from "config";
|
import config from "config";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import AuthToken from "../models/AuthToken";
|
import Formidable from "formidable";
|
||||||
import {IncomingForm} from "formidable";
|
|
||||||
import generateSlug from "../SlugGenerator";
|
import generateSlug from "../SlugGenerator";
|
||||||
import {logger} from "swaf/Logger";
|
import {logger} from "swaf/Logger";
|
||||||
import FileUploadMiddleware from "swaf/FileUploadMiddleware";
|
import FileUploadMiddleware from "swaf/FileUploadMiddleware";
|
||||||
@ -14,21 +13,20 @@ import FileUploadMiddleware from "swaf/FileUploadMiddleware";
|
|||||||
|
|
||||||
export default class FileController extends Controller {
|
export default class FileController extends Controller {
|
||||||
public routes(): void {
|
public routes(): void {
|
||||||
this.get('/files/upload', this.getFileUploader, 'file-upload', RequireAuthMiddleware);
|
this.get('/files/:page([0-9]+)?', this.getFileUploader, 'file-uploader', RequireAuthMiddleware);
|
||||||
this.get('/files/upload/script', this.downloadLinuxScript, 'file-linux-script');
|
this.get('/files/upload-script', this.downloadLinuxScript, 'file-linux-script');
|
||||||
this.post('/files/post', this.postFileFrontend, 'post-file-frontend', RequireAuthMiddleware, FileUploadFormMiddleware);
|
this.post('/files/upload', this.postFileFrontend, 'post-file-frontend', RequireAuthMiddleware, FileUploadFormMiddleware);
|
||||||
this.get('/files/:page([0-9]+)?', this.getFileManager, 'file-manager', RequireAuthMiddleware);
|
|
||||||
this.post('/files/delete/:slug', FileController.deleteFileRoute, 'delete-file-frontend', RequireAuthMiddleware);
|
this.post('/files/delete/:slug', FileController.deleteFileRoute, 'delete-file-frontend', RequireAuthMiddleware);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getFileUploader(req: Request, res: Response): Promise<void> {
|
protected async getFileUploader(req: Request, res: Response): Promise<void> {
|
||||||
const allowedDomains = config.get<string[]>('allowed_url_domains');
|
const allowedDomains = config.get<string[]>('allowed_url_domains');
|
||||||
const user = req.as(RequireAuthMiddleware).getUser();
|
const user = req.as(RequireAuthMiddleware).getUser();
|
||||||
res.render('file-upload', {
|
res.render('file-uploader', {
|
||||||
max_upload_size: config.get<string>('max_upload_size'),
|
max_upload_size: config.get<string>('max_upload_size'),
|
||||||
auth_tokens: await AuthToken.select().where('user_id', user.id).get(),
|
|
||||||
allowed_domains: allowedDomains,
|
allowed_domains: allowedDomains,
|
||||||
default_domain: allowedDomains[config.get<number>('default_url_domain_for_files')],
|
default_domain: allowedDomains[config.get<number>('default_url_domain_for_files')],
|
||||||
|
files: await FileModel.paginateForUser(req, 100, user.getOrFail('id')),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,13 +34,6 @@ export default class FileController extends Controller {
|
|||||||
res.download('assets/files/upload_file.sh', 'upload_file.sh');
|
res.download('assets/files/upload_file.sh', 'upload_file.sh');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getFileManager(req: Request, res: Response): Promise<void> {
|
|
||||||
const user = req.as(RequireAuthMiddleware).getUser();
|
|
||||||
res.render('file-manager', {
|
|
||||||
files: await FileModel.paginateForUser(req, 100, user.getOrFail('id')),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async postFileFrontend(req: Request, res: Response): Promise<void> {
|
protected async postFileFrontend(req: Request, res: Response): Promise<void> {
|
||||||
req.body.type = 'file';
|
req.body.type = 'file';
|
||||||
await FileController.handleFileUpload(
|
await FileController.handleFileUpload(
|
||||||
@ -100,7 +91,7 @@ export default class FileController extends Controller {
|
|||||||
html: () => {
|
html: () => {
|
||||||
req.flash('success', 'Upload success!');
|
req.flash('success', 'Upload success!');
|
||||||
req.flash('url', file.getURL(domain));
|
req.flash('url', file.getURL(domain));
|
||||||
res.redirect(Controller.route('file-manager'));
|
res.redirect(Controller.route('file-uploader'));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -135,7 +126,7 @@ export default class FileController extends Controller {
|
|||||||
text: () => res.send('success'),
|
text: () => res.send('success'),
|
||||||
html: () => {
|
html: () => {
|
||||||
req.flash('success', 'Successfully deleted file.');
|
req.flash('success', 'Successfully deleted file.');
|
||||||
res.redirect(Controller.route('file-manager'));
|
res.redirect(Controller.route('file-uploader'));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -152,11 +143,11 @@ export class FileUploadFormMiddleware extends FileUploadMiddleware {
|
|||||||
return 'upload';
|
return 'upload';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected makeForm(): IncomingForm {
|
protected makeForm(): Formidable {
|
||||||
const form = new IncomingForm();
|
return new Formidable({
|
||||||
form.uploadDir = 'storage/tmp';
|
uploadDir: 'storage/tmp',
|
||||||
form.maxFileSize = config.get<number>('max_upload_size') * 1024 * 1024;
|
maxFileSize: config.get<number>('max_upload_size') * 1024 * 1024,
|
||||||
return form;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,21 @@ import URLRedirect from "../models/URLRedirect";
|
|||||||
import {RequireAuthMiddleware, RequireRequestAuthMiddleware} from "swaf/auth/AuthComponent";
|
import {RequireAuthMiddleware, RequireRequestAuthMiddleware} from "swaf/auth/AuthComponent";
|
||||||
import generateSlug from "../SlugGenerator";
|
import generateSlug from "../SlugGenerator";
|
||||||
import config from "config";
|
import config from "config";
|
||||||
import AuthToken from "../models/AuthToken";
|
|
||||||
|
|
||||||
export default class URLRedirectController extends Controller {
|
export default class URLRedirectController extends Controller {
|
||||||
public routes(): void {
|
public routes(): void {
|
||||||
this.get('/url/shrink', this.getUrlShrinker, 'url-shrinker', RequireAuthMiddleware);
|
this.get('/url/:page([0-9]+)?', this.getUrlShrinker, 'url-shrinker', RequireAuthMiddleware);
|
||||||
this.get('/url/shrink/script', this.downloadLinuxScript, 'url-linux-script');
|
this.get('/url/shrink-script', this.downloadLinuxScript, 'url-linux-script');
|
||||||
this.post('/url/shrink', this.addUrlFrontend, 'shrink-url', RequireAuthMiddleware);
|
this.post('/url/shrink', this.addUrlFrontend, 'shrink-url', RequireAuthMiddleware);
|
||||||
this.get('/urls/:page([0-9]+)?', this.getUrlRedirectManager, 'url-manager', RequireAuthMiddleware);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getUrlShrinker(req: Request, res: Response): Promise<void> {
|
protected async getUrlShrinker(req: Request, res: Response): Promise<void> {
|
||||||
const user = req.as(RequireAuthMiddleware).getUser();
|
const user = req.as(RequireAuthMiddleware).getUser();
|
||||||
const allowedDomains = config.get<string[]>('allowed_url_domains');
|
const allowedDomains = config.get<string[]>('allowed_url_domains');
|
||||||
res.render('url-shrinker', {
|
res.render('url-shrinker', {
|
||||||
auth_tokens: await AuthToken.select().where('user_id', user.id).get(),
|
|
||||||
allowed_domains: allowedDomains,
|
allowed_domains: allowedDomains,
|
||||||
default_domain: allowedDomains[config.get<number>('default_url_domain_for_urls')],
|
default_domain: allowedDomains[config.get<number>('default_url_domain_for_urls')],
|
||||||
|
urls: await URLRedirect.paginateForUser(req, 2, user.getOrFail('id')),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,13 +26,6 @@ export default class URLRedirectController extends Controller {
|
|||||||
res.download('assets/files/shrink_url.sh', 'shrink_url.sh');
|
res.download('assets/files/shrink_url.sh', 'shrink_url.sh');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getUrlRedirectManager(req: Request, res: Response): Promise<void> {
|
|
||||||
const user = req.as(RequireAuthMiddleware).getUser();
|
|
||||||
res.render('url-manager', {
|
|
||||||
urls: await URLRedirect.paginateForUser(req, 100, user.getOrFail('id')),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async addUrlFrontend(req: Request, res: Response, next: NextFunction): Promise<void> {
|
protected async addUrlFrontend(req: Request, res: Response, next: NextFunction): Promise<void> {
|
||||||
req.body.type = 'url';
|
req.body.type = 'url';
|
||||||
await URLRedirectController.addURL(
|
await URLRedirectController.addURL(
|
||||||
@ -75,7 +66,7 @@ export default class URLRedirectController extends Controller {
|
|||||||
html: () => {
|
html: () => {
|
||||||
req.flash('success', 'URL shrunk successfully!');
|
req.flash('success', 'URL shrunk successfully!');
|
||||||
req.flash('url', urlRedirect.getURL(domain));
|
req.flash('url', urlRedirect.getURL(domain));
|
||||||
res.redirect(Controller.route('url-manager'));
|
res.redirect(Controller.route('url-shrinker'));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
{% extends 'layouts/base.njk' %}
|
|
||||||
|
|
||||||
{% set title = app.name + ' - File manager' %}
|
|
||||||
|
|
||||||
{% block scripts %}
|
|
||||||
<script src="/js/fm.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>File manager</h1>
|
|
||||||
<p>You're their manager, please be nice with them.</p>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<section class="panel">
|
|
||||||
<h2><i data-feather="folder"></i> File list</h2>
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>#</th>
|
|
||||||
<th class="table-col-grow">URL</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Size</th>
|
|
||||||
<th>Expires at</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
{% for file in files %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ file.id }}</td>
|
|
||||||
<td>
|
|
||||||
<div class="copyable-text">
|
|
||||||
<a class="content" href="{{ file.getURL() }}" target="_blank">{{ file.getURL() }}</a>
|
|
||||||
<button class="copy-button"><i data-feather="copy"></i></button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td><pre>{{ file.real_name }}</pre></td>
|
|
||||||
<td>{{ (file.size / (1024 * 1024)).toFixed(2) }}MB</td>
|
|
||||||
{% set expires_at = file.getExpirationDate() %}
|
|
||||||
<td>{% if expires_at %}{{ expires_at.toISOString() }}{% else %}Never{% endif %}</td>
|
|
||||||
<td class="actions">
|
|
||||||
{% if file.shouldBeDeleted() %}
|
|
||||||
Pending deletion
|
|
||||||
{% else %}
|
|
||||||
<form action="{{ route('delete-file-frontend', file.slug) }}" method="post">
|
|
||||||
{{ macros.csrf(getCsrfToken) }}
|
|
||||||
<button class="button danger"><i data-feather="trash"></i> <span class="tip">Delete</span></button>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,6 +1,6 @@
|
|||||||
{% extends 'layouts/base.njk' %}
|
{% extends 'layouts/base.njk' %}
|
||||||
|
|
||||||
{% set title = app.name + ' - File upload' %}
|
{% set title = app.name + ' - Upload file' %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script src="/js/fm.js"></script>
|
<script src="/js/fm.js"></script>
|
||||||
@ -50,7 +50,50 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
|
||||||
|
|
||||||
{% include 'desktop-utility.njk' %}
|
|
||||||
|
<section class="panel">
|
||||||
|
<h2><i data-feather="folder"></i> File list</h2>
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th class="table-col-grow">URL</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Size</th>
|
||||||
|
<th>Expires at</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for file in files %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ file.id }}</td>
|
||||||
|
<td>
|
||||||
|
<div class="copyable-text">
|
||||||
|
<a class="content" href="{{ file.getURL() }}" target="_blank">{{ file.getURL() }}</a>
|
||||||
|
<button class="copy-button"><i data-feather="copy"></i></button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td><pre>{{ file.real_name }}</pre></td>
|
||||||
|
<td>{{ (file.size / (1024 * 1024)).toFixed(2) }}MB</td>
|
||||||
|
{% set expires_at = file.getExpirationDate() %}
|
||||||
|
<td>{% if expires_at %}{{ expires_at.toISOString() }}{% else %}Never{% endif %}</td>
|
||||||
|
<td class="actions">
|
||||||
|
{% if file.shouldBeDeleted() %}
|
||||||
|
Pending deletion
|
||||||
|
{% else %}
|
||||||
|
<form action="{{ route('delete-file-frontend', file.slug) }}" method="post">
|
||||||
|
{{ macros.csrf(getCsrfToken) }}
|
||||||
|
<button class="button danger"><i data-feather="trash"></i> <span class="tip">Delete</span></button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -18,16 +18,8 @@
|
|||||||
<ul id="main-menu">
|
<ul id="main-menu">
|
||||||
<li><a href="{{ route('about') }}"><i data-feather="info"></i> <span class="tip">About</span></a></li>
|
<li><a href="{{ route('about') }}"><i data-feather="info"></i> <span class="tip">About</span></a></li>
|
||||||
{% if user %}
|
{% if user %}
|
||||||
<li><a href="{{ route('file-manager') }}"><i data-feather="folder"></i> <span class="tip">File manager</span></a>
|
<li><a href="{{ route('file-uploader') }}"><i data-feather="upload"></i> <span class="tip">Upload file</span></a></li>
|
||||||
<ul class="dropdown">
|
|
||||||
<li><a href="{{ route('file-upload') }}"><i data-feather="upload"></i> <span class="tip">Upload file</span></a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="{{ route('url-manager') }}"><i data-feather="link"></i> <span class="tip">URL manager</span></a>
|
|
||||||
<ul class="dropdown">
|
|
||||||
<li><a href="{{ route('url-shrinker') }}"><i data-feather="crosshair"></i> <span class="tip">Shrink URL</span></a></li>
|
<li><a href="{{ route('url-shrinker') }}"><i data-feather="crosshair"></i> <span class="tip">Shrink URL</span></a></li>
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
{% if user.is_admin %}
|
{% if user.is_admin %}
|
||||||
<li><a href="{{ route('backend') }}"><i data-feather="settings"></i> <span class="tip">Backend</span></a></li>
|
<li><a href="{{ route('backend') }}"><i data-feather="settings"></i> <span class="tip">Backend</span></a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
{% extends 'layouts/base.njk' %}
|
|
||||||
|
|
||||||
{% set title = app.name + ' - URL manager' %}
|
|
||||||
|
|
||||||
{% block scripts %}{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>URL manager</h1>
|
|
||||||
<p>These are permanent.</p>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<section class="panel">
|
|
||||||
<h2><i data-feather="link"></i> URL list</h2>
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>#</th>
|
|
||||||
<th class="table-col-grow">URL</th>
|
|
||||||
<th>Target</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
{% for url in urls %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ url.id }}</td>
|
|
||||||
<td>
|
|
||||||
<div class="copyable-text">
|
|
||||||
<a class="content" href="{{ url.getURL() }}" target="_blank">{{ url.getURL() }}</a>
|
|
||||||
<button class="copy-button"><i data-feather="copy"></i></button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td><pre>{{ url.target_url }}</pre></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,6 +1,6 @@
|
|||||||
{% extends 'layouts/base.njk' %}
|
{% extends 'layouts/base.njk' %}
|
||||||
|
|
||||||
{% set title = app.name + ' - URL shrinker' %}
|
{% set title = app.name + ' - Shrink URL' %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script src="/js/url-shrinker.js"></script>
|
<script src="/js/url-shrinker.js"></script>
|
||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<h1>Shrink URLs</h1>
|
<h1>Shrink URLs</h1>
|
||||||
<p>(no phishing allowed)</p>
|
<p>For security reasons, shrinked URLs cannot be deleted.</p>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
@ -34,7 +34,34 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
|
||||||
|
|
||||||
{% include 'desktop-utility.njk' %}
|
|
||||||
|
<section class="panel">
|
||||||
|
<h2><i data-feather="link"></i> URL list</h2>
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th class="table-col-grow">URL</th>
|
||||||
|
<th>Target</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for url in urls %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ url.id }}</td>
|
||||||
|
<td>
|
||||||
|
<div class="copyable-text">
|
||||||
|
<a class="content" href="{{ url.getURL() }}" target="_blank">{{ url.getURL() }}</a>
|
||||||
|
<button class="copy-button"><i data-feather="copy"></i></button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td><pre>{{ url.target_url }}</pre></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Loading…
Reference in New Issue
Block a user