diff --git a/cpanfile b/cpanfile index d59815e..b006806 100644 --- a/cpanfile +++ b/cpanfile @@ -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'; diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 4927ff6..38d6810 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -1,5 +1,26 @@ # carton snapshot format: version 1.0 DISTRIBUTIONS + Authen-SASL-2.16 + pathname: G/GB/GBARR/Authen-SASL-2.16.tar.gz + provides: + Authen::SASL 2.16 + Authen::SASL::CRAM_MD5 2.14 + Authen::SASL::EXTERNAL 2.14 + Authen::SASL::Perl 2.14 + Authen::SASL::Perl::ANONYMOUS 2.14 + Authen::SASL::Perl::CRAM_MD5 2.14 + Authen::SASL::Perl::DIGEST_MD5 2.14 + Authen::SASL::Perl::EXTERNAL 2.14 + Authen::SASL::Perl::GSSAPI 0.05 + Authen::SASL::Perl::LOGIN 2.14 + Authen::SASL::Perl::Layer 2.14 + Authen::SASL::Perl::PLAIN 2.14 + requirements: + Digest::HMAC_MD5 0 + Digest::MD5 0 + ExtUtils::MakeMaker 6.42 + Test::More 0 + perl 5.005 CPAN-Meta-2.150005 pathname: D/DA/DAGOLDEN/CPAN-Meta-2.150005.tar.gz provides: @@ -29,6 +50,14 @@ DISTRIBUTIONS Canary::Stability 2006 requirements: ExtUtils::MakeMaker 0 + Convert-ASN1-0.27 + pathname: G/GB/GBARR/Convert-ASN1-0.27.tar.gz + provides: + Convert::ASN1 0.27 + requirements: + ExtUtils::MakeMaker 6.30 + Math::BigInt 1.997 + Test::More 0.90 Crypt-Rijndael-1.13 pathname: L/LE/LEONT/Crypt-Rijndael-1.13.tar.gz provides: @@ -193,10 +222,21 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - EV-4.21 - pathname: M/ML/MLEHMANN/EV-4.21.tar.gz + Digest-HMAC-1.03 + pathname: G/GA/GAAS/Digest-HMAC-1.03.tar.gz provides: - EV 4.21 + Digest::HMAC 1.03 + Digest::HMAC_MD5 1.01 + Digest::HMAC_SHA1 1.03 + requirements: + Digest::MD5 2 + Digest::SHA 1 + ExtUtils::MakeMaker 0 + perl 5.004 + EV-4.22 + pathname: M/ML/MLEHMANN/EV-4.22.tar.gz + provides: + EV 4.22 EV::MakeMaker undef requirements: Canary::Stability 0 @@ -212,16 +252,38 @@ DISTRIBUTIONS Time::Local 0 strict 0 warnings 0 - Email-Valid-1.196 - pathname: R/RJ/RJBS/Email-Valid-1.196.tar.gz + Email-Valid-1.200 + pathname: R/RJ/RJBS/Email-Valid-1.200.tar.gz provides: - Email::Valid 1.196 + Email::Valid 1.200 requirements: ExtUtils::MakeMaker 0 Mail::Address 0 Scalar::Util 0 Test::More 0 perl 5.006 + Encode-Locale-1.05 + pathname: G/GA/GAAS/Encode-Locale-1.05.tar.gz + provides: + Encode::Locale 1.05 + requirements: + Encode 2 + Encode::Alias 0 + ExtUtils::MakeMaker 0 + perl 5.008 + File-Listing-6.04 + pathname: G/GA/GAAS/File-Listing-6.04.tar.gz + provides: + File::Listing 6.04 + File::Listing::apache 6.04 + File::Listing::dosftp 6.04 + File::Listing::netware 6.04 + File::Listing::unix 6.04 + File::Listing::vms 6.04 + requirements: + ExtUtils::MakeMaker 0 + HTTP::Date 6 + perl 5.006002 File-Remove-1.52 pathname: A/AD/ADAMK/File-Remove-1.52.tar.gz provides: @@ -249,6 +311,62 @@ DISTRIBUTIONS File::Temp 0 Test::More 0 Test::Warn 0 + HTML-Parser-3.72 + pathname: G/GA/GAAS/HTML-Parser-3.72.tar.gz + provides: + HTML::Entities 3.69 + HTML::Filter 3.72 + HTML::HeadParser 3.71 + HTML::LinkExtor 3.69 + HTML::Parser 3.72 + HTML::PullParser 3.57 + HTML::TokeParser 3.69 + requirements: + ExtUtils::MakeMaker 0 + HTML::Tagset 3 + XSLoader 0 + perl 5.008 + HTML-Tagset-3.20 + pathname: P/PE/PETDANCE/HTML-Tagset-3.20.tar.gz + provides: + HTML::Tagset 3.20 + requirements: + ExtUtils::MakeMaker 0 + HTTP-Cookies-6.01 + pathname: G/GA/GAAS/HTTP-Cookies-6.01.tar.gz + provides: + HTTP::Cookies 6.01 + HTTP::Cookies::Microsoft 6.00 + HTTP::Cookies::Netscape 6.00 + requirements: + ExtUtils::MakeMaker 0 + HTTP::Date 6 + HTTP::Headers::Util 6 + Time::Local 0 + perl 5.008001 + HTTP-Daemon-6.01 + pathname: G/GA/GAAS/HTTP-Daemon-6.01.tar.gz + provides: + HTTP::Daemon 6.01 + HTTP::Daemon::ClientConn 6.01 + requirements: + ExtUtils::MakeMaker 0 + HTTP::Date 6 + HTTP::Request 6 + HTTP::Response 6 + HTTP::Status 6 + IO::Socket 0 + LWP::MediaTypes 6 + Sys::Hostname 0 + perl 5.008001 + HTTP-Date-6.02 + pathname: G/GA/GAAS/HTTP-Date-6.02.tar.gz + provides: + HTTP::Date 6.02 + requirements: + ExtUtils::MakeMaker 0 + Time::Local 0 + perl 5.006002 HTTP-Lite-2.44 pathname: N/NE/NEILB/HTTP-Lite-2.44.tar.gz provides: @@ -260,6 +378,80 @@ DISTRIBUTIONS perl 5.005 strict 0 warnings 0 + HTTP-Message-6.11 + pathname: E/ET/ETHER/HTTP-Message-6.11.tar.gz + provides: + HTTP::Config 6.11 + HTTP::Headers 6.11 + HTTP::Headers::Auth 6.11 + HTTP::Headers::ETag 6.11 + HTTP::Headers::Util 6.11 + HTTP::Message 6.11 + HTTP::Request 6.11 + HTTP::Request::Common 6.11 + HTTP::Response 6.11 + HTTP::Status 6.11 + requirements: + Compress::Raw::Zlib 0 + Encode 2.21 + Encode::Locale 1 + Exporter 5.57 + ExtUtils::MakeMaker 0 + HTTP::Date 6 + IO::Compress::Bzip2 2.021 + IO::Compress::Deflate 0 + IO::Compress::Gzip 0 + IO::HTML 0 + IO::Uncompress::Bunzip2 2.021 + IO::Uncompress::Gunzip 0 + IO::Uncompress::Inflate 0 + IO::Uncompress::RawInflate 0 + LWP::MediaTypes 6 + MIME::Base64 2.1 + MIME::QuotedPrint 0 + URI 1.10 + perl 5.008001 + HTTP-Negotiate-6.01 + pathname: G/GA/GAAS/HTTP-Negotiate-6.01.tar.gz + provides: + HTTP::Negotiate 6.01 + requirements: + ExtUtils::MakeMaker 0 + HTTP::Headers 6 + perl 5.008001 + IO-HTML-1.001 + pathname: C/CJ/CJM/IO-HTML-1.001.tar.gz + provides: + IO::HTML 1.001 + requirements: + Carp 0 + Encode 2.10 + Exporter 5.57 + ExtUtils::MakeMaker 6.30 + IO-Socket-IP-0.37 + pathname: P/PE/PEVANS/IO-Socket-IP-0.37.tar.gz + provides: + IO::Socket::IP 0.37 + requirements: + IO::Socket 0 + Socket 1.97 + Test::More 0.88 + IO-Socket-SSL-2.027 + pathname: S/SU/SULLR/IO-Socket-SSL-2.027.tar.gz + provides: + IO::Socket::SSL 2.027 + IO::Socket::SSL::Intercept 2.014 + IO::Socket::SSL::OCSP_Cache 2.027 + IO::Socket::SSL::OCSP_Resolver 2.027 + IO::Socket::SSL::PublicSuffix undef + IO::Socket::SSL::SSL_Context 2.027 + IO::Socket::SSL::SSL_HANDLE 2.027 + IO::Socket::SSL::Session_Cache 2.027 + IO::Socket::SSL::Utils 2.014 + requirements: + ExtUtils::MakeMaker 0 + Net::SSLeay 1.46 + Scalar::Util 0 IPC-Run3-0.048 pathname: R/RJ/RJBS/IPC-Run3-0.048.tar.gz provides: @@ -268,6 +460,22 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 Test::More 0.31 Time::HiRes 0 + JSON-2.90 + pathname: M/MA/MAKAMAKA/JSON-2.90.tar.gz + provides: + JSON 2.90 + JSON::Backend::PP 2.90 + JSON::Boolean 2.90 + requirements: + ExtUtils::MakeMaker 0 + Test::More 0 + LWP-MediaTypes-6.02 + pathname: G/GA/GAAS/LWP-MediaTypes-6.02.tar.gz + provides: + LWP::MediaTypes 6.02 + requirements: + ExtUtils::MakeMaker 0 + perl 5.006002 Locale-Maketext-Lexicon-1.00 pathname: D/DR/DRTECH/Locale-Maketext-Lexicon-1.00.tar.gz provides: @@ -427,8 +635,8 @@ DISTRIBUTIONS Text::ParseWords 0 perl 5.008000 version 0.87 - Mojolicious-6.22 - pathname: S/SR/SRI/Mojolicious-6.22.tar.gz + Mojolicious-6.62 + pathname: S/SR/SRI/Mojolicious-6.62.tar.gz provides: Mojo undef Mojo::Asset undef @@ -490,7 +698,8 @@ DISTRIBUTIONS Mojo::UserAgent::Server undef Mojo::UserAgent::Transactor undef Mojo::Util undef - Mojolicious 6.22 + Mojo::WebSocket undef + Mojolicious 6.62 Mojolicious::Command undef Mojolicious::Command::cgi undef Mojolicious::Command::cpanify undef @@ -538,10 +747,19 @@ DISTRIBUTIONS ojo undef requirements: ExtUtils::MakeMaker 0 - IO::Socket::IP 0.26 + IO::Socket::IP 0.37 JSON::PP 2.27103 Pod::Simple 3.09 Time::Local 1.2 + Mojolicious-Plugin-Authentication-1.29 + pathname: M/MA/MADCAT/Mojolicious-Plugin-Authentication-1.29.tar.gz + provides: + Mojolicious::Plugin::Authentication 1.29 + requirements: + ExtUtils::MakeMaker 0 + Mojo::Base 0 + strict 0 + warnings 0 Mojolicious-Plugin-DebugDumperHelper-0.02 pathname: L/LD/LDIDRY/Mojolicious-Plugin-DebugDumperHelper-0.02.tar.gz provides: @@ -570,10 +788,35 @@ DISTRIBUTIONS Mojolicious 5 Test::More 0 perl 5.001001 - Number-Bytes-Human-0.09 - pathname: D/DA/DAGOBERT/Number-Bytes-Human-0.09.tar.gz + Net-HTTP-6.09 + pathname: E/ET/ETHER/Net-HTTP-6.09.tar.gz provides: - Number::Bytes::Human 0.09 + Net::HTTP 6.09 + Net::HTTP::Methods 6.09 + Net::HTTP::NB 6.09 + Net::HTTPS 6.09 + requirements: + Compress::Raw::Zlib 0 + ExtUtils::MakeMaker 0 + IO::Select 0 + IO::Socket::INET 0 + IO::Uncompress::Gunzip 0 + URI 0 + perl 5.006002 + Net-SSLeay-1.74 + pathname: M/MI/MIKEM/Net-SSLeay-1.74.tar.gz + provides: + Net::SSLeay 1.74 + Net::SSLeay::Handle 0.61 + requirements: + ExtUtils::MakeMaker 6.36 + MIME::Base64 0 + Test::More 0.60_01 + perl 5.005 + Number-Bytes-Human-0.10 + pathname: D/DA/DAGOBERT/Number-Bytes-Human-0.10.tar.gz + provides: + Number::Bytes::Human 0.10 requirements: Carp 0 ExtUtils::MakeMaker 0 @@ -676,6 +919,13 @@ DISTRIBUTIONS Test::Builder::Tester 1.02 Test::More 0 perl 5.006 + Text-Soundex-3.05 + pathname: R/RJ/RJBS/Text-Soundex-3.05.tar.gz + provides: + Text::Soundex 3.05 + requirements: + ExtUtils::MakeMaker 0 + if 0 TimeDate-2.30 pathname: G/GB/GBARR/TimeDate-2.30.tar.gz provides: @@ -719,9 +969,233 @@ DISTRIBUTIONS Time::Zone 2.24 requirements: ExtUtils::MakeMaker 0 + URI-1.71 + pathname: E/ET/ETHER/URI-1.71.tar.gz + provides: + URI 1.71 + URI::Escape 3.31 + URI::Heuristic 4.20 + URI::IRI 1.71 + URI::QueryParam 1.71 + URI::Split 1.71 + URI::URL 5.04 + URI::WithBase 2.20 + URI::_foreign 1.71 + URI::_generic 1.71 + URI::_idna 1.71 + URI::_ldap 1.71 + URI::_login 1.71 + URI::_punycode 1.71 + URI::_query 1.71 + URI::_segment 1.71 + URI::_server 1.71 + URI::_userpass 1.71 + URI::data 1.71 + URI::file 4.21 + URI::file::Base 1.71 + URI::file::FAT 1.71 + URI::file::Mac 1.71 + URI::file::OS2 1.71 + URI::file::QNX 1.71 + URI::file::Unix 1.71 + URI::file::Win32 1.71 + URI::ftp 1.71 + URI::gopher 1.71 + URI::http 1.71 + URI::https 1.71 + URI::ldap 1.71 + URI::ldapi 1.71 + URI::ldaps 1.71 + URI::mailto 1.71 + URI::mms 1.71 + URI::news 1.71 + URI::nntp 1.71 + URI::pop 1.71 + URI::rlogin 1.71 + URI::rsync 1.71 + URI::rtsp 1.71 + URI::rtspu 1.71 + URI::sftp 1.71 + URI::sip 1.71 + URI::sips 1.71 + URI::snews 1.71 + URI::ssh 1.71 + URI::telnet 1.71 + URI::tn3270 1.71 + URI::urn 1.71 + URI::urn::isbn undef + URI::urn::oid 1.71 + requirements: + Exporter 5.57 + ExtUtils::MakeMaker 0 + MIME::Base64 2 + Scalar::Util 0 + parent 0 + perl 5.008001 + utf8 0 + WWW-RobotRules-6.02 + pathname: G/GA/GAAS/WWW-RobotRules-6.02.tar.gz + provides: + WWW::RobotRules 6.02 + WWW::RobotRules::AnyDBM_File 6.00 + WWW::RobotRules::InCore 6.02 + requirements: + AnyDBM_File 0 + ExtUtils::MakeMaker 0 + Fcntl 0 + URI 1.10 + perl 5.008001 + XML-SAX-Base-1.08 + pathname: G/GR/GRANTM/XML-SAX-Base-1.08.tar.gz + provides: + XML::SAX::Base 1.08 + XML::SAX::Base::NoHandler 1.08 + XML::SAX::Exception 1.08 + requirements: + ExtUtils::MakeMaker 6.31 + Test::More 0.88 common-sense-3.74 pathname: M/ML/MLEHMANN/common-sense-3.74.tar.gz provides: common::sense 3.74 requirements: ExtUtils::MakeMaker 0 + libwww-perl-6.15 + pathname: E/ET/ETHER/libwww-perl-6.15.tar.gz + provides: + LWP 6.15 + LWP::Authen::Basic undef + LWP::Authen::Digest undef + LWP::Authen::Ntlm 6.15 + LWP::ConnCache 6.15 + LWP::Debug undef + LWP::DebugFile undef + LWP::MemberMixin undef + LWP::Protocol 6.15 + LWP::Protocol::GHTTP undef + LWP::Protocol::MyFTP undef + LWP::Protocol::cpan undef + LWP::Protocol::data undef + LWP::Protocol::file undef + LWP::Protocol::ftp undef + LWP::Protocol::gopher undef + LWP::Protocol::http undef + LWP::Protocol::http::Socket undef + LWP::Protocol::http::SocketMethods undef + LWP::Protocol::loopback undef + LWP::Protocol::mailto undef + LWP::Protocol::nntp undef + LWP::Protocol::nogo undef + LWP::RobotUA 6.15 + LWP::Simple 6.15 + LWP::UserAgent 6.15 + requirements: + Digest::MD5 0 + Encode 2.12 + Encode::Locale 0 + ExtUtils::MakeMaker 0 + File::Copy 0 + File::Listing 6 + Getopt::Long 0 + HTML::Entities 0 + HTML::HeadParser 0 + HTTP::Cookies 6 + HTTP::Daemon 6 + HTTP::Date 6 + HTTP::Negotiate 6 + HTTP::Request 6 + HTTP::Request::Common 6 + HTTP::Response 6 + HTTP::Status 6 + IO::Select 0 + IO::Socket 0 + LWP::MediaTypes 6 + MIME::Base64 2.1 + Net::FTP 2.58 + Net::HTTP 6.07 + URI 1.10 + URI::Escape 0 + WWW::RobotRules 6 + perl 5.008001 + perl-ldap-0.65 + pathname: M/MA/MARSCHAP/perl-ldap-0.65.tar.gz + provides: + Bundle::Net::LDAP 0.03 + LWP::Protocol::ldap 1.25 + LWP::Protocol::ldapi undef + LWP::Protocol::ldaps undef + Net::LDAP 0.65 + Net::LDAP::ASN 0.12 + Net::LDAP::Bind 1.05 + Net::LDAP::Constant 0.23 + Net::LDAP::Control 0.18 + Net::LDAP::Control::Assertion 0.02 + Net::LDAP::Control::DontUseCopy 0.01 + Net::LDAP::Control::EntryChange 0.02 + Net::LDAP::Control::ManageDsaIT 0.04 + Net::LDAP::Control::MatchedValues 0.02 + Net::LDAP::Control::Paged 0.05 + Net::LDAP::Control::PasswordPolicy 0.04 + Net::LDAP::Control::PersistentSearch 0.04 + Net::LDAP::Control::PostRead 0.03 + Net::LDAP::Control::PreRead 0.04 + Net::LDAP::Control::ProxyAuth 1.09 + Net::LDAP::Control::Relax 0.03 + Net::LDAP::Control::Sort 0.04 + Net::LDAP::Control::SortResult 0.03 + Net::LDAP::Control::SyncDone 0.03 + Net::LDAP::Control::SyncRequest 0.03 + Net::LDAP::Control::SyncState 0.04 + Net::LDAP::Control::VLV 0.06 + Net::LDAP::Control::VLVResponse 0.04 + Net::LDAP::DSML 0.16 + Net::LDAP::DSML::output 0.16 + Net::LDAP::DSML::pp 0.16 + Net::LDAP::Entry 0.27 + Net::LDAP::Extension 1.04 + Net::LDAP::Extension::Cancel 0.02 + Net::LDAP::Extension::Refresh 0.03 + Net::LDAP::Extension::SetPassword 0.06 + Net::LDAP::Extension::WhoAmI 0.02 + Net::LDAP::Extra 0.02 + Net::LDAP::Extra::AD 0.04 + Net::LDAP::Extra::eDirectory 0.03 + Net::LDAP::Filter 0.20 + Net::LDAP::FilterList 0.02 + Net::LDAP::FilterMatch 0.27 + Net::LDAP::Intermediate 0.04 + Net::LDAP::Intermediate::SyncInfo 0.03 + Net::LDAP::LDIF 0.26 + Net::LDAP::Message 1.12 + Net::LDAP::Message::Dummy 1.12 + Net::LDAP::Reference 0.14 + Net::LDAP::RootDSE 0.02 + Net::LDAP::Schema 0.9908 + Net::LDAP::Search 0.14 + Net::LDAP::Util 0.19 + Net::LDAPI 0.04 + Net::LDAPS 0.06 + requirements: + Authen::SASL 2.00 + Convert::ASN1 0.2 + Digest::MD5 0 + ExtUtils::MakeMaker 6.42 + File::Basename 0 + File::Compare 0 + File::Path 0 + HTTP::Negotiate 0 + HTTP::Response 0 + HTTP::Status 0 + IO::File 0 + IO::Socket::SSL 1.26 + JSON 0 + LWP 0 + LWP::MediaTypes 0 + LWP::Protocol 0 + MIME::Base64 0 + Test::More 0 + Text::Soundex 0 + Time::Local 0 + URI::ldap 1.1 + XML::SAX::Base 0 + perl 5.008001 diff --git a/lib/Lufi.pm b/lib/Lufi.pm index 9e9c2f4..605c5c3 100644 --- a/lib/Lufi.pm +++ b/lib/Lufi.pm @@ -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 diff --git a/lib/Lufi/Controller/Files.pm b/lib/Lufi/Controller/Files.pm index 3b99d86..8f9b408 100644 --- a/lib/Lufi/Controller/Files.pm +++ b/lib/Lufi/Controller/Files.pm @@ -13,122 +13,124 @@ use Filesys::DfPortable; sub upload { my $c = shift; - $c->inactivity_timeout(30000000); + if (!defined($c->config('ldap')) || $c->is_user_authenticated) { + $c->inactivity_timeout(30000000); - $c->app->log->debug('Client connected'); + $c->app->log->debug('Client connected'); - $c->on( - message => sub { - my ($ws, $text) = @_; + $c->on( + message => sub { + my ($ws, $text) = @_; - my $begin = time; + my $begin = time; - my ($json) = split('XXMOJOXX', $text, 2); - $json = encode 'UTF-8', $json; - $json = decode_json $json; + my ($json) = split('XXMOJOXX', $text, 2); + $json = encode 'UTF-8', $json; + $json = decode_json $json; - $c->app->log->debug('Got message'); + $c->app->log->debug('Got message'); - my $stop = 0; + my $stop = 0; - # Check if stop_upload file is present - if ($c->stop_upload) { - $stop = 1; - $c->send(sprintf('{"success": false, "msg":"'.$c->l('Sorry, uploading is disabled.').'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i})); - } - # Check against max_size - elsif (defined $c->config('max_file_size')) { - if ($json->{size} > $c->config('max_file_size')) { + # Check if stop_upload file is present + if ($c->stop_upload) { $stop = 1; - $c->send(sprintf('{"success": false, "msg":"'.$c->l('Your file is too big: %1 (maximum size allowed: %2)', format_bytes($json->{size}), format_bytes($c->config('max_file_size'))).'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i})); + $c->send(sprintf('{"success": false, "msg":"'.$c->l('Sorry, uploading is disabled.').'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i})); + } + # Check against max_size + elsif (defined $c->config('max_file_size')) { + if ($json->{size} > $c->config('max_file_size')) { + $stop = 1; + $c->send(sprintf('{"success": false, "msg":"'.$c->l('Your file is too big: %1 (maximum size allowed: %2)', format_bytes($json->{size}), format_bytes($c->config('max_file_size'))).'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i})); + } + } + # Check that we have enough space (multiplying by 2 since it's encrypted, it takes more place that the original file) + elsif ($json->{part} == 0 && ($json->{size} * 2) >= dfportable($c->config('upload_dir'))->{bavail}) { + $stop = 1; + $c->send(sprintf('{"success": false, "msg":"'.$c->l('No enough space available on the server for this file (size: %1).', format_bytes($json->{size})).'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i})); } - } - # Check that we have enough space (multiplying by 2 since it's encrypted, it takes more place that the original file) - elsif ($json->{part} == 0 && ($json->{size} * 2) >= dfportable($c->config('upload_dir'))->{bavail}) { - $stop = 1; - $c->send(sprintf('{"success": false, "msg":"'.$c->l('No enough space available on the server for this file (size: %1).', format_bytes($json->{size})).'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i})); - } - unless ($stop) { - my $f; - if (defined($json->{id})) { - my @records = LufiDB::Files->select('WHERE short = ?', $json->{id}); - $f = Lufi::File->new(record => $records[0]) if scalar @records; - } else { - my $delay; + unless ($stop) { + my $f; + if (defined($json->{id})) { + my @records = LufiDB::Files->select('WHERE short = ?', $json->{id}); + $f = Lufi::File->new(record => $records[0]) if scalar @records; + } else { + my $delay; - if (defined $c->config('delay_for_size')) { - # Choose delay according to config - my $delays = $c->config('delay_for_size'); - my @keys = sort {$b <=> $a} keys %{$delays}; - for my $key (@keys) { - if ($json->{size} >= $key) { - $delay = ($json->{delay} < $delays->{$key}) ? $json->{delay} : $delays->{$key}; - last; + if (defined $c->config('delay_for_size')) { + # Choose delay according to config + my $delays = $c->config('delay_for_size'); + my @keys = sort {$b <=> $a} keys %{$delays}; + for my $key (@keys) { + if ($json->{size} >= $key) { + $delay = ($json->{delay} < $delays->{$key}) ? $json->{delay} : $delays->{$key}; + last; + } } } - } - # If the file size is lower than the lowest configured size or if there is no delay_for_size setting, we choose the configured max delay - unless (defined $delay) { - $delay = ($json->{delay} <= $c->max_delay || $c->max_delay == 0) ? $json->{delay} : $c->max_delay; - } - - $f = Lufi::File->new( - record => $c->get_empty, - created_by => $c->ip, - delete_at_first_view => ($json->{del_at_first_view}) ? 1 : 0, - delete_at_day => $delay, - mediatype => $json->{type}, - filename => $json->{name}, - filesize => $json->{size}, - nbslices => $json->{total}, - mod_token => $c->shortener($c->config('token_length')) - ); - $f->write; - } - - # This check is just in case we didn't succeed to find a corresponding record - # It normally can't happen - if (defined $f) { - # If we already have a part, it's a resend because the websocket has been broken - # In this case, we don't need to rewrite the file - unless ($f->slices->grep(sub { $_->j == $json->{part} })->size) { - # Create directory - my $dir = catdir($c->config('upload_dir'), $f->short); - mkdir($dir, 0700) unless (-d $dir); - - # Create slice file - my $file = catfile($dir, $json->{part}.'.part'); - my $s = Lufi::Slice->new( - short => $f->short, - j => $json->{part}, - path => $file - ); - spurt $text, $file; - push @{$f->slices}, $s; - $s->write; - - if (($json->{part} + 1) == $json->{total}) { - $f->complete(1); - $f->created_at(time); - $f->write; + # If the file size is lower than the lowest configured size or if there is no delay_for_size setting, we choose the configured max delay + unless (defined $delay) { + $delay = ($json->{delay} <= $c->max_delay || $c->max_delay == 0) ? $json->{delay} : $c->max_delay; } + + $f = Lufi::File->new( + record => $c->get_empty, + created_by => $c->ip, + delete_at_first_view => ($json->{del_at_first_view}) ? 1 : 0, + delete_at_day => $delay, + mediatype => $json->{type}, + filename => $json->{name}, + filesize => $json->{size}, + nbslices => $json->{total}, + mod_token => $c->shortener($c->config('token_length')) + ); + $f->write; } - $c->provisioning; + # This check is just in case we didn't succeed to find a corresponding record + # It normally can't happen + if (defined $f) { + # If we already have a part, it's a resend because the websocket has been broken + # In this case, we don't need to rewrite the file + unless ($f->slices->grep(sub { $_->j == $json->{part} })->size) { + # Create directory + my $dir = catdir($c->config('upload_dir'), $f->short); + mkdir($dir, 0700) unless (-d $dir); - $ws->send(sprintf('{"success": true, "i": %d, "j": %d, "parts": %d, "short": "%s", "name": "%s", "size": %d, "del_at_first_view": %s, "created_at": %d, "delay": %d, "token": "%s", "sent_delay": %d, "duration": %d}', $json->{i}, $json->{part}, $json->{total}, $f->short, $f->filename, $f->filesize, (($f->delete_at_first_view) ? 'true' : 'false'), $f->created_at, $f->delete_at_day, $f->mod_token, $json->{delay}, time - $begin)); - } else { - $ws->send(sprintf('{"success": false, "msg":"'.$c->l('The server was unable to find the file record to add your file part to. Please, contact the administrator.').'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i})); + # Create slice file + my $file = catfile($dir, $json->{part}.'.part'); + my $s = Lufi::Slice->new( + short => $f->short, + j => $json->{part}, + path => $file + ); + spurt $text, $file; + push @{$f->slices}, $s; + $s->write; + + if (($json->{part} + 1) == $json->{total}) { + $f->complete(1); + $f->created_at(time); + $f->write; + } + } + + $c->provisioning; + + $ws->send(sprintf('{"success": true, "i": %d, "j": %d, "parts": %d, "short": "%s", "name": "%s", "size": %d, "del_at_first_view": %s, "created_at": %d, "delay": %d, "token": "%s", "sent_delay": %d, "duration": %d}', $json->{i}, $json->{part}, $json->{total}, $f->short, $f->filename, $f->filesize, (($f->delete_at_first_view) ? 'true' : 'false'), $f->created_at, $f->delete_at_day, $f->mod_token, $json->{delay}, time - $begin)); + } else { + $ws->send(sprintf('{"success": false, "msg":"'.$c->l('The server was unable to find the file record to add your file part to. Please, contact the administrator.').'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i})); + } } } - } - ); - $c->on( - finish => sub { - $c->app->log->debug('Client disconnected'); - } - ); + ); + $c->on( + finish => sub { + $c->app->log->debug('Client disconnected'); + } + ); + } } sub download { @@ -233,24 +235,35 @@ sub get_counter { my $short = $c->param('short'); my $token = $c->param('token'); - my @records = LufiDB::Files->select('WHERE short = ?', $short); - if (scalar(@records)) { - if ($records[0]->mod_token eq $token) { - return $c->render( - json => { - success => true, - short => $short, - counter => $records[0]->counter, - deleted => ($records[0]->deleted) ? true : false - } - ); + if (!defined($c->config('ldap')) || $c->is_user_authenticated) { + my @records = LufiDB::Files->select('WHERE short = ?', $short); + if (scalar(@records)) { + if ($records[0]->mod_token eq $token) { + return $c->render( + json => { + success => true, + short => $short, + counter => $records[0]->counter, + deleted => ($records[0]->deleted) ? true : false + } + ); + } else { + return $c->render( + json => { + success => false, + missing => false, + short => $short, + msg => $c->l('Unable to get counter for %1. The token is invalid.', $short) + } + ); + } } else { return $c->render( json => { success => false, - missing => false, + missing => true, short => $short, - msg => $c->l('Unable to get counter for %1. The token is invalid.', $short) + msg => $c->l('Unable to get counter for %1. The file does not exists. It will be removed from your localStorage.', $short) } ); } @@ -258,9 +271,9 @@ sub get_counter { return $c->render( json => { success => false, - missing => true, + missing => false, short => $short, - msg => $c->l('Unable to get counter for %1. The file does not exists. It will be removed from your localStorage.', $short) + msg => $c->l('Unable to get counter for %1. You are not authenticated.', $short) } ); } @@ -271,31 +284,48 @@ sub delete { my $short = $c->param('short'); my $token = $c->param('token'); - my @records = LufiDB::Files->select('WHERE short = ? AND mod_token = ?', ($short, $token)); - if (scalar(@records)) { - my $f = Lufi::File->new(record => $records[0]); - my $msg; - if ($f->deleted) { - $msg = $c->l('The file has already been deleted'); - } else { - $f->delete; - $msg = $c->l('File deleted'); - } - return $c->respond_to( - json => { - success => true, - msg => $msg - }, - any => sub { - $c->render( - template => 'msg', - f => $f, - msg => $msg - ); + if (!defined($c->config('ldap')) || $c->is_user_authenticated) { + my @records = LufiDB::Files->select('WHERE short = ? AND mod_token = ?', ($short, $token)); + if (scalar(@records)) { + my $f = Lufi::File->new(record => $records[0]); + my $msg; + if ($f->deleted) { + $msg = $c->l('The file has already been deleted'); + } else { + $f->delete; + $msg = $c->l('File deleted'); } - ); + return $c->respond_to( + json => { + success => true, + msg => $msg + }, + any => sub { + $c->render( + template => 'msg', + f => $f, + msg => $msg + ); + } + ); + } else { + my $msg = $c->l('Could not find the file. Are you sure of the URL and the token?'); + return $c->respond_to( + json => { + success => false, + msg => $msg + }, + any => sub { + $c->render( + template => 'msg', + f => undef, + msg => $msg + ); + } + ); + } } else { - my $msg = $c->l('Could not find the file. Are you sure of the URL and the token?'); + my $msg = $c->l('Could not delete the file. You are not authenticated.'); return $c->respond_to( json => { success => false, diff --git a/lufi.conf.template b/lufi.conf.template index 8eb1b64..3100aba 100644 --- a/lufi.conf.template +++ b/lufi.conf.template @@ -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, }; diff --git a/themes/default/lib/Lufi/I18N/en.po b/themes/default/lib/Lufi/I18N/en.po index 8f0f609..aa2a078 100644 --- a/themes/default/lib/Lufi/I18N/en.po +++ b/themes/default/lib/Lufi/I18N/en.po @@ -37,7 +37,7 @@ msgstr "" msgid "A thank you with a photo of kitten on Diaspora* or Twitter 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 Luc Didry. If you want to support him, you can do it via Flattr or with Bitcoin." 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 "" diff --git a/themes/default/lib/Lufi/I18N/fr.po b/themes/default/lib/Lufi/I18N/fr.po index 7214bad..14f7a8a 100644 --- a/themes/default/lib/Lufi/I18N/fr.po +++ b/themes/default/lib/Lufi/I18N/fr.po @@ -39,7 +39,7 @@ msgstr " :" msgid "A thank you with a photo of kitten on Diaspora* or Twitter is cool too ;-)" msgstr "Un merci avec une photo de chaton sur Diaspora* ou Twitter 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 Luc Didry. If you want to support him, you can do it via Flattr or with Bitcoin." msgstr "L’auteur originel (et pour l’instant, le seul) est Luc Didry. Si vous avez envie de le supporter, vous pouvez le faire via Flattr ou en Bitcoin." -#: 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)" diff --git a/themes/default/templates/layouts/default.html.ep b/themes/default/templates/layouts/default.html.ep index 0837dc7..5854eeb 100644 --- a/themes/default/templates/layouts/default.html.ep +++ b/themes/default/templates/layouts/default.html.ep @@ -31,14 +31,28 @@ diff --git a/themes/default/templates/login.html.ep b/themes/default/templates/login.html.ep new file mode 100644 index 0000000..189a8dc --- /dev/null +++ b/themes/default/templates/login.html.ep @@ -0,0 +1,29 @@ +% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab: +% if (defined stash('msg')) { +
+
+
+ <%= stash('msg') %> +
+
+
+% } +
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+
diff --git a/themes/default/templates/logout.html.ep b/themes/default/templates/logout.html.ep new file mode 100644 index 0000000..d8d8028 --- /dev/null +++ b/themes/default/templates/logout.html.ep @@ -0,0 +1,11 @@ +% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab: +
+
+
+ <%= l('You have been successfully logged out.') %> +
+ +
+
diff --git a/utilities/locales_files.txt b/utilities/locales_files.txt index 62818da..dd95bb9 100644 --- a/utilities/locales_files.txt +++ b/utilities/locales_files.txt @@ -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