Browse Source

Add multi-domain support for urls and rename url "shortening" to url "shrinking"

develop
Alice Gaudon 1 year ago
parent
commit
095e68b27e
  1. 2
      assets/config.json
  2. 0
      assets/files/shrink_url.sh
  3. 2
      assets/js/url-shrinker.js
  4. 6
      config/default.ts
  5. 6
      config/production.ts
  6. 9
      src/controllers/FileController.ts
  7. 26
      src/controllers/URLRedirectController.ts
  8. 4
      src/models/FileModel.ts
  9. 4
      src/models/URLRedirect.ts
  10. 20
      views/desktop-utility.njk
  11. 11
      views/file-upload.njk
  12. 2
      views/layouts/base.njk
  13. 14
      views/url-shrinker.njk

2
assets/config.json

@ -2,7 +2,7 @@
"bundles": {
"app": "js/app.js",
"fm": "js/fm.js",
"url-shortener": "js/url-shortener.js",
"url-shrinker": "js/url-shrinker.js",
"layout": "sass/layout.scss",
"error": "sass/error.scss",
"logo": "img/logo.svg",

0
assets/files/shorten_url.sh → assets/files/shrink_url.sh

2
assets/js/url-shortener.js → assets/js/url-shrinker.js

@ -1,5 +1,5 @@
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('url-shortener-form');
const form = document.getElementById('url-shrink-form');
if (!form) return;
const autogenUrlCheckbox = document.getElementById('field-autogen_url');

6
config/default.ts

@ -33,4 +33,10 @@ export default Object.assign(require("wms-core/config/default").default, {
from: 'contact@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,
});

6
config/production.ts

@ -21,4 +21,10 @@ export default Object.assign(require("wms-core/config/production").default, {
secure: true,
allow_invalid_tls: false
},
allowed_url_domains: [
'ily.li',
'gris.li',
],
default_url_domain_for_files: 0,
default_url_domain_for_urls: 1,
});

9
src/controllers/FileController.ts

@ -27,9 +27,12 @@ export default class FileController extends Controller {
}
protected async getFileUploader(req: Request, res: Response): Promise<void> {
const allowedDomains = config.get<string[]>('allowed_url_domains');
res.render('file-upload', {
max_upload_size: config.get<string>('max_upload_size'),
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();
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({
json: () => res.json({
url: file.getURL(),
url: file.getURL(domain),
}),
text: () => res.send(file.getURL()),
text: () => res.send(file.getURL(domain)),
html: () => {
req.flash('success', 'Upload success!');
req.flash('url', file.getURL(domain));
res.redirectBack('/');
},
});

26
src/controllers/URLRedirectController.ts

@ -4,12 +4,13 @@ import URLRedirect from "../models/URLRedirect";
import {REQUIRE_AUTH_MIDDLEWARE, REQUIRE_REQUEST_AUTH_MIDDLEWARE} from "wms-core/auth/AuthComponent";
import generateSlug from "../SlugGenerator";
import {BadRequestError} from "wms-core/HttpError";
import config from "config";
export default class URLRedirectController extends Controller {
routes(): void {
this.get('/url/shorten', this.getURLShortener, 'url-shortener', REQUIRE_AUTH_MIDDLEWARE);
this.get('/url/shorten/script', this.downloadLinuxScript, 'url-linux-script');
this.post('/url/shorten', this.addURLFrontend, 'shorten-url', REQUIRE_AUTH_MIDDLEWARE);
this.get('/url/shrink', this.getURLShrinker, 'url-shrinker', REQUIRE_AUTH_MIDDLEWARE);
this.get('/url/shrink/script', this.downloadLinuxScript, 'url-linux-script');
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.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);
}
protected async getURLShortener(req: Request, res: Response): Promise<void> {
res.render('url-shortener');
protected async getURLShrinker(req: Request, res: Response): Promise<void> {
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> {
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> {
@ -67,14 +72,15 @@ export default class URLRedirectController extends Controller {
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({
json: () => res.json({
url: urlRedirect.getURL(),
url: urlRedirect.getURL(domain),
}),
text: () => res.send(urlRedirect.getURL()),
text: () => res.send(urlRedirect.getURL(domain)),
html: () => {
req.flash('success', 'URL shortened successfully!');
req.flash('url', urlRedirect.getURL());
req.flash('success', 'URL shrunk successfully!');
req.flash('url', urlRedirect.getURL(domain));
res.redirectBack('/');
},
});

4
src/models/FileModel.ts

@ -39,8 +39,8 @@ export default class FileModel extends Model {
this.addProperty('ttl', new Validator().defined().min(0).max(4294967295));
}
public getURL(): string {
return config.get<string>('base_url') + Controller.route('get-file', {
public getURL(domain: string = config.get<string>('base_url')): string {
return (/^https?:\/\//.test(domain) ? '' : 'https://') + domain + Controller.route('get-file', {
slug: this.slug,
});
}

4
src/models/URLRedirect.ts

@ -35,8 +35,8 @@ export default class URLRedirect extends Model {
this.addProperty('created_at', new Validator());
}
public getURL(): string {
return config.get<string>('base_url') + Controller.route('get-url', {
public getURL(domain: string = config.get<string>('base_url')): string {
return (/^https?:\/\//.test(domain) ? '' : 'https://') + domain + Controller.route('get-url', {
slug: this.slug,
});
}

20
views/desktop-utility.njk

@ -22,7 +22,7 @@
<td><a href="{{ route('file-linux-script') }}">Download</a></td>
</tr>
<tr>
<td>shorten_url.sh</td>
<td>shrink_url.sh</td>
<td><a href="{{ route('url-linux-script') }}">Download</a></td>
</tr>
</tbody>
@ -32,8 +32,8 @@
<p>Examples:</p>
<pre>upload_file.sh path/to/file</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>shorten_url.sh https://gitlab.com/ArisuOngaku/ilyli repo</pre>
<pre>shrink_url.sh https://gitlab.com/ArisuOngaku/ilyli</pre>
<pre>shrink_url.sh https://gitlab.com/ArisuOngaku/ilyli repo</pre>
</section>
<hr>
@ -81,9 +81,15 @@
<td>No</td>
<td>0 (never delete), 30 (delete after 30s)</td>
</tr>
<tr>
<td>url_domain</td>
<td>Choose domain name</td>
<td>No</td>
<td>{{ allowed_domains.join('|') }}</td>
</tr>
<tr>
<th colspan="4">URL shorten</th>
<th colspan="4">URL shrink</th>
</tr>
<tr>
<td>type</td>
@ -97,6 +103,12 @@
<td>Yes</td>
<td>A valid URL starting with https:// or http://</td>
</tr>
<tr>
<td>url_domain</td>
<td>Choose domain name</td>
<td>No</td>
<td>{{ allowed_domains.join('|') }}</td>
</tr>
</tbody>
</table>
<p>For examples with curl, please download and review the scripts above.</p>

11
views/file-upload.njk

@ -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, '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.csrf(getCSRFToken) }}
@ -40,6 +40,15 @@
<div class="content"></div>
<button class="copy-button"><i data-feather="copy"></i></button>
</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>
</div>

2
views/layouts/base.njk

@ -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-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-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 %}
<li><a href="{{ route('backend') }}"><i data-feather="settings"></i> <span class="tip">Backend</span></a></li>
{% endif %}

14
views/url-shortener.njk → views/url-shrinker.njk

@ -1,28 +1,28 @@
{% extends 'layouts/base.njk' %}
{% set title = app.name + ' - URL shortener' %}
{% set title = app.name + ' - URL shrinker' %}
{% block scripts %}
<script src="/js/url-shortener.js"></script>
<script src="/js/url-shrinker.js"></script>
{% endblock %}
{% block body %}
<h1>Shorten URLs</h1>
<h1>Shrink URLs</h1>
<p>(no phishing allowed)</p>
<div class="container">
<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', '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.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>
{% set url = flash('url') %}
Loading…
Cancel
Save