Add multi-domain support for urls and rename url "shortening" to url "shrinking"
This commit is contained in:
parent
d3909c0371
commit
095e68b27e
@ -2,7 +2,7 @@
|
|||||||
"bundles": {
|
"bundles": {
|
||||||
"app": "js/app.js",
|
"app": "js/app.js",
|
||||||
"fm": "js/fm.js",
|
"fm": "js/fm.js",
|
||||||
"url-shortener": "js/url-shortener.js",
|
"url-shrinker": "js/url-shrinker.js",
|
||||||
"layout": "sass/layout.scss",
|
"layout": "sass/layout.scss",
|
||||||
"error": "sass/error.scss",
|
"error": "sass/error.scss",
|
||||||
"logo": "img/logo.svg",
|
"logo": "img/logo.svg",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const form = document.getElementById('url-shortener-form');
|
const form = document.getElementById('url-shrink-form');
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
|
|
||||||
const autogenUrlCheckbox = document.getElementById('field-autogen_url');
|
const autogenUrlCheckbox = document.getElementById('field-autogen_url');
|
@ -33,4 +33,10 @@ export default Object.assign(require("wms-core/config/default").default, {
|
|||||||
from: 'contact@ily.li',
|
from: 'contact@ily.li',
|
||||||
from_name: 'ily.li',
|
from_name: 'ily.li',
|
||||||
},
|
},
|
||||||
|
allowed_url_domains: [
|
||||||
|
'localhost:4893',
|
||||||
|
'127.0.0.1:4893',
|
||||||
|
],
|
||||||
|
default_url_domain_for_files: 0,
|
||||||
|
default_url_domain_for_urls: 1,
|
||||||
});
|
});
|
@ -21,4 +21,10 @@ export default Object.assign(require("wms-core/config/production").default, {
|
|||||||
secure: true,
|
secure: true,
|
||||||
allow_invalid_tls: false
|
allow_invalid_tls: false
|
||||||
},
|
},
|
||||||
|
allowed_url_domains: [
|
||||||
|
'ily.li',
|
||||||
|
'gris.li',
|
||||||
|
],
|
||||||
|
default_url_domain_for_files: 0,
|
||||||
|
default_url_domain_for_urls: 1,
|
||||||
});
|
});
|
@ -27,9 +27,12 @@ export default class FileController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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');
|
||||||
res.render('file-upload', {
|
res.render('file-upload', {
|
||||||
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', req.models.user!.id!),
|
auth_tokens: await AuthToken.select().where('user_id', req.models.user!.id!),
|
||||||
|
allowed_domains: allowedDomains,
|
||||||
|
default_domain: allowedDomains[config.get<number>('default_url_domain_for_files')],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,13 +111,15 @@ export default class FileController extends Controller {
|
|||||||
await file.save();
|
await file.save();
|
||||||
fs.renameSync(upload.path, file.storage_path);
|
fs.renameSync(upload.path, file.storage_path);
|
||||||
|
|
||||||
|
const domain = req.body.url_domain || config.get<string[]>('allowed_url_domains')[config.get<number>('default_url_domain_for_files')];
|
||||||
res.format({
|
res.format({
|
||||||
json: () => res.json({
|
json: () => res.json({
|
||||||
url: file.getURL(),
|
url: file.getURL(domain),
|
||||||
}),
|
}),
|
||||||
text: () => res.send(file.getURL()),
|
text: () => res.send(file.getURL(domain)),
|
||||||
html: () => {
|
html: () => {
|
||||||
req.flash('success', 'Upload success!');
|
req.flash('success', 'Upload success!');
|
||||||
|
req.flash('url', file.getURL(domain));
|
||||||
res.redirectBack('/');
|
res.redirectBack('/');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -4,12 +4,13 @@ import URLRedirect from "../models/URLRedirect";
|
|||||||
import {REQUIRE_AUTH_MIDDLEWARE, REQUIRE_REQUEST_AUTH_MIDDLEWARE} from "wms-core/auth/AuthComponent";
|
import {REQUIRE_AUTH_MIDDLEWARE, REQUIRE_REQUEST_AUTH_MIDDLEWARE} from "wms-core/auth/AuthComponent";
|
||||||
import generateSlug from "../SlugGenerator";
|
import generateSlug from "../SlugGenerator";
|
||||||
import {BadRequestError} from "wms-core/HttpError";
|
import {BadRequestError} from "wms-core/HttpError";
|
||||||
|
import config from "config";
|
||||||
|
|
||||||
export default class URLRedirectController extends Controller {
|
export default class URLRedirectController extends Controller {
|
||||||
routes(): void {
|
routes(): void {
|
||||||
this.get('/url/shorten', this.getURLShortener, 'url-shortener', REQUIRE_AUTH_MIDDLEWARE);
|
this.get('/url/shrink', this.getURLShrinker, 'url-shrinker', REQUIRE_AUTH_MIDDLEWARE);
|
||||||
this.get('/url/shorten/script', this.downloadLinuxScript, 'url-linux-script');
|
this.get('/url/shrink/script', this.downloadLinuxScript, 'url-linux-script');
|
||||||
this.post('/url/shorten', this.addURLFrontend, 'shorten-url', REQUIRE_AUTH_MIDDLEWARE);
|
this.post('/url/shrink', this.addURLFrontend, 'shrink-url', REQUIRE_AUTH_MIDDLEWARE);
|
||||||
this.get('/urls/:page([0-9]+)?', this.getURLRedirectManager, 'url-manager', REQUIRE_AUTH_MIDDLEWARE);
|
this.get('/urls/:page([0-9]+)?', this.getURLRedirectManager, 'url-manager', REQUIRE_AUTH_MIDDLEWARE);
|
||||||
|
|
||||||
this.post('/', this.addURL, 'post-url', REQUIRE_REQUEST_AUTH_MIDDLEWARE);
|
this.post('/', this.addURL, 'post-url', REQUIRE_REQUEST_AUTH_MIDDLEWARE);
|
||||||
@ -18,12 +19,16 @@ export default class URLRedirectController extends Controller {
|
|||||||
this.put('/:slug', this.addURL, 'put-url', REQUIRE_REQUEST_AUTH_MIDDLEWARE);
|
this.put('/:slug', this.addURL, 'put-url', REQUIRE_REQUEST_AUTH_MIDDLEWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getURLShortener(req: Request, res: Response): Promise<void> {
|
protected async getURLShrinker(req: Request, res: Response): Promise<void> {
|
||||||
res.render('url-shortener');
|
const allowedDomains = config.get<string[]>('allowed_url_domains');
|
||||||
|
res.render('url-shrinker', {
|
||||||
|
allowed_domains: allowedDomains,
|
||||||
|
default_domain: allowedDomains[config.get<number>('default_url_domain_for_urls')],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async downloadLinuxScript(req: Request, res: Response): Promise<void> {
|
protected async downloadLinuxScript(req: Request, res: Response): Promise<void> {
|
||||||
res.download('assets/files/shorten_url.sh', 'shorten_url.sh');
|
res.download('assets/files/shrink_url.sh', 'shrink_url.sh');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getURLRedirectManager(req: Request, res: Response): Promise<void> {
|
protected async getURLRedirectManager(req: Request, res: Response): Promise<void> {
|
||||||
@ -67,14 +72,15 @@ export default class URLRedirectController extends Controller {
|
|||||||
|
|
||||||
await urlRedirect.save();
|
await urlRedirect.save();
|
||||||
|
|
||||||
|
const domain = req.body.url_domain || config.get<string[]>('allowed_url_domains')[config.get<number>('default_url_domain_for_urls')];
|
||||||
res.format({
|
res.format({
|
||||||
json: () => res.json({
|
json: () => res.json({
|
||||||
url: urlRedirect.getURL(),
|
url: urlRedirect.getURL(domain),
|
||||||
}),
|
}),
|
||||||
text: () => res.send(urlRedirect.getURL()),
|
text: () => res.send(urlRedirect.getURL(domain)),
|
||||||
html: () => {
|
html: () => {
|
||||||
req.flash('success', 'URL shortened successfully!');
|
req.flash('success', 'URL shrunk successfully!');
|
||||||
req.flash('url', urlRedirect.getURL());
|
req.flash('url', urlRedirect.getURL(domain));
|
||||||
res.redirectBack('/');
|
res.redirectBack('/');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -39,8 +39,8 @@ export default class FileModel extends Model {
|
|||||||
this.addProperty('ttl', new Validator().defined().min(0).max(4294967295));
|
this.addProperty('ttl', new Validator().defined().min(0).max(4294967295));
|
||||||
}
|
}
|
||||||
|
|
||||||
public getURL(): string {
|
public getURL(domain: string = config.get<string>('base_url')): string {
|
||||||
return config.get<string>('base_url') + Controller.route('get-file', {
|
return (/^https?:\/\//.test(domain) ? '' : 'https://') + domain + Controller.route('get-file', {
|
||||||
slug: this.slug,
|
slug: this.slug,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,8 @@ export default class URLRedirect extends Model {
|
|||||||
this.addProperty('created_at', new Validator());
|
this.addProperty('created_at', new Validator());
|
||||||
}
|
}
|
||||||
|
|
||||||
public getURL(): string {
|
public getURL(domain: string = config.get<string>('base_url')): string {
|
||||||
return config.get<string>('base_url') + Controller.route('get-url', {
|
return (/^https?:\/\//.test(domain) ? '' : 'https://') + domain + Controller.route('get-url', {
|
||||||
slug: this.slug,
|
slug: this.slug,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<td><a href="{{ route('file-linux-script') }}">Download</a></td>
|
<td><a href="{{ route('file-linux-script') }}">Download</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>shorten_url.sh</td>
|
<td>shrink_url.sh</td>
|
||||||
<td><a href="{{ route('url-linux-script') }}">Download</a></td>
|
<td><a href="{{ route('url-linux-script') }}">Download</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -32,8 +32,8 @@
|
|||||||
<p>Examples:</p>
|
<p>Examples:</p>
|
||||||
<pre>upload_file.sh path/to/file</pre>
|
<pre>upload_file.sh path/to/file</pre>
|
||||||
<pre>upload_file.sh path/to/file my_very_important_file.png</pre>
|
<pre>upload_file.sh path/to/file my_very_important_file.png</pre>
|
||||||
<pre>shorten_url.sh https://gitlab.com/ArisuOngaku/ilyli</pre>
|
<pre>shrink_url.sh https://gitlab.com/ArisuOngaku/ilyli</pre>
|
||||||
<pre>shorten_url.sh https://gitlab.com/ArisuOngaku/ilyli repo</pre>
|
<pre>shrink_url.sh https://gitlab.com/ArisuOngaku/ilyli repo</pre>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
@ -81,9 +81,15 @@
|
|||||||
<td>No</td>
|
<td>No</td>
|
||||||
<td>0 (never delete), 30 (delete after 30s)</td>
|
<td>0 (never delete), 30 (delete after 30s)</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>url_domain</td>
|
||||||
|
<td>Choose domain name</td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>{{ allowed_domains.join('|') }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="4">URL shorten</th>
|
<th colspan="4">URL shrink</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>type</td>
|
<td>type</td>
|
||||||
@ -97,6 +103,12 @@
|
|||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>A valid URL starting with https:// or http://</td>
|
<td>A valid URL starting with https:// or http://</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>url_domain</td>
|
||||||
|
<td>Choose domain name</td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>{{ allowed_domains.join('|') }}</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p>For examples with curl, please download and review the scripts above.</p>
|
<p>For examples with curl, please download and review the scripts above.</p>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
{{ macros.field(_locals, 'number', 'expire_after_days', '30', 'How many days to delete this file after', null, validation_attributes='max="1825"') }}
|
{{ macros.field(_locals, 'number', 'expire_after_days', '30', 'How many days to delete this file after', null, validation_attributes='max="1825"') }}
|
||||||
{{ macros.field(_locals, 'checkbox', 'never_expire', '', 'Never delete this file') }}
|
{{ macros.field(_locals, 'checkbox', 'never_expire', '', 'Never delete this file') }}
|
||||||
|
|
||||||
{{ macros.field(_locals, 'text', 'slug', '', 'Custom url slug', 'Example: beautiful_image.jpg sets url to https://ily.li/beautiful_image.jpg', validation_attributes='disabled') }}
|
{{ macros.field(_locals, 'text', 'slug', '', 'Custom url slug', 'Example: beautiful_image.jpg sets url to https://'+default_domain+'/beautiful_image.jpg', validation_attributes='disabled') }}
|
||||||
{{ macros.field(_locals, 'checkbox', 'autogen_url', '', 'Generate url automatically', null, validation_attributes='checked') }}
|
{{ macros.field(_locals, 'checkbox', 'autogen_url', '', 'Generate url automatically', null, validation_attributes='checked') }}
|
||||||
|
|
||||||
{{ macros.csrf(getCSRFToken) }}
|
{{ macros.csrf(getCSRFToken) }}
|
||||||
@ -40,6 +40,15 @@
|
|||||||
<div class="content"></div>
|
<div class="content"></div>
|
||||||
<button class="copy-button"><i data-feather="copy"></i></button>
|
<button class="copy-button"><i data-feather="copy"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% set url = flash('url') %}
|
||||||
|
{% if url | length %}
|
||||||
|
<div class="copyable-text">
|
||||||
|
<div class="title">URL</div>
|
||||||
|
<div class="content">{{ url }}</div>
|
||||||
|
<button class="copy-button"><i data-feather="copy"></i></button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<li><a href="{{ route('file-manager') }}"><i data-feather="folder"></i> <span class="tip">File manager</span></a></li>
|
<li><a href="{{ route('file-manager') }}"><i data-feather="folder"></i> <span class="tip">File manager</span></a></li>
|
||||||
<li><a href="{{ route('file-upload') }}"><i data-feather="upload"></i> <span class="tip">Upload file</span></a></li>
|
<li><a href="{{ route('file-upload') }}"><i data-feather="upload"></i> <span class="tip">Upload file</span></a></li>
|
||||||
<li><a href="{{ route('url-manager') }}"><i data-feather="link"></i> <span class="tip">URL manager</span></a></li>
|
<li><a href="{{ route('url-manager') }}"><i data-feather="link"></i> <span class="tip">URL manager</span></a></li>
|
||||||
<li><a href="{{ route('url-shortener') }}"><i data-feather="crosshair"></i> <span class="tip">Shorten URL</span></a></li>
|
<li><a href="{{ route('url-shrinker') }}"><i data-feather="crosshair"></i> <span class="tip">Shrink URL</span></a></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,28 +1,28 @@
|
|||||||
{% extends 'layouts/base.njk' %}
|
{% extends 'layouts/base.njk' %}
|
||||||
|
|
||||||
{% set title = app.name + ' - URL shortener' %}
|
{% set title = app.name + ' - URL shrinker' %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script src="/js/url-shortener.js"></script>
|
<script src="/js/url-shrinker.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<h1>Shorten URLs</h1>
|
<h1>Shrink URLs</h1>
|
||||||
<p>(no phishing allowed)</p>
|
<p>(no phishing allowed)</p>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<h2>Shorten a URL</h2>
|
<h2>Shrink a URL</h2>
|
||||||
|
|
||||||
<form action="{{ route('shorten-url') }}" method="POST" id="url-shortener-form">
|
<form action="{{ route('shrink-url') }}" method="POST" id="url-shrink-form">
|
||||||
{{ macros.field(_locals, 'text', 'target_url', '', 'Target URL', 'Only valid URLs starting with http:// or https://', validation_attributes='required') }}
|
{{ macros.field(_locals, 'text', 'target_url', '', 'Target URL', 'Only valid URLs starting with http:// or https://', validation_attributes='required') }}
|
||||||
|
|
||||||
{{ macros.field(_locals, 'text', 'slug', '', 'Custom url slug', 'Example: bear sets url to https://ily.li/bear', validation_attributes='disabled') }}
|
{{ macros.field(_locals, 'text', 'slug', '', 'Custom url slug', 'Example: bear sets url to https://'+default_domain+'/bear', validation_attributes='disabled') }}
|
||||||
{{ macros.field(_locals, 'checkbox', 'autogen_url', '', 'Generate url automatically', null, validation_attributes='checked') }}
|
{{ macros.field(_locals, 'checkbox', 'autogen_url', '', 'Generate url automatically', null, validation_attributes='checked') }}
|
||||||
|
|
||||||
{{ macros.csrf(getCSRFToken) }}
|
{{ macros.csrf(getCSRFToken) }}
|
||||||
|
|
||||||
<button type="submit"><i data-feather="link"></i> Shorten URL</button>
|
<button type="submit"><i data-feather="link"></i> Shrink URL</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% set url = flash('url') %}
|
{% set url = flash('url') %}
|
Loading…
Reference in New Issue
Block a user