Branding and auth views

This commit is contained in:
Alice Gaudon 2020-06-14 15:15:15 +02:00
parent 6fd4f167f3
commit fae5e54066
10 changed files with 138 additions and 11 deletions

View File

@ -4,6 +4,6 @@ document.addEventListener('DOMContentLoaded', () => {
neverExpireCheckbox.addEventListener('change', () => { neverExpireCheckbox.addEventListener('change', () => {
// noinspection RedundantConditionalExpressionJS // noinspection RedundantConditionalExpressionJS
expireAfterDaysField.disabled = neverExpireCheckbox.value ? true : false; expireAfterDaysField.disabled = neverExpireCheckbox.checked ? true : false;
}); });
}); });

View File

@ -1,8 +1,8 @@
{ {
"name": "aldap", "name": "ily.li",
"version": "0.1.0", "version": "0.1.0",
"description": "Authentication LDAP server", "description": "Self-hosted file pusher",
"repository": "git@gitlab.com:ArisuOngaku/aldap.git", "repository": "git@gitlab.com:ArisuOngaku/ily.li.git",
"author": "Alice Gaudon <alice@gaudon.pro>", "author": "Alice Gaudon <alice@gaudon.pro>",
"private": true, "private": true,
"main": "dist/main.js", "main": "dist/main.js",

View File

@ -3,7 +3,8 @@ import {Request, Response} from "express";
export default class AboutController extends Controller { export default class AboutController extends Controller {
routes(): void { routes(): void {
this.get('/about', this.getAbout, 'about'); this.get('/', this.getAbout, 'home');
this.get('/', this.getAbout, 'about');
} }
private async getAbout(req: Request, res: Response) { private async getAbout(req: Request, res: Response) {

View File

@ -118,12 +118,15 @@ export default class FileController extends Controller {
return slug; return slug;
} }
i++; i++;
} while (i < tries) } while (i < tries);
throw new ServerError('Failed to generate slug; newly generated slug size should be increased by 1.'); throw new ServerError('Failed to generate slug; newly generated slug size should be increased by 1.');
} }
} }
const FILE_UPLOAD_MAX_SIZE_MIDDLEWARE = express.urlencoded({limit: config.get<string>('max_upload_size')}); const FILE_UPLOAD_MAX_SIZE_MIDDLEWARE = express.urlencoded({
limit: config.get<string>('max_upload_size'),
extended: true,
});
const FILE_UPLOAD_MIDDLEWARE = fileUpload({ const FILE_UPLOAD_MIDDLEWARE = fileUpload({
tempFileDir: 'storage/tmp', tempFileDir: 'storage/tmp',

View File

@ -1,8 +1,9 @@
import Logger from "wms-core/Logger"; import Logger from "wms-core/Logger";
import App from "./App"; import App from "./App";
import config from "config";
(async () => { (async () => {
const app = new App(4899); const app = new App(config.get<number>('port'));
await app.start(); await app.start();
})().catch(err => { })().catch(err => {
Logger.error(err); Logger.error(err);

42
views/auth.njk Normal file
View File

@ -0,0 +1,42 @@
{% extends 'layouts/base.njk' %}
{% import 'macros.njk' as macros %}
{% set title = 'Authentication / Registration' %}
{% set decription = 'Join Watch My Stream and power up your streams!' %}
{% set h1 = 'Authentication and registration' %}
{% block body %}
<div class="container">
<div class="panel">
{% if register_confirm_email %}
<form action="/auth" method="POST" id="register-form">
<h2>Register</h2>
{{ macros.message('question', 'Do you wish to create a new account with ' + register_confirm_email + '?', false, false) }}
{{ macros.message('warning', 'If you already have an account, please log in with your existing email first and then add your new email in the Account page.', false, true) }}
<input type="hidden" name="email" value="{{ register_confirm_email }}">
<input type="hidden" name="confirm_register" value="confirm">
<div class="form-field">
<div class="form-display">Email: {{ register_confirm_email }}</div>
</div>
<a href="/auth" class="button transparent">Go back</a>
<button type="submit" class="primary">Register</button>
{{ macros.csrf(getCSRFToken) }}
</form>
{% else %}
<form action="/auth" method="POST" id="login-form">
<h2>Log in or register</h2>
{# {{ macros.message('info', 'If we don\'t find your email address in our database, you will be able to register.', false, true) }}#}
<div class="input-field">
{{ macros.field(_locals, 'email', 'email', query.email or '', 'Your email address', "If we don't find your email address in our database, you will be able to register.", 'required') }}
</div>
<button type="submit">Authenticate</button>
{{ macros.csrf(getCSRFToken) }}
</form>
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -12,12 +12,15 @@
{% endblock %} {% endblock %}
{% block header %} {% block header %}
<a href="/" class="logo"><img src="/img/logo.svg" alt="Logo"> Example app</a> <a href="/" class="logo"><img src="/img/logo.svg" alt="Logo"> ily.li</a>
<nav> <nav>
<ul> <ul>
<li><a href="{{ route('about') }}"><i data-feather="info"></i> About</a></li> <li><a href="{{ route('about') }}"><i data-feather="info"></i> About</a></li>
{% if user %} {% if user %}
<li><a href="{{ route('file-manager') }}"><i data-feather="folder"></i>File manager</a></li> <li><a href="{{ route('file-manager') }}"><i data-feather="folder"></i>File manager</a></li>
<li><a href="{{ route('logout') }}"><i data-feather="logout"></i> Logout</a></li>
{% else %}
<li><a href="{{ route('auth') }}"><i data-feather="user"></i> Login / Register</a></li>
{% endif %} {% endif %}
</ul> </ul>
</nav> </nav>
@ -40,4 +43,4 @@
</main> </main>
{% endblock %} {% endblock %}
{% block footer %}Example app v{{ app_version }} - all rights reserved.{% endblock %} {% block footer %}ily.li v{{ app_version }} - all rights reserved.{% endblock %}

19
views/magic_link.njk Normal file
View File

@ -0,0 +1,19 @@
{% extends 'layouts/base.njk' %}
{% import 'macros.njk' as macros %}
{% set actionType = magicLink.action_type %}
{% set title = 'WMS: Magic Link' + (' - ' + actionType if actionType) %}
{% set h1 = 'Magic Link' + (' - ' + actionType if actionType) %}
{% block body %}
<div class="container">
<div class="panel">
{% if err %}
{{ macros.message('error', err) }}
{% else %}
{{ macros.message('success', 'Success!') }}
<p>You can now close this page.</p>
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,58 @@
{% extends 'layouts/base.njk' %}
{% import 'macros.njk' as macros %}
{% set title = 'Authentication lobby' %}
{% set h1 = 'Authentication lobby' %}
{% block body %}
<div class="container">
<div class="panel">
{{ macros.message('success', 'We sent a link to ' + email + '. To authenticate, open it from any device.') }}
{{ macros.message('info', 'This link will be valid for <span id="countdown"></span> and can only be used once.', true, true) }}
<p class="center">Waiting for you to open the link...</p>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
const validUntil = {{ validUntil }}.0;
function isValid() {
return new Date().getTime() < validUntil;
}
function websocketListen(websocket, e) {
if (e.data === 'refresh') {
window.location.reload();
}
}
document.addEventListener('DOMContentLoaded', () => {
const countdown = document.getElementById('countdown');
if (!isValid()) return;
function animateCountdown() {
requestAnimationFrame(() => {
let diff = Math.max(0, validUntil - new Date().getTime());
if (diff === 0) {
return;
}
diff /= 1000;
const seconds = Math.floor(diff % 60).toFixed(0);
const minutes = Math.floor((diff - seconds) / 60).toFixed(0);
countdown.innerText = `${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
animateCountdown();
});
}
animateCountdown();
});
</script>
{{ macros.websocket(websocketUrl, 'websocketListen', 1, 'isValid') }}
{% endblock %}