Commit ac8d764b authored by Luc Didry's avatar Luc Didry Committed by Luc Didry

Add optionnal LDAP authentication for uploading files

parent 261d9b43
......@@ -3,6 +3,7 @@ requires "ORLite";
requires "Mojolicious::Plugin::DebugDumperHelper";
requires 'Mojolicious::Plugin::I18N';
requires 'Mojolicious::Plugin::Mail';
requires 'Mojolicious::Plugin::Authentication';
requires 'EV';
requires 'Filesys::DiskUsage';
requires 'Switch';
......@@ -13,3 +14,4 @@ requires 'Number::Bytes::Human';
requires 'Filesys::DfPortable';
requires 'Switch';
requires 'Data::Entropy';
requires 'Net::LDAP';
This diff is collapsed.
......@@ -3,6 +3,7 @@ package Lufi;
use Mojo::Base 'Mojolicious';
use LufiDB;
use Data::Entropy qw(entropy_source);
use Net::LDAP;
$ENV{MOJO_MAX_WEBSOCKET_SIZE} = 100485760; # 10 * 1024 * 1024 = 10MiB
......@@ -12,19 +13,20 @@ sub startup {
my $config = $self->plugin('Config' => {
default => {
provisioning => 100,
provis_step => 5,
length => 10,
token_length => 32,
secrets => ['hfudsifdsih'],
default_delay => 0,
max_delay => 0,
mail => {
provisioning => 100,
provis_step => 5,
length => 10,
token_length => 32,
secrets => ['hfudsifdsih'],
default_delay => 0,
max_delay => 0,
mail => {
how => 'sendmail'
},
mail_sender => 'no-reply@lufi.io',
theme => 'default',
upload_dir => 'files',
mail_sender => 'no-reply@lufi.io',
theme => 'default',
upload_dir => 'files',
session_duration => 3600,
}
});
......@@ -59,6 +61,55 @@ sub startup {
# Debug
$self->plugin('DebugDumperHelper');
# Authentication (if configured)
$self->plugin('authentication' =>
{
autoload_user => 1,
session_key => 'Dolomon',
load_user => sub {
my ($c, $username) = @_;
return $username;
},
validate_user => sub {
my ($c, $username, $password, $extradata) = @_;
my $ldap = Net::LDAP->new($c->config->{ldap}->{uri});
my $mesg = $ldap->bind($c->config->{ldap}->{bind_user}.$c->config->{ldap}->{bind_dn},
password => $c->config->{ldap}->{bind_pwd}
);
$mesg->code && die $mesg->error;
$mesg = $ldap->search(
base => $c->config->{ldap}->{user_tree},
filter => "(&(uid=$username)".$c->config->{ldap}->{user_filter}.")"
);
if ($mesg->code) {
$c->app->log->error($mesg->error);
return undef;
}
# Now we know that the user exists
$mesg = $ldap->bind('uid='.$username.$c->config->{ldap}->{bind_dn},
password => $password
);
if ($mesg->code) {
$c->app->log->error($mesg->error);
return undef;
}
return $username;
}
}
);
if (defined($self->config('ldap'))) {
$self->app->sessions->default_expiration($self->config('session_duration'));
}
# Secrets
$self->secrets($self->config('secrets'));
# Helpers
......@@ -183,9 +234,47 @@ sub startup {
# Page for files uploading
$r->get('/' => sub {
shift->render(template => 'index');
my $c = shift;
if (!defined($c->config('ldap')) || $c->is_user_authenticated) {
$c->render(template => 'index');
} else {
$c->redirect_to('login');
}
})->name('index');
if (defined $self->config('ldap')) {
# Login page
$r->get('/login' => sub {
my $c = shift;
if ($c->is_user_authenticated) {
$c->redirect_to('index');
} else {
$c->render(template => 'login');
}
});
# Authentication
$r->post('/login' => sub {
my $c = shift;
my $login = $c->param('login');
my $pwd = $c->param('password');
if($c->authenticate($login, $pwd)) {
$c->redirect_to('index');
} else {
$c->stash(msg => $c->l('Please, check your credentials: unable to authenticate.'));
$c->render(template => 'login');
}
});
# Logout page
$r->get('/logout' => sub {
my $c = shift;
if ($c->is_user_authenticated) {
$c->logout;
}
$c->render(template => 'logout');
})->name('logout');
}
# About page
$r->get('/about' => sub {
shift->render(template => 'about');
......@@ -196,9 +285,14 @@ sub startup {
to('Files#r')->
name('render');
# List of files (use localstorage, so the server know nothing about files
# List of files (use localstorage, so the server know nothing about files)
$r->get('/files' => sub {
shift->render(template => 'files');
my $c = shift;
if (!defined($c->config('ldap')) || $c->is_user_authenticated) {
$c->render(template => 'files');
} else {
$c->redirect_to('login');
}
})->name('files');
# Get counter informations about a file
......
This diff is collapsed.
......@@ -115,6 +115,23 @@
# optional, default is 'files'
#upload_dir => 'files',
# set `ldap` if you want that only authenticated users can upload files
# please note that everybody can still download files
# optional, no default
#ldap => {
# uri => 'ldaps://ldap.example.org',
# user_tree => 'ou=users,dc=example,dc=org',
# bind_dn => ',ou=users,dc=example,dc=org',
# bind_user => 'uid=ldap_user',
# bind_pwd => 'secr3t',
# user_filter => '!(uid=ldap_user)'
#},
# if you setted ldap above, the session will last `session_duration` seconds before
# the user needs to reauthenticate
# optional, default is 3600
#session_duration => 3600,
#########################
# Lufi cron jobs settings
#########################
......@@ -138,5 +155,5 @@
# images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
# if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
# optional, no default
#delete_no_longer_viewed_files => 90
#delete_no_longer_viewed_files => 90,
};
......@@ -37,7 +37,7 @@ msgstr ""
msgid "A thank you with a photo of kitten on <a href=\"https://framasphere.org/people/b13eb6b0beac0131e7e32a0000053625\" class=\"classic\">Diaspora*</a> or <a href=\"https://twitter.com/framasky\" class=\"classic\">Twitter</a> is cool too ;-)"
msgstr ""
#: themes/default/templates/layouts/default.html.ep:36 themes/default/templates/layouts/default.html.ep:41
#: themes/default/templates/layouts/default.html.ep:40 themes/default/templates/layouts/default.html.ep:52
msgid "About"
msgstr ""
......@@ -74,11 +74,15 @@ msgstr ""
msgid "Copy to clipboard"
msgstr ""
#: lib/Lufi/Controller/Files.pm:298
#: lib/Lufi/Controller/Files.pm:328
msgid "Could not delete the file. You are not authenticated."
msgstr ""
#: lib/Lufi/Controller/Files.pm:312
msgid "Could not find the file. Are you sure of the URL and the token?"
msgstr ""
#: lib/Lufi/Controller/Files.pm:226
#: lib/Lufi/Controller/Files.pm:228
msgid "Could not find the file. Are you sure of the URL?"
msgstr ""
......@@ -130,15 +134,15 @@ msgstr ""
msgid "Encrypting part XX1 of XX2"
msgstr ""
#: lib/Lufi/Controller/Files.pm:162
#: lib/Lufi/Controller/Files.pm:164
msgid "Error: the file existed but was deleted."
msgstr ""
#: lib/Lufi/Controller/Files.pm:203
#: lib/Lufi/Controller/Files.pm:205
msgid "Error: the file has not been sent entirely."
msgstr ""
#: lib/Lufi/Controller/Files.pm:208
#: lib/Lufi/Controller/Files.pm:210
msgid "Error: unable to find the file. Are you sure of your URL?"
msgstr ""
......@@ -154,7 +158,7 @@ msgstr ""
msgid "Export localStorage data"
msgstr ""
#: lib/Lufi/Controller/Files.pm:282
#: lib/Lufi/Controller/Files.pm:296
msgid "File deleted"
msgstr ""
......@@ -222,16 +226,24 @@ msgstr ""
msgid "Javascript is disabled. You won't be able to use Lufi."
msgstr ""
#: themes/default/templates/login.html.ep:15
msgid "Login"
msgstr ""
#: themes/default/templates/layouts/default.html.ep:42 themes/default/templates/layouts/default.html.ep:54
msgid "Logout"
msgstr ""
#: themes/default/templates/about.html.ep:4
msgid "Lufi is a free (as in free speech) file hosting software."
msgstr ""
#: themes/default/templates/files.html.ep:3 themes/default/templates/layouts/default.html.ep:35 themes/default/templates/layouts/default.html.ep:40
#: themes/default/templates/files.html.ep:3 themes/default/templates/layouts/default.html.ep:36 themes/default/templates/layouts/default.html.ep:48
msgid "My files"
msgstr ""
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:49
#: lib/Lufi/Controller/Files.pm:50
msgid "No enough space available on the server for this file (size: %1)."
msgstr ""
......@@ -243,6 +255,10 @@ msgstr ""
msgid "Only the files sent with this browser will be listed here. This list is stored in localStorage: if you delete your localStorage data, you'll lose this list."
msgstr ""
#: themes/default/templates/login.html.ep:21
msgid "Password"
msgstr ""
#. (config('contact')
#: themes/default/templates/about.html.ep:13
msgid "Please contact the administrator: %1"
......@@ -285,11 +301,15 @@ msgstr ""
msgid "Share your files in total privacy on %1"
msgstr ""
#: themes/default/templates/layouts/default.html.ep:38 themes/default/templates/layouts/default.html.ep:50 themes/default/templates/login.html.ep:26 themes/default/templates/logout.html.ep:8
msgid "Signin"
msgstr ""
#: themes/default/templates/index.html.ep:30
msgid "Sorry, the uploading is currently disabled. Please try again later."
msgstr ""
#: lib/Lufi/Controller/Files.pm:37
#: lib/Lufi/Controller/Files.pm:38
msgid "Sorry, uploading is disabled."
msgstr ""
......@@ -309,7 +329,7 @@ msgstr ""
msgid "The email subject can't be empty."
msgstr ""
#: lib/Lufi/Controller/Files.pm:279
#: lib/Lufi/Controller/Files.pm:293
msgid "The file has already been deleted"
msgstr ""
......@@ -335,7 +355,7 @@ msgstr ""
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>. If you want to support him, you can do it via <a href=\"https://flattr.com/submit/auto?user_id=_SKy_&amp;url=%1&amp;title=Lufi&amp;category=software\" class=\"classic\">Flattr</a> or with <a href=\"bitcoin:1CJYU2uGmPKhvithCGntyniTTe2hofpPX3?label=Lufi\" class=\"classic\">Bitcoin</a>."
msgstr ""
#: lib/Lufi/Controller/Files.pm:122
#: lib/Lufi/Controller/Files.pm:123
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
msgstr ""
......@@ -348,16 +368,21 @@ msgid "Unable to copy the link(s) to your clipboard"
msgstr ""
#. ($short)
#: lib/Lufi/Controller/Files.pm:263
#: lib/Lufi/Controller/Files.pm:266
msgid "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
msgstr ""
#. ($short)
#: lib/Lufi/Controller/Files.pm:253
#: lib/Lufi/Controller/Files.pm:256
msgid "Unable to get counter for %1. The token is invalid."
msgstr ""
#: themes/default/templates/layouts/default.html.ep:34 themes/default/templates/layouts/default.html.ep:39
#. ($short)
#: lib/Lufi/Controller/Files.pm:276
msgid "Unable to get counter for %1. You are not authenticated."
msgstr ""
#: themes/default/templates/layouts/default.html.ep:35 themes/default/templates/layouts/default.html.ep:47
msgid "Upload files"
msgstr ""
......@@ -401,12 +426,16 @@ msgstr ""
msgid "You have attempted to leave this page. The upload will be canceled. Are you sure?"
msgstr ""
#: themes/default/templates/logout.html.ep:5
msgid "You have been successfully logged out."
msgstr ""
#: lib/Lufi/Controller/Mail.pm:30
msgid "You must give email addresses."
msgstr ""
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:43
#: lib/Lufi/Controller/Files.pm:44
msgid "Your file is too big: %1 (maximum size allowed: %2)"
msgstr ""
......
......@@ -39,7 +39,7 @@ msgstr " :"
msgid "A thank you with a photo of kitten on <a href=\"https://framasphere.org/people/b13eb6b0beac0131e7e32a0000053625\" class=\"classic\">Diaspora*</a> or <a href=\"https://twitter.com/framasky\" class=\"classic\">Twitter</a> is cool too ;-)"
msgstr "Un merci avec une photo de chaton sur <a href=\"https://framasphere.org/people/b13eb6b0beac0131e7e32a0000053625\" class=\"classic\">Diaspora*</a> ou <a href=\"https://twitter.com/framasky\" class=\"classic\">Twitter</a> fait aussi l’affaire ;-)"
#: themes/default/templates/layouts/default.html.ep:36 themes/default/templates/layouts/default.html.ep:41
#: themes/default/templates/layouts/default.html.ep:40 themes/default/templates/layouts/default.html.ep:52
msgid "About"
msgstr "À propos"
......@@ -76,11 +76,15 @@ msgstr "Copier tous les liens dans le presse-papier"
msgid "Copy to clipboard"
msgstr "Copier dans le presse-papier"
#: lib/Lufi/Controller/Files.pm:298
#: lib/Lufi/Controller/Files.pm:328
msgid "Could not delete the file. You are not authenticated."
msgstr "Impossible de supprimer le fichier. Vous n'êtes pas connecté·e."
#: lib/Lufi/Controller/Files.pm:312
msgid "Could not find the file. Are you sure of the URL and the token?"
msgstr "Impossible de retrouver le fichier. Êtes-vous sûr(e) que l’URL et le jeton sont les bons ?"
#: lib/Lufi/Controller/Files.pm:226
#: lib/Lufi/Controller/Files.pm:228
msgid "Could not find the file. Are you sure of the URL?"
msgstr "Impossible de retrouver le fichier. Êtes-vous sûr(e) que l’URL est la bonne ?"
......@@ -132,15 +136,15 @@ msgstr "Mails"
msgid "Encrypting part XX1 of XX2"
msgstr "Chiffrement du fragment XX1 sur XX2"
#: lib/Lufi/Controller/Files.pm:162
#: lib/Lufi/Controller/Files.pm:164
msgid "Error: the file existed but was deleted."
msgstr "Erreur : le fichier existait mais a été supprimé"
#: lib/Lufi/Controller/Files.pm:203
#: lib/Lufi/Controller/Files.pm:205
msgid "Error: the file has not been sent entirely."
msgstr "Erreur : le fichier n’a pas été envoyé dans son intégralité"
#: lib/Lufi/Controller/Files.pm:208
#: lib/Lufi/Controller/Files.pm:210
msgid "Error: unable to find the file. Are you sure of your URL?"
msgstr "Erreur : impossible de retrouver le fichier. Êtes-vous sûr(e) de l’URL ?"
......@@ -156,7 +160,7 @@ msgstr "Expire le"
msgid "Export localStorage data"
msgstr "Exporter les données localStorage"
#: lib/Lufi/Controller/Files.pm:282
#: lib/Lufi/Controller/Files.pm:296
msgid "File deleted"
msgstr "Fichier supprimé"
......@@ -224,16 +228,24 @@ msgstr "Il semble que la clé dans votre URL soit incorrecte. Veuillez vérifier
msgid "Javascript is disabled. You won't be able to use Lufi."
msgstr "Javascript est désactivé. Lufi ne fonctionnera pas."
#: themes/default/templates/login.html.ep:15
msgid "Login"
msgstr "Identifiant"
#: themes/default/templates/layouts/default.html.ep:42 themes/default/templates/layouts/default.html.ep:54
msgid "Logout"
msgstr "Déconnexion"
#: themes/default/templates/about.html.ep:4
msgid "Lufi is a free (as in free speech) file hosting software."
msgstr "Lufi est un logiciel libre d’hébergement de fichiers."
#: themes/default/templates/files.html.ep:3 themes/default/templates/layouts/default.html.ep:35 themes/default/templates/layouts/default.html.ep:40
#: themes/default/templates/files.html.ep:3 themes/default/templates/layouts/default.html.ep:36 themes/default/templates/layouts/default.html.ep:48
msgid "My files"
msgstr "Mes fichiers"
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:49
#: lib/Lufi/Controller/Files.pm:50
msgid "No enough space available on the server for this file (size: %1)."
msgstr "Espace disque insuffisant sur le serveur pour ce fichier (taille du fichier: %1)."
......@@ -245,6 +257,10 @@ msgstr "Pas de délai d’expiration"
msgid "Only the files sent with this browser will be listed here. This list is stored in localStorage: if you delete your localStorage data, you'll lose this list."
msgstr "Seuls les fichiers envoyés avec ce navigateur web sont listés ici. Les informations sont stockées en localStorage : si vous supprimez vos données localStorage, vous perdrez ces informations."
#: themes/default/templates/login.html.ep:21
msgid "Password"
msgstr "Mot de passe"
#. (config('contact')
#: themes/default/templates/about.html.ep:13
msgid "Please contact the administrator: %1"
......@@ -287,11 +303,15 @@ msgstr "Envoi du fragment XX1 sur XX2"
msgid "Share your files in total privacy on %1"
msgstr "Partagez vos fichiers en toute confidentialité sur %1"
#: themes/default/templates/layouts/default.html.ep:38 themes/default/templates/layouts/default.html.ep:50 themes/default/templates/login.html.ep:26 themes/default/templates/logout.html.ep:8
msgid "Signin"
msgstr "Connexion"
#: themes/default/templates/index.html.ep:30
msgid "Sorry, the uploading is currently disabled. Please try again later."
msgstr "Désolé, l’envoi de fichier est actuellement désactivé. Veuillez réessayer plus tard."
#: lib/Lufi/Controller/Files.pm:37
#: lib/Lufi/Controller/Files.pm:38
msgid "Sorry, uploading is disabled."
msgstr "Désolé, l’envoi de fichier est désactivé."
......@@ -311,7 +331,7 @@ msgstr "Le corps du mail ne peut être vide."
msgid "The email subject can't be empty."
msgstr "Le sujet du mail ne peut être vide."
#: lib/Lufi/Controller/Files.pm:279
#: lib/Lufi/Controller/Files.pm:293
msgid "The file has already been deleted"
msgstr "Le fichier a déjà été supprimé"
......@@ -337,7 +357,7 @@ msgstr "Le mail a été envoyé."
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>. If you want to support him, you can do it via <a href=\"https://flattr.com/submit/auto?user_id=_SKy_&amp;url=%1&amp;title=Lufi&amp;category=software\" class=\"classic\">Flattr</a> or with <a href=\"bitcoin:1CJYU2uGmPKhvithCGntyniTTe2hofpPX3?label=Lufi\" class=\"classic\">Bitcoin</a>."
msgstr "L’auteur originel (et pour l’instant, le seul) est <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>. Si vous avez envie de le supporter, vous pouvez le faire via <a href=\"https://flattr.com/submit/auto?user_id=_SKy_&amp;url=%1&amp;title=Lufi&amp;category=software\" class=\"classic\">Flattr</a> ou en <a href=\"bitcoin:1CJYU2uGmPKhvithCGntyniTTe2hofpPX3?label=Lufi\" class=\"classic\">Bitcoin</a>."
#: lib/Lufi/Controller/Files.pm:122
#: lib/Lufi/Controller/Files.pm:123
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
msgstr "Le serveur a été incapable de retrouver l’enregistrement du fichier auquel ajouter votre fragment de fichier. Veuillez contacter l'administrateur."
......@@ -350,16 +370,21 @@ msgid "Unable to copy the link(s) to your clipboard"
msgstr "Impossible de copier le(s) lien(s) dans votre presse-papier"
#. ($short)
#: lib/Lufi/Controller/Files.pm:263
#: lib/Lufi/Controller/Files.pm:266
msgid "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
msgstr "Impossible de récupérer le compteur pour %1. Le fichier n’existe pas. Il va être supprimé de votre localStorage."
#. ($short)
#: lib/Lufi/Controller/Files.pm:253
#: lib/Lufi/Controller/Files.pm:256
msgid "Unable to get counter for %1. The token is invalid."
msgstr "Impossible de récupérer le compteur pour %1. Le jeton est invalide."
#: themes/default/templates/layouts/default.html.ep:34 themes/default/templates/layouts/default.html.ep:39
#. ($short)
#: lib/Lufi/Controller/Files.pm:276
msgid "Unable to get counter for %1. You are not authenticated."
msgstr "Impossible de récupérer le compteur pour %1. Vous n'êtes pas connecté·e."
#: themes/default/templates/layouts/default.html.ep:35 themes/default/templates/layouts/default.html.ep:47
msgid "Upload files"
msgstr "Envoyer des fichiers"
......@@ -403,12 +428,16 @@ msgstr "Vous essayez de quitter la page. Le téléchargement sera annulé. Êtes
msgid "You have attempted to leave this page. The upload will be canceled. Are you sure?"
msgstr "Vous essayez de quitter la page. L’envoi sera annulé. Êtes-vous sûr(e) ?"
#: themes/default/templates/logout.html.ep:5
msgid "You have been successfully logged out."
msgstr "Vous avez été déconnecté·e avec succès."
#: lib/Lufi/Controller/Mail.pm:30
msgid "You must give email addresses."
msgstr "Vous devez envoyer des adresses mail."
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:43
#: lib/Lufi/Controller/Files.pm:44
msgid "Your file is too big: %1 (maximum size allowed: %2)"
msgstr "Votre fichier est trop volumineux : %1 (la taille maximum autorisée est %2)"
......
......@@ -31,14 +31,28 @@
<a href="<%= url_for('/') %>" class="brand-logo">&nbsp;<img src="<%= url_for('/img/lufi-min.png') %>" alt="logo"> Lufi</a>
<a href="#" data-activates="mobile-demo" class="button-collapse"><i class="mdi-navigation-menu"></i></a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
% if (!defined(config('ldap')) || is_user_authenticated()) {
<li<%== ' class="active"' if (current_route eq 'index') %>><a href="<%= url_for('/') %>"><%= l('Upload files') %></a></li>
<li<%== ' class="active"' if (current_route eq 'files') %>><a href="<%= url_for('/files') %>"><%= l('My files') %></a></li>
% } else {
<li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li>
% }
<li<%== ' class="active"' if (current_route eq 'about') %>><a href="<%= url_for('/about') %>"><%= l('About') %></a></li>
% if (defined(config('ldap')) && is_user_authenticated()) {
<li><a href="<%= url_for('/logout') %>"><%= l('Logout') %></a></li>
% }
</ul>
<ul id="mobile-demo" class="side-nav">
% if (!defined(config('ldap')) || is_user_authenticated()) {
<li<%== ' class="active"' if (current_route eq 'index') %>><a href="<%= url_for('/') %>"><%= l('Upload files') %></a></li>
<li<%== ' class="active"' if (current_route eq 'files') %>><a href="<%= url_for('/files') %>"><%= l('My files') %></a></li>
% } else {
<li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li>
% }
<li<%== ' class="active"' if (current_route eq 'about') %>><a href="<%= url_for('/about') %>"><%= l('About') %></a></li>
% if (defined(config('ldap')) && is_user_authenticated()) {
<li><a href="<%= url_for('/logout') %>"><%= l('Logout') %></a></li>
% }
</ul>
</div>
</nav>
......
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
% if (defined stash('msg')) {
<div class="col s12">
<div class="card pink">
<div class="card-content white-text">
<strong><%= stash('msg') %></strong>
</div>
</div>
</div>
% }
<form class="row" method="post" action="<%= url_for('login') %>">
<div class="col s8 m8 offset-s2 offset-m2">
<div class="input-field">
<input id="login" type="text" class="validate" name="login">
<label for="login"><%= l('Login') %></label>
</div>
</div>
<div class="col s8 m8 offset-s2 offset-m2">
<div class="input-field">
<input id="password" type="password" class="validate" name="password">
<label for="password"><%= l('Password') %></label>
</div>
</div>
<div class="col s8 m8 offset-s2 offset-m2">
<button class="btn waves-effect waves-light" type="submit" name="action">
<%= l('Signin') %>
</button>
</div>
</form>
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
<div class="col s12">
<div class="card blue-grey darken-1">
<div class="card-content white-text">
<strong><%= l('You have been successfully logged out.') %></strong>
</div>
<div class="card-action">
<a href="<%= url_for('login') %>"><%= l('Signin') %></a>
</div>
</div>
</div>
......@@ -6,5 +6,7 @@ themes/default/templates/mail.html.ep
themes/default/templates/msg.html.ep
themes/default/templates/render.html.ep
themes/default/templates/about.html.ep
themes/default/templates/login.html.ep
themes/default/templates/logout.html.ep
lib/Lufi/Controller/Files.pm
lib/Lufi/Controller/Mail.pm
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment