Merge branch 'fix-150' into 'development'
✉️ Implement invitations to other people when using LDAP auth
See merge request fiat-tux/hat-softwares/lufi!29
This commit is contained in:
commit
386437391a
|
@ -1,4 +1,4 @@
|
|||
image: hatsoftwares/lufi-test-ci:latest
|
||||
image: hatsoftwares/lufi-test-ci:buster
|
||||
stages:
|
||||
- publish_changelog
|
||||
- carton
|
||||
|
@ -41,6 +41,9 @@ variables:
|
|||
coverage: '/Total.* (\d+\.\d+)$/'
|
||||
before_script:
|
||||
- tar xf local.tar && rm local.tar
|
||||
- which mariadb_config && cd $(dirname $(which mariadb_config)) && ln -s mariadb_config mysql_config
|
||||
- cd $CI_PROJECT_DIR
|
||||
- pwd
|
||||
script:
|
||||
- MOJO_CONFIG="t/${CI_JOB_NAME}.conf" make test
|
||||
- MOJO_CONFIG="t/${CI_JOB_NAME}.conf" make cover
|
||||
|
@ -57,7 +60,7 @@ variables:
|
|||
dependencies:
|
||||
- carton_postgresql
|
||||
services:
|
||||
- name: postgres:9.6
|
||||
- name: postgres:11
|
||||
alias: postgres
|
||||
- name: rroemhild/test-openldap
|
||||
alias: rroemhild-test-openldap
|
||||
|
@ -66,7 +69,7 @@ variables:
|
|||
dependencies:
|
||||
- carton_mysql
|
||||
services:
|
||||
- name: mariadb:10.1
|
||||
- name: mariadb:10.3
|
||||
alias: mariadb
|
||||
- name: rroemhild/test-openldap
|
||||
alias: rroemhild-test-openldap
|
||||
|
@ -96,6 +99,19 @@ podcheck:
|
|||
except:
|
||||
- tags
|
||||
|
||||
### Cpanfile.snapshot
|
||||
## Used to get a cpanfile.snapshot from a fresh server (not like my dev VM)
|
||||
#
|
||||
#cpanfile_snapshot:
|
||||
# stage: carton
|
||||
# script:
|
||||
# - rm cpanfile.snapshot
|
||||
# - which mariadb_config && cd $(dirname $(which mariadb_config)) && ln -s mariadb_config mysql_config
|
||||
# - carton install
|
||||
# - cat cpanfile.snapshot
|
||||
# except:
|
||||
# - tags
|
||||
|
||||
### Install common dependencies
|
||||
##
|
||||
#
|
||||
|
@ -122,6 +138,9 @@ carton_postgresql:
|
|||
- carton install --deployment --without=sqlite --without=mysql
|
||||
carton_mysql:
|
||||
<<: *carton_bdd_definition
|
||||
before_script:
|
||||
- which mariadb_config && cd $(dirname $(which mariadb_config)) && ln -s mariadb_config mysql_config
|
||||
- cd $CI_PROJECT_DIR
|
||||
script:
|
||||
- carton install --deployment --without=sqlite --without=postgresql
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ Revision history for Lufi
|
|||
- Allow to zip the files before upload
|
||||
- Allow to see what's in zip file on download page
|
||||
- Allow to individually download files from zip file (only if zip created by Lufi)
|
||||
- Allow to invite people to send you files on Lufi when using LDAP auth (See #150)
|
||||
|
||||
0.03.7 2019-08-01
|
||||
- Fix missing default values for some settings (mildis)
|
||||
|
|
5
Makefile
5
Makefile
|
@ -32,6 +32,11 @@ clean:
|
|||
dev: clean
|
||||
$(CARTON) morbo $(LUFI) --listen http://0.0.0.0:3000 --watch lib/ --watch script/ --watch themes/ --watch lufi.conf
|
||||
|
||||
ldap:
|
||||
sudo docker run --privileged -d -p 389:389 rroemhild/test-openldap; exit 0
|
||||
|
||||
ldapdev: ldap dev
|
||||
|
||||
devlog:
|
||||
multitail log/development.log
|
||||
|
||||
|
|
3
cpanfile
3
cpanfile
|
@ -1,5 +1,4 @@
|
|||
requires 'inc::Module::Install';
|
||||
requires 'List::Util', '>= 1.50';
|
||||
requires 'Mojolicious', '>= 8.05';
|
||||
requires 'Mojolicious::Plugin::DebugDumperHelper';
|
||||
requires 'Mojolicious::Plugin::I18N';
|
||||
|
@ -33,10 +32,12 @@ feature 'optional_deps' => sub {
|
|||
|
||||
feature 'test' => sub {
|
||||
requires 'Devel::Cover';
|
||||
requires 'B::Debug';
|
||||
};
|
||||
feature 'ldap', 'LDAP authentication support' => sub {
|
||||
requires 'Net::LDAP';
|
||||
requires 'Mojolicious::Plugin::Authentication';
|
||||
requires 'Date::Format';
|
||||
};
|
||||
feature 'htpasswd', 'Htpasswd authentication support' => sub {
|
||||
requires 'Apache::Htpasswd';
|
||||
|
|
|
@ -30,10 +30,19 @@ DISTRIBUTIONS
|
|||
ExtUtils::MakeMaker 6.42
|
||||
Test::More 0
|
||||
perl 5.005
|
||||
Canary-Stability-2012
|
||||
pathname: M/ML/MLEHMANN/Canary-Stability-2012.tar.gz
|
||||
B-Debug-1.26
|
||||
pathname: R/RU/RURBAN/B-Debug-1.26.tar.gz
|
||||
provides:
|
||||
Canary::Stability 2012
|
||||
B::Debug 1.26
|
||||
requirements:
|
||||
B 0
|
||||
ExtUtils::MakeMaker 0
|
||||
Test::More 0
|
||||
deprecate 0.03
|
||||
Canary-Stability-2013
|
||||
pathname: M/ML/MLEHMANN/Canary-Stability-2013.tar.gz
|
||||
provides:
|
||||
Canary::Stability 2013
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
Capture-Tiny-0.48
|
||||
|
@ -92,10 +101,10 @@ DISTRIBUTIONS
|
|||
ExtUtils::MakeMaker 6.30
|
||||
Math::BigInt 1.997
|
||||
Test::More 0.90
|
||||
Cpanel-JSON-XS-4.06
|
||||
pathname: R/RU/RURBAN/Cpanel-JSON-XS-4.06.tar.gz
|
||||
Cpanel-JSON-XS-4.12
|
||||
pathname: R/RU/RURBAN/Cpanel-JSON-XS-4.12.tar.gz
|
||||
provides:
|
||||
Cpanel::JSON::XS 4.06
|
||||
Cpanel::JSON::XS 4.12
|
||||
Cpanel::JSON::XS::Type undef
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
|
@ -110,10 +119,10 @@ DISTRIBUTIONS
|
|||
Test::More 0.94
|
||||
strict 0
|
||||
warnings 0
|
||||
Crypt-Rijndael-1.13
|
||||
pathname: L/LE/LEONT/Crypt-Rijndael-1.13.tar.gz
|
||||
Crypt-Rijndael-1.14
|
||||
pathname: L/LE/LEONT/Crypt-Rijndael-1.14.tar.gz
|
||||
provides:
|
||||
Crypt::Rijndael 1.13
|
||||
Crypt::Rijndael 1.14
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
perl 5.006
|
||||
|
@ -126,24 +135,25 @@ DISTRIBUTIONS
|
|||
ExtUtils::MakeMaker 6.30
|
||||
Test::Fatal 0
|
||||
Test::More 0
|
||||
DBD-Pg-3.7.4
|
||||
pathname: T/TU/TURNSTEP/DBD-Pg-3.7.4.tar.gz
|
||||
DBD-Pg-3.8.1
|
||||
pathname: T/TU/TURNSTEP/DBD-Pg-3.8.1.tar.gz
|
||||
provides:
|
||||
Bundle::DBD::Pg v3.7.4
|
||||
DBD::Pg v3.7.4
|
||||
Bundle::DBD::Pg v3.8.1
|
||||
DBD::Pg v3.8.1
|
||||
requirements:
|
||||
DBI 1.614
|
||||
ExtUtils::MakeMaker 6.11
|
||||
Test::More 0.88
|
||||
Time::HiRes 0
|
||||
version 0
|
||||
DBD-SQLite-1.58
|
||||
pathname: I/IS/ISHIGAKI/DBD-SQLite-1.58.tar.gz
|
||||
DBD-SQLite-1.62
|
||||
pathname: I/IS/ISHIGAKI/DBD-SQLite-1.62.tar.gz
|
||||
provides:
|
||||
DBD::SQLite 1.58
|
||||
DBD::SQLite 1.62
|
||||
DBD::SQLite::Constants undef
|
||||
DBD::SQLite::VirtualTable 1.58
|
||||
DBD::SQLite::VirtualTable::Cursor 1.58
|
||||
DBD::SQLite::GetInfo undef
|
||||
DBD::SQLite::VirtualTable 1.62
|
||||
DBD::SQLite::VirtualTable::Cursor 1.62
|
||||
DBD::SQLite::VirtualTable::FileContent undef
|
||||
DBD::SQLite::VirtualTable::FileContent::Cursor undef
|
||||
DBD::SQLite::VirtualTable::PerlData undef
|
||||
|
@ -356,58 +366,58 @@ DISTRIBUTIONS
|
|||
File::Spec 0
|
||||
File::Temp 0.16
|
||||
perl 5.00405
|
||||
Devel-Cover-1.31
|
||||
pathname: P/PJ/PJCJ/Devel-Cover-1.31.tar.gz
|
||||
Devel-Cover-1.33
|
||||
pathname: P/PJ/PJCJ/Devel-Cover-1.33.tar.gz
|
||||
provides:
|
||||
Devel::Cover 1.31
|
||||
Devel::Cover::Annotation::Git 1.31
|
||||
Devel::Cover::Annotation::Random 1.31
|
||||
Devel::Cover::Annotation::Svk 1.31
|
||||
Devel::Cover::Branch 1.31
|
||||
Devel::Cover::Collection 1.31
|
||||
Devel::Cover::Collection::Template::Provider 1.31
|
||||
Devel::Cover::Condition 1.31
|
||||
Devel::Cover::Condition_and_2 1.31
|
||||
Devel::Cover::Condition_and_3 1.31
|
||||
Devel::Cover::Condition_or_2 1.31
|
||||
Devel::Cover::Condition_or_3 1.31
|
||||
Devel::Cover::Condition_xor_4 1.31
|
||||
Devel::Cover::Criterion 1.31
|
||||
Devel::Cover::DB 1.31
|
||||
Devel::Cover::DB::Criterion 1.31
|
||||
Devel::Cover::DB::Digests 1.31
|
||||
Devel::Cover::DB::File 1.31
|
||||
Devel::Cover::DB::IO 1.31
|
||||
Devel::Cover::DB::IO::Base 1.31
|
||||
Devel::Cover::DB::IO::JSON 1.31
|
||||
Devel::Cover::DB::IO::Sereal 1.31
|
||||
Devel::Cover::DB::IO::Storable 1.31
|
||||
Devel::Cover::DB::Run 1.31
|
||||
Devel::Cover::DB::Structure 1.31
|
||||
Devel::Cover::Html_Common 1.31
|
||||
Devel::Cover::Op 1.31
|
||||
Devel::Cover::Pod 1.31
|
||||
Devel::Cover::Report::Compilation 1.31
|
||||
Devel::Cover::Report::Html 1.31
|
||||
Devel::Cover::Report::Html_basic 1.31
|
||||
Devel::Cover::Report::Html_basic::Template::Provider 1.31
|
||||
Devel::Cover::Report::Html_minimal 1.31
|
||||
Devel::Cover::Report::Html_subtle 1.31
|
||||
Devel::Cover::Report::Html_subtle::Template::Provider 1.31
|
||||
Devel::Cover::Report::Json 1.31
|
||||
Devel::Cover::Report::Sort 1.31
|
||||
Devel::Cover::Report::Text 1.31
|
||||
Devel::Cover::Report::Text2 1.31
|
||||
Devel::Cover::Report::Vim 1.31
|
||||
Devel::Cover::Report::Vim::Template::Provider 1.31
|
||||
Devel::Cover::Statement 1.31
|
||||
Devel::Cover::Subroutine 1.31
|
||||
Devel::Cover::Test 1.31
|
||||
Devel::Cover::Time 1.31
|
||||
Devel::Cover::Truth_Table 1.31
|
||||
Devel::Cover::Truth_Table::Row 1.31
|
||||
Devel::Cover::Util 1.31
|
||||
Devel::Cover::Web 1.31
|
||||
Devel::Cover 1.33
|
||||
Devel::Cover::Annotation::Git 1.33
|
||||
Devel::Cover::Annotation::Random 1.33
|
||||
Devel::Cover::Annotation::Svk 1.33
|
||||
Devel::Cover::Branch 1.33
|
||||
Devel::Cover::Collection 1.33
|
||||
Devel::Cover::Collection::Template::Provider 1.33
|
||||
Devel::Cover::Condition 1.33
|
||||
Devel::Cover::Condition_and_2 1.33
|
||||
Devel::Cover::Condition_and_3 1.33
|
||||
Devel::Cover::Condition_or_2 1.33
|
||||
Devel::Cover::Condition_or_3 1.33
|
||||
Devel::Cover::Condition_xor_4 1.33
|
||||
Devel::Cover::Criterion 1.33
|
||||
Devel::Cover::DB 1.33
|
||||
Devel::Cover::DB::Criterion 1.33
|
||||
Devel::Cover::DB::Digests 1.33
|
||||
Devel::Cover::DB::File 1.33
|
||||
Devel::Cover::DB::IO 1.33
|
||||
Devel::Cover::DB::IO::Base 1.33
|
||||
Devel::Cover::DB::IO::JSON 1.33
|
||||
Devel::Cover::DB::IO::Sereal 1.33
|
||||
Devel::Cover::DB::IO::Storable 1.33
|
||||
Devel::Cover::DB::Run 1.33
|
||||
Devel::Cover::DB::Structure 1.33
|
||||
Devel::Cover::Html_Common 1.33
|
||||
Devel::Cover::Op 1.33
|
||||
Devel::Cover::Pod 1.33
|
||||
Devel::Cover::Report::Compilation 1.33
|
||||
Devel::Cover::Report::Html 1.33
|
||||
Devel::Cover::Report::Html_basic 1.33
|
||||
Devel::Cover::Report::Html_basic::Template::Provider 1.33
|
||||
Devel::Cover::Report::Html_minimal 1.33
|
||||
Devel::Cover::Report::Html_subtle 1.33
|
||||
Devel::Cover::Report::Html_subtle::Template::Provider 1.33
|
||||
Devel::Cover::Report::Json 1.33
|
||||
Devel::Cover::Report::Sort 1.33
|
||||
Devel::Cover::Report::Text 1.33
|
||||
Devel::Cover::Report::Text2 1.33
|
||||
Devel::Cover::Report::Vim 1.33
|
||||
Devel::Cover::Report::Vim::Template::Provider 1.33
|
||||
Devel::Cover::Statement 1.33
|
||||
Devel::Cover::Subroutine 1.33
|
||||
Devel::Cover::Test 1.33
|
||||
Devel::Cover::Time 1.33
|
||||
Devel::Cover::Truth_Table 1.33
|
||||
Devel::Cover::Truth_Table::Row 1.33
|
||||
Devel::Cover::Util 1.33
|
||||
Devel::Cover::Web 1.33
|
||||
requirements:
|
||||
B::Debug 0
|
||||
Digest::MD5 0
|
||||
|
@ -434,10 +444,10 @@ DISTRIBUTIONS
|
|||
Digest::SHA 1
|
||||
ExtUtils::MakeMaker 0
|
||||
perl 5.004
|
||||
EV-4.22
|
||||
pathname: M/ML/MLEHMANN/EV-4.22.tar.gz
|
||||
EV-4.27
|
||||
pathname: M/ML/MLEHMANN/EV-4.27.tar.gz
|
||||
provides:
|
||||
EV 4.22
|
||||
EV 4.27
|
||||
EV::MakeMaker undef
|
||||
requirements:
|
||||
Canary::Stability 0
|
||||
|
@ -547,10 +557,10 @@ DISTRIBUTIONS
|
|||
Filesys::DfPortable 0.85
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
Filesys-DiskUsage-0.12
|
||||
pathname: M/MA/MANWAR/Filesys-DiskUsage-0.12.tar.gz
|
||||
Filesys-DiskUsage-0.13
|
||||
pathname: M/MA/MANWAR/Filesys-DiskUsage-0.13.tar.gz
|
||||
provides:
|
||||
Filesys::DiskUsage 0.12
|
||||
Filesys::DiskUsage 0.13
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
File::Basename 0
|
||||
|
@ -597,21 +607,25 @@ DISTRIBUTIONS
|
|||
perl 5.008001
|
||||
strict 0
|
||||
vars 0
|
||||
HTTP-Daemon-6.01
|
||||
pathname: G/GA/GAAS/HTTP-Daemon-6.01.tar.gz
|
||||
HTTP-Daemon-6.05
|
||||
pathname: E/ET/ETHER/HTTP-Daemon-6.05.tar.gz
|
||||
provides:
|
||||
HTTP::Daemon 6.01
|
||||
HTTP::Daemon::ClientConn 6.01
|
||||
HTTP::Daemon 6.05
|
||||
requirements:
|
||||
Carp 0
|
||||
ExtUtils::MakeMaker 0
|
||||
HTTP::Date 6
|
||||
HTTP::Request 6
|
||||
HTTP::Response 6
|
||||
HTTP::Status 6
|
||||
IO::Socket 0
|
||||
IO::Socket::IP 0
|
||||
LWP::MediaTypes 6
|
||||
Module::Build::Tiny 0.034
|
||||
Socket 0
|
||||
Sys::Hostname 0
|
||||
perl 5.008001
|
||||
perl 5.006
|
||||
strict 0
|
||||
warnings 0
|
||||
HTTP-Date-6.02
|
||||
pathname: G/GA/GAAS/HTTP-Date-6.02.tar.gz
|
||||
provides:
|
||||
|
@ -695,17 +709,17 @@ DISTRIBUTIONS
|
|||
Encode 2.10
|
||||
Exporter 5.57
|
||||
ExtUtils::MakeMaker 6.30
|
||||
IO-Socket-SSL-2.060
|
||||
pathname: S/SU/SULLR/IO-Socket-SSL-2.060.tar.gz
|
||||
IO-Socket-SSL-2.066
|
||||
pathname: S/SU/SULLR/IO-Socket-SSL-2.066.tar.gz
|
||||
provides:
|
||||
IO::Socket::SSL 2.060
|
||||
IO::Socket::SSL 2.066
|
||||
IO::Socket::SSL::Intercept 2.056
|
||||
IO::Socket::SSL::OCSP_Cache 2.060
|
||||
IO::Socket::SSL::OCSP_Resolver 2.060
|
||||
IO::Socket::SSL::OCSP_Cache 2.066
|
||||
IO::Socket::SSL::OCSP_Resolver 2.066
|
||||
IO::Socket::SSL::PublicSuffix undef
|
||||
IO::Socket::SSL::SSL_Context 2.060
|
||||
IO::Socket::SSL::SSL_HANDLE 2.060
|
||||
IO::Socket::SSL::Session_Cache 2.060
|
||||
IO::Socket::SSL::SSL_Context 2.066
|
||||
IO::Socket::SSL::SSL_HANDLE 2.066
|
||||
IO::Socket::SSL::Session_Cache 2.066
|
||||
IO::Socket::SSL::Utils 2.014
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
|
@ -726,28 +740,33 @@ DISTRIBUTIONS
|
|||
Socket 1.94
|
||||
Test::More 0.88
|
||||
constant 1.03
|
||||
ISO-639_1-0.02
|
||||
pathname: L/LD/LDIDRY/ISO-639_1-0.02.tar.gz
|
||||
ISO-639_1-0.03
|
||||
pathname: L/LD/LDIDRY/ISO-639_1-0.03.tar.gz
|
||||
provides:
|
||||
ISO::639_1 0.02
|
||||
ISO::639_1 0.03
|
||||
requirements:
|
||||
Module::Build::Tiny 0.035
|
||||
perl 5.008001
|
||||
JSON-2.97001
|
||||
pathname: I/IS/ISHIGAKI/JSON-2.97001.tar.gz
|
||||
JSON-4.02
|
||||
pathname: I/IS/ISHIGAKI/JSON-4.02.tar.gz
|
||||
provides:
|
||||
JSON 2.97001
|
||||
JSON::Backend::PP 2.97001
|
||||
JSON 4.02
|
||||
JSON::Backend::PP 4.02
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
Test::More 0
|
||||
LWP-MediaTypes-6.02
|
||||
pathname: G/GA/GAAS/LWP-MediaTypes-6.02.tar.gz
|
||||
LWP-MediaTypes-6.04
|
||||
pathname: O/OA/OALDERS/LWP-MediaTypes-6.04.tar.gz
|
||||
provides:
|
||||
LWP::MediaTypes 6.02
|
||||
LWP::MediaTypes 6.04
|
||||
requirements:
|
||||
Carp 0
|
||||
Exporter 0
|
||||
ExtUtils::MakeMaker 0
|
||||
File::Basename 0
|
||||
Scalar::Util 0
|
||||
perl 5.006002
|
||||
strict 0
|
||||
Locale-Maketext-Lexicon-1.00
|
||||
pathname: D/DR/DRTECH/Locale-Maketext-Lexicon-1.00.tar.gz
|
||||
provides:
|
||||
|
@ -831,31 +850,31 @@ DISTRIBUTIONS
|
|||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
perl 5.006
|
||||
MailTools-2.20
|
||||
pathname: M/MA/MARKOV/MailTools-2.20.tar.gz
|
||||
MailTools-2.21
|
||||
pathname: M/MA/MARKOV/MailTools-2.21.tar.gz
|
||||
provides:
|
||||
Mail::Address 2.20
|
||||
Mail::Cap 2.20
|
||||
Mail::Field 2.20
|
||||
Mail::Field::AddrList 2.20
|
||||
Mail::Field::Date 2.20
|
||||
Mail::Field::Generic 2.20
|
||||
Mail::Filter 2.20
|
||||
Mail::Header 2.20
|
||||
Mail::Internet 2.20
|
||||
Mail::Mailer 2.20
|
||||
Mail::Mailer::qmail 2.20
|
||||
Mail::Mailer::rfc822 2.20
|
||||
Mail::Mailer::sendmail 2.20
|
||||
Mail::Mailer::smtp 2.20
|
||||
Mail::Mailer::smtp::pipe 2.20
|
||||
Mail::Mailer::smtps 2.20
|
||||
Mail::Mailer::smtps::pipe 2.20
|
||||
Mail::Mailer::testfile 2.20
|
||||
Mail::Mailer::testfile::pipe 2.20
|
||||
Mail::Send 2.20
|
||||
Mail::Util 2.20
|
||||
MailTools 2.20
|
||||
Mail::Address 2.21
|
||||
Mail::Cap 2.21
|
||||
Mail::Field 2.21
|
||||
Mail::Field::AddrList 2.21
|
||||
Mail::Field::Date 2.21
|
||||
Mail::Field::Generic 2.21
|
||||
Mail::Filter 2.21
|
||||
Mail::Header 2.21
|
||||
Mail::Internet 2.21
|
||||
Mail::Mailer 2.21
|
||||
Mail::Mailer::qmail 2.21
|
||||
Mail::Mailer::rfc822 2.21
|
||||
Mail::Mailer::sendmail 2.21
|
||||
Mail::Mailer::smtp 2.21
|
||||
Mail::Mailer::smtp::pipe 2.21
|
||||
Mail::Mailer::smtps 2.21
|
||||
Mail::Mailer::smtps::pipe 2.21
|
||||
Mail::Mailer::testfile 2.21
|
||||
Mail::Mailer::testfile::pipe 2.21
|
||||
Mail::Send 2.21
|
||||
Mail::Util 2.21
|
||||
MailTools 2.21
|
||||
requirements:
|
||||
Date::Format 0
|
||||
Date::Parse 0
|
||||
|
@ -864,31 +883,30 @@ DISTRIBUTIONS
|
|||
Net::Domain 1.05
|
||||
Net::SMTP 1.03
|
||||
Test::More 0
|
||||
Module-Build-0.4224
|
||||
pathname: L/LE/LEONT/Module-Build-0.4224.tar.gz
|
||||
Module-Build-0.4229
|
||||
pathname: L/LE/LEONT/Module-Build-0.4229.tar.gz
|
||||
provides:
|
||||
Module::Build 0.4224
|
||||
Module::Build::Base 0.4224
|
||||
Module::Build::Compat 0.4224
|
||||
Module::Build::Config 0.4224
|
||||
Module::Build::Cookbook 0.4224
|
||||
Module::Build::Dumper 0.4224
|
||||
Module::Build::Notes 0.4224
|
||||
Module::Build::PPMMaker 0.4224
|
||||
Module::Build::Platform::Default 0.4224
|
||||
Module::Build::Platform::MacOS 0.4224
|
||||
Module::Build::Platform::Unix 0.4224
|
||||
Module::Build::Platform::VMS 0.4224
|
||||
Module::Build::Platform::VOS 0.4224
|
||||
Module::Build::Platform::Windows 0.4224
|
||||
Module::Build::Platform::aix 0.4224
|
||||
Module::Build::Platform::cygwin 0.4224
|
||||
Module::Build::Platform::darwin 0.4224
|
||||
Module::Build::Platform::os2 0.4224
|
||||
Module::Build::PodParser 0.4224
|
||||
Module::Build 0.4229
|
||||
Module::Build::Base 0.4229
|
||||
Module::Build::Compat 0.4229
|
||||
Module::Build::Config 0.4229
|
||||
Module::Build::Cookbook 0.4229
|
||||
Module::Build::Dumper 0.4229
|
||||
Module::Build::Notes 0.4229
|
||||
Module::Build::PPMMaker 0.4229
|
||||
Module::Build::Platform::Default 0.4229
|
||||
Module::Build::Platform::MacOS 0.4229
|
||||
Module::Build::Platform::Unix 0.4229
|
||||
Module::Build::Platform::VMS 0.4229
|
||||
Module::Build::Platform::VOS 0.4229
|
||||
Module::Build::Platform::Windows 0.4229
|
||||
Module::Build::Platform::aix 0.4229
|
||||
Module::Build::Platform::cygwin 0.4229
|
||||
Module::Build::Platform::darwin 0.4229
|
||||
Module::Build::Platform::os2 0.4229
|
||||
Module::Build::PodParser 0.4229
|
||||
requirements:
|
||||
CPAN::Meta 2.142060
|
||||
CPAN::Meta::YAML 0.003
|
||||
Cwd 0
|
||||
Data::Dumper 0
|
||||
ExtUtils::CBuilder 0.27
|
||||
|
@ -902,14 +920,11 @@ DISTRIBUTIONS
|
|||
File::Find 0
|
||||
File::Path 0
|
||||
File::Spec 0.82
|
||||
File::Temp 0.15
|
||||
Getopt::Long 0
|
||||
Module::Metadata 1.000002
|
||||
Parse::CPAN::Meta 1.4401
|
||||
Perl::OSType 1
|
||||
Pod::Man 2.17
|
||||
TAP::Harness 3.29
|
||||
Test::More 0.49
|
||||
Text::Abbrev 0
|
||||
Text::ParseWords 0
|
||||
perl 5.006001
|
||||
|
@ -1005,10 +1020,10 @@ DISTRIBUTIONS
|
|||
perl 5.006
|
||||
strict 0
|
||||
warnings 0
|
||||
Module-ScanDeps-1.25
|
||||
pathname: R/RS/RSCHUPP/Module-ScanDeps-1.25.tar.gz
|
||||
Module-ScanDeps-1.27
|
||||
pathname: R/RS/RSCHUPP/Module-ScanDeps-1.27.tar.gz
|
||||
provides:
|
||||
Module::ScanDeps 1.25
|
||||
Module::ScanDeps 1.27
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
File::Spec 0
|
||||
|
@ -1018,10 +1033,10 @@ DISTRIBUTIONS
|
|||
Text::ParseWords 0
|
||||
perl 5.008001
|
||||
version 0
|
||||
Mojo-Pg-4.11
|
||||
pathname: S/SR/SRI/Mojo-Pg-4.11.tar.gz
|
||||
Mojo-Pg-4.15
|
||||
pathname: S/SR/SRI/Mojo-Pg-4.15.tar.gz
|
||||
provides:
|
||||
Mojo::Pg 4.11
|
||||
Mojo::Pg 4.15
|
||||
Mojo::Pg::Database undef
|
||||
Mojo::Pg::Migrations undef
|
||||
Mojo::Pg::PubSub undef
|
||||
|
@ -1034,15 +1049,15 @@ DISTRIBUTIONS
|
|||
Mojolicious 8.03
|
||||
SQL::Abstract 1.86
|
||||
perl 5.010001
|
||||
Mojo-SQLite-3.001
|
||||
pathname: D/DB/DBOOK/Mojo-SQLite-3.001.tar.gz
|
||||
Mojo-SQLite-3.002
|
||||
pathname: D/DB/DBOOK/Mojo-SQLite-3.002.tar.gz
|
||||
provides:
|
||||
Mojo::SQLite 3.001
|
||||
Mojo::SQLite::Database 3.001
|
||||
Mojo::SQLite::Migrations 3.001
|
||||
Mojo::SQLite::PubSub 3.001
|
||||
Mojo::SQLite::Results 3.001
|
||||
Mojo::SQLite::Transaction 3.001
|
||||
Mojo::SQLite 3.002
|
||||
Mojo::SQLite::Database 3.002
|
||||
Mojo::SQLite::Migrations 3.002
|
||||
Mojo::SQLite::PubSub 3.002
|
||||
Mojo::SQLite::Results 3.002
|
||||
Mojo::SQLite::Transaction 3.002
|
||||
requirements:
|
||||
Carp 0
|
||||
DBD::SQLite 1.54
|
||||
|
@ -1057,25 +1072,27 @@ DISTRIBUTIONS
|
|||
URI::db 0.15
|
||||
URI::file 4.21
|
||||
perl 5.010001
|
||||
Mojo-mysql-1.07
|
||||
pathname: J/JH/JHTHORSEN/Mojo-mysql-1.07.tar.gz
|
||||
Mojo-mysql-1.16
|
||||
pathname: T/TE/TEKKI/Mojo-mysql-1.16.tar.gz
|
||||
provides:
|
||||
Blog undef
|
||||
Blog::Controller::Posts undef
|
||||
Blog::Model::Posts undef
|
||||
Mojo::mysql 1.07
|
||||
Mojo::mysql 1.16
|
||||
Mojo::mysql::Database undef
|
||||
Mojo::mysql::Migrations undef
|
||||
Mojo::mysql::PubSub undef
|
||||
Mojo::mysql::Results undef
|
||||
Mojo::mysql::Transaction undef
|
||||
SQL::Abstract::mysql undef
|
||||
requirements:
|
||||
DBD::mysql 4.042
|
||||
DBI 1.627
|
||||
ExtUtils::MakeMaker 0
|
||||
Mojolicious 7.55
|
||||
SQL::Abstract 1.81
|
||||
Mojolicious-8.05
|
||||
pathname: S/SR/SRI/Mojolicious-8.05.tar.gz
|
||||
Mojolicious 8.03
|
||||
SQL::Abstract 1.86
|
||||
Mojolicious-8.22
|
||||
pathname: S/SR/SRI/Mojolicious-8.22.tar.gz
|
||||
provides:
|
||||
Mojo undef
|
||||
Mojo::Asset undef
|
||||
|
@ -1130,7 +1147,6 @@ DISTRIBUTIONS
|
|||
Mojo::Server::Morbo::Backend undef
|
||||
Mojo::Server::Morbo::Backend::Poll undef
|
||||
Mojo::Server::PSGI undef
|
||||
Mojo::Server::PSGI::_IO undef
|
||||
Mojo::Server::Prefork undef
|
||||
Mojo::Template undef
|
||||
Mojo::Transaction undef
|
||||
|
@ -1145,7 +1161,7 @@ DISTRIBUTIONS
|
|||
Mojo::UserAgent::Transactor undef
|
||||
Mojo::Util undef
|
||||
Mojo::WebSocket undef
|
||||
Mojolicious 8.05
|
||||
Mojolicious 8.22
|
||||
Mojolicious::Command undef
|
||||
Mojolicious::Command::Author::cpanify undef
|
||||
Mojolicious::Command::Author::generate undef
|
||||
|
@ -1173,7 +1189,6 @@ DISTRIBUTIONS
|
|||
Mojolicious::Plugin::HeaderCondition undef
|
||||
Mojolicious::Plugin::JSONConfig undef
|
||||
Mojolicious::Plugin::Mount undef
|
||||
Mojolicious::Plugin::PODRenderer undef
|
||||
Mojolicious::Plugin::TagHelpers undef
|
||||
Mojolicious::Plugins undef
|
||||
Mojolicious::Renderer undef
|
||||
|
@ -1300,11 +1315,11 @@ DISTRIBUTIONS
|
|||
ExtUtils::MakeMaker 0
|
||||
Test 0
|
||||
perl 5.006
|
||||
Net-DNS-1.18
|
||||
pathname: N/NL/NLNETLABS/Net-DNS-1.18.tar.gz
|
||||
Net-DNS-1.20
|
||||
pathname: N/NL/NLNETLABS/Net-DNS-1.20.tar.gz
|
||||
provides:
|
||||
Net::DNS 1.18
|
||||
Net::DNS::Domain 1698
|
||||
Net::DNS 1.20
|
||||
Net::DNS::Domain 1726
|
||||
Net::DNS::DomainName 1605
|
||||
Net::DNS::DomainName1035 1605
|
||||
Net::DNS::DomainName2535 1605
|
||||
|
@ -1314,9 +1329,9 @@ DISTRIBUTIONS
|
|||
Net::DNS::Mailbox2535 1605
|
||||
Net::DNS::Nameserver 1692
|
||||
Net::DNS::Packet 1714
|
||||
Net::DNS::Parameters 1714
|
||||
Net::DNS::Question 1714
|
||||
Net::DNS::RR 1714
|
||||
Net::DNS::Parameters 1729
|
||||
Net::DNS::Question 1726
|
||||
Net::DNS::RR 1726
|
||||
Net::DNS::RR::A 1597
|
||||
Net::DNS::RR::AAAA 1597
|
||||
Net::DNS::RR::AFSDB 1597
|
||||
|
@ -1325,20 +1340,20 @@ DISTRIBUTIONS
|
|||
Net::DNS::RR::CAA 1597
|
||||
Net::DNS::RR::CDNSKEY 1586
|
||||
Net::DNS::RR::CDS 1586
|
||||
Net::DNS::RR::CERT 1597
|
||||
Net::DNS::RR::CERT 1729
|
||||
Net::DNS::RR::CNAME 1597
|
||||
Net::DNS::RR::CSYNC 1597
|
||||
Net::DNS::RR::DHCID 1597
|
||||
Net::DNS::RR::DLV 1528
|
||||
Net::DNS::RR::DNAME 1597
|
||||
Net::DNS::RR::DNSKEY 1597
|
||||
Net::DNS::RR::DS 1597
|
||||
Net::DNS::RR::DNSKEY 1729
|
||||
Net::DNS::RR::DS 1729
|
||||
Net::DNS::RR::EUI48 1597
|
||||
Net::DNS::RR::EUI64 1597
|
||||
Net::DNS::RR::GPOS 1528
|
||||
Net::DNS::RR::HINFO 1597
|
||||
Net::DNS::RR::HIP 1597
|
||||
Net::DNS::RR::IPSECKEY 1597
|
||||
Net::DNS::RR::IPSECKEY 1718
|
||||
Net::DNS::RR::ISDN 1597
|
||||
Net::DNS::RR::KEY 1528
|
||||
Net::DNS::RR::KX 1597
|
||||
|
@ -1355,27 +1370,27 @@ DISTRIBUTIONS
|
|||
Net::DNS::RR::NID 1597
|
||||
Net::DNS::RR::NS 1597
|
||||
Net::DNS::RR::NSEC 1696
|
||||
Net::DNS::RR::NSEC3 1694
|
||||
Net::DNS::RR::NSEC3 1726
|
||||
Net::DNS::RR::NSEC3PARAM 1597
|
||||
Net::DNS::RR::NULL 1528
|
||||
Net::DNS::RR::OPENPGPKEY 1597
|
||||
Net::DNS::RR::OPT 1605
|
||||
Net::DNS::RR::OPT::CHAIN 1605
|
||||
Net::DNS::RR::OPT::CLIENT_SUBNET 1605
|
||||
Net::DNS::RR::OPT::COOKIE 1605
|
||||
Net::DNS::RR::OPT::DAU 1605
|
||||
Net::DNS::RR::OPT::DHU 1605
|
||||
Net::DNS::RR::OPT::EXPIRE 1605
|
||||
Net::DNS::RR::OPT::KEY_TAG 1605
|
||||
Net::DNS::RR::OPT::N3U 1605
|
||||
Net::DNS::RR::OPT::PADDING 1605
|
||||
Net::DNS::RR::OPT::TCP_KEEPALIVE 1605
|
||||
Net::DNS::RR::OPT 1717
|
||||
Net::DNS::RR::OPT::CHAIN 1717
|
||||
Net::DNS::RR::OPT::CLIENT_SUBNET 1717
|
||||
Net::DNS::RR::OPT::COOKIE 1717
|
||||
Net::DNS::RR::OPT::DAU 1717
|
||||
Net::DNS::RR::OPT::DHU 1717
|
||||
Net::DNS::RR::OPT::EXPIRE 1717
|
||||
Net::DNS::RR::OPT::KEY_TAG 1717
|
||||
Net::DNS::RR::OPT::N3U 1717
|
||||
Net::DNS::RR::OPT::PADDING 1717
|
||||
Net::DNS::RR::OPT::TCP_KEEPALIVE 1717
|
||||
Net::DNS::RR::PTR 1597
|
||||
Net::DNS::RR::PX 1597
|
||||
Net::DNS::RR::RP 1597
|
||||
Net::DNS::RR::RRSIG 1709
|
||||
Net::DNS::RR::RRSIG 1729
|
||||
Net::DNS::RR::RT 1597
|
||||
Net::DNS::RR::SIG 1709
|
||||
Net::DNS::RR::SIG 1729
|
||||
Net::DNS::RR::SMIMEA 1597
|
||||
Net::DNS::RR::SOA 1597
|
||||
Net::DNS::RR::SPF 1593
|
||||
|
@ -1383,21 +1398,21 @@ DISTRIBUTIONS
|
|||
Net::DNS::RR::SSHFP 1597
|
||||
Net::DNS::RR::TKEY 1528
|
||||
Net::DNS::RR::TLSA 1597
|
||||
Net::DNS::RR::TSIG 1597
|
||||
Net::DNS::RR::TSIG 1726
|
||||
Net::DNS::RR::TXT 1597
|
||||
Net::DNS::RR::URI 1597
|
||||
Net::DNS::RR::X25 1597
|
||||
Net::DNS::Resolver 1714
|
||||
Net::DNS::Resolver::Base 1709
|
||||
Net::DNS::Resolver 1726
|
||||
Net::DNS::Resolver::Base 1727
|
||||
Net::DNS::Resolver::MSWin32 1568
|
||||
Net::DNS::Resolver::Recurse 1709
|
||||
Net::DNS::Resolver::Recurse 1737
|
||||
Net::DNS::Resolver::UNIX 1573
|
||||
Net::DNS::Resolver::android 1568
|
||||
Net::DNS::Resolver::cygwin 1568
|
||||
Net::DNS::Resolver::cygwin 1719
|
||||
Net::DNS::Resolver::os2 1568
|
||||
Net::DNS::Resolver::os390 1579
|
||||
Net::DNS::Text 1698
|
||||
Net::DNS::Update 1714
|
||||
Net::DNS::Resolver::os390 1719
|
||||
Net::DNS::Text 1726
|
||||
Net::DNS::Update 1726
|
||||
Net::DNS::ZoneFile 1709
|
||||
Net::DNS::ZoneFile::Generator 1709
|
||||
Net::DNS::ZoneFile::Text 1709
|
||||
|
@ -1410,7 +1425,7 @@ DISTRIBUTIONS
|
|||
IO::File 1.08
|
||||
IO::Select 1.14
|
||||
IO::Socket::IP 0.38
|
||||
MIME::Base64 2.11
|
||||
MIME::Base64 2.13
|
||||
PerlIO 1.05
|
||||
Scalar::Util 1.25
|
||||
Test::More 0.52
|
||||
|
@ -1424,13 +1439,13 @@ DISTRIBUTIONS
|
|||
Carp 0
|
||||
ExtUtils::MakeMaker 0
|
||||
Storable 0
|
||||
Net-HTTP-6.18
|
||||
pathname: O/OA/OALDERS/Net-HTTP-6.18.tar.gz
|
||||
Net-HTTP-6.19
|
||||
pathname: O/OA/OALDERS/Net-HTTP-6.19.tar.gz
|
||||
provides:
|
||||
Net::HTTP 6.18
|
||||
Net::HTTP::Methods 6.18
|
||||
Net::HTTP::NB 6.18
|
||||
Net::HTTPS 6.18
|
||||
Net::HTTP 6.19
|
||||
Net::HTTP::Methods 6.19
|
||||
Net::HTTP::NB 6.19
|
||||
Net::HTTPS 6.19
|
||||
requirements:
|
||||
Carp 0
|
||||
Compress::Raw::Zlib 0
|
||||
|
@ -1443,16 +1458,15 @@ DISTRIBUTIONS
|
|||
strict 0
|
||||
vars 0
|
||||
warnings 0
|
||||
Net-SSLeay-1.85
|
||||
pathname: M/MI/MIKEM/Net-SSLeay-1.85.tar.gz
|
||||
Net-SSLeay-1.88
|
||||
pathname: C/CH/CHRISN/Net-SSLeay-1.88.tar.gz
|
||||
provides:
|
||||
Net::SSLeay 1.85
|
||||
Net::SSLeay::Handle 0.61
|
||||
Net::SSLeay 1.88
|
||||
Net::SSLeay::Handle 1.88
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 6.36
|
||||
ExtUtils::MakeMaker 0
|
||||
MIME::Base64 0
|
||||
Test::More 0.60_01
|
||||
perl 5.005
|
||||
perl 5.008001
|
||||
NetAddr-IP-4.079
|
||||
pathname: M/MI/MIKER/NetAddr-IP-4.079.tar.gz
|
||||
provides:
|
||||
|
@ -1519,11 +1533,11 @@ DISTRIBUTIONS
|
|||
Sub::Exporter::Progressive 0.001013
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
Sub-Quote-2.005001
|
||||
pathname: H/HA/HAARG/Sub-Quote-2.005001.tar.gz
|
||||
Sub-Quote-2.006003
|
||||
pathname: H/HA/HAARG/Sub-Quote-2.006003.tar.gz
|
||||
provides:
|
||||
Sub::Defer 2.005001
|
||||
Sub::Quote 2.005001
|
||||
Sub::Defer 2.006003
|
||||
Sub::Quote 2.006003
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
Scalar::Util 0
|
||||
|
@ -1567,10 +1581,10 @@ DISTRIBUTIONS
|
|||
Test::More 0.80
|
||||
Test::Warnings 0
|
||||
perl 5.006
|
||||
TermReadKey-2.37
|
||||
pathname: J/JS/JSTOWE/TermReadKey-2.37.tar.gz
|
||||
TermReadKey-2.38
|
||||
pathname: J/JS/JSTOWE/TermReadKey-2.38.tar.gz
|
||||
provides:
|
||||
Term::ReadKey 2.37
|
||||
Term::ReadKey 2.38
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 6.58
|
||||
Test-Exception-0.43
|
||||
|
@ -1687,52 +1701,52 @@ DISTRIBUTIONS
|
|||
perl 5.006
|
||||
strict 0
|
||||
warnings 0
|
||||
URI-1.74
|
||||
pathname: E/ET/ETHER/URI-1.74.tar.gz
|
||||
URI-1.76
|
||||
pathname: O/OA/OALDERS/URI-1.76.tar.gz
|
||||
provides:
|
||||
URI 1.74
|
||||
URI 1.76
|
||||
URI::Escape 3.31
|
||||
URI::Heuristic 4.20
|
||||
URI::IRI 1.74
|
||||
URI::QueryParam 1.74
|
||||
URI::Split 1.74
|
||||
URI::IRI 1.76
|
||||
URI::QueryParam 1.76
|
||||
URI::Split 1.76
|
||||
URI::URL 5.04
|
||||
URI::WithBase 2.20
|
||||
URI::data 1.74
|
||||
URI::data 1.76
|
||||
URI::file 4.21
|
||||
URI::file::Base 1.74
|
||||
URI::file::FAT 1.74
|
||||
URI::file::Mac 1.74
|
||||
URI::file::OS2 1.74
|
||||
URI::file::QNX 1.74
|
||||
URI::file::Unix 1.74
|
||||
URI::file::Win32 1.74
|
||||
URI::ftp 1.74
|
||||
URI::gopher 1.74
|
||||
URI::http 1.74
|
||||
URI::https 1.74
|
||||
URI::ldap 1.74
|
||||
URI::ldapi 1.74
|
||||
URI::ldaps 1.74
|
||||
URI::mailto 1.74
|
||||
URI::mms 1.74
|
||||
URI::news 1.74
|
||||
URI::nntp 1.74
|
||||
URI::pop 1.74
|
||||
URI::rlogin 1.74
|
||||
URI::rsync 1.74
|
||||
URI::rtsp 1.74
|
||||
URI::rtspu 1.74
|
||||
URI::sftp 1.74
|
||||
URI::sip 1.74
|
||||
URI::sips 1.74
|
||||
URI::snews 1.74
|
||||
URI::ssh 1.74
|
||||
URI::telnet 1.74
|
||||
URI::tn3270 1.74
|
||||
URI::urn 1.74
|
||||
URI::urn::isbn 1.74
|
||||
URI::urn::oid 1.74
|
||||
URI::file::Base 1.76
|
||||
URI::file::FAT 1.76
|
||||
URI::file::Mac 1.76
|
||||
URI::file::OS2 1.76
|
||||
URI::file::QNX 1.76
|
||||
URI::file::Unix 1.76
|
||||
URI::file::Win32 1.76
|
||||
URI::ftp 1.76
|
||||
URI::gopher 1.76
|
||||
URI::http 1.76
|
||||
URI::https 1.76
|
||||
URI::ldap 1.76
|
||||
URI::ldapi 1.76
|
||||
URI::ldaps 1.76
|
||||
URI::mailto 1.76
|
||||
URI::mms 1.76
|
||||
URI::news 1.76
|
||||
URI::nntp 1.76
|
||||
URI::pop 1.76
|
||||
URI::rlogin 1.76
|
||||
URI::rsync 1.76
|
||||
URI::rtsp 1.76
|
||||
URI::rtspu 1.76
|
||||
URI::sftp 1.76
|
||||
URI::sip 1.76
|
||||
URI::sips 1.76
|
||||
URI::snews 1.76
|
||||
URI::ssh 1.76
|
||||
URI::telnet 1.76
|
||||
URI::tn3270 1.76
|
||||
URI::urn 1.76
|
||||
URI::urn::isbn 1.76
|
||||
URI::urn::oid 1.76
|
||||
requirements:
|
||||
Carp 0
|
||||
Cwd 0
|
||||
|
@ -1852,32 +1866,32 @@ DISTRIBUTIONS
|
|||
common::sense 3.74
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
libwww-perl-6.36
|
||||
pathname: E/ET/ETHER/libwww-perl-6.36.tar.gz
|
||||
libwww-perl-6.39
|
||||
pathname: O/OA/OALDERS/libwww-perl-6.39.tar.gz
|
||||
provides:
|
||||
LWP 6.36
|
||||
LWP::Authen::Basic 6.36
|
||||
LWP::Authen::Digest 6.36
|
||||
LWP::Authen::Ntlm 6.36
|
||||
LWP::ConnCache 6.36
|
||||
LWP::Debug 6.36
|
||||
LWP::Debug::TraceHTTP 6.36
|
||||
LWP::DebugFile 6.36
|
||||
LWP::MemberMixin 6.36
|
||||
LWP::Protocol 6.36
|
||||
LWP::Protocol::cpan 6.36
|
||||
LWP::Protocol::data 6.36
|
||||
LWP::Protocol::file 6.36
|
||||
LWP::Protocol::ftp 6.36
|
||||
LWP::Protocol::gopher 6.36
|
||||
LWP::Protocol::http 6.36
|
||||
LWP::Protocol::loopback 6.36
|
||||
LWP::Protocol::mailto 6.36
|
||||
LWP::Protocol::nntp 6.36
|
||||
LWP::Protocol::nogo 6.36
|
||||
LWP::RobotUA 6.36
|
||||
LWP::Simple 6.36
|
||||
LWP::UserAgent 6.36
|
||||
LWP 6.39
|
||||
LWP::Authen::Basic 6.39
|
||||
LWP::Authen::Digest 6.39
|
||||
LWP::Authen::Ntlm 6.39
|
||||
LWP::ConnCache 6.39
|
||||
LWP::Debug 6.39
|
||||
LWP::Debug::TraceHTTP 6.39
|
||||
LWP::DebugFile 6.39
|
||||
LWP::MemberMixin 6.39
|
||||
LWP::Protocol 6.39
|
||||
LWP::Protocol::cpan 6.39
|
||||
LWP::Protocol::data 6.39
|
||||
LWP::Protocol::file 6.39
|
||||
LWP::Protocol::ftp 6.39
|
||||
LWP::Protocol::gopher 6.39
|
||||
LWP::Protocol::http 6.39
|
||||
LWP::Protocol::loopback 6.39
|
||||
LWP::Protocol::mailto 6.39
|
||||
LWP::Protocol::nntp 6.39
|
||||
LWP::Protocol::nogo 6.39
|
||||
LWP::RobotUA 6.39
|
||||
LWP::Simple 6.39
|
||||
LWP::UserAgent 6.39
|
||||
libwww::perl undef
|
||||
requirements:
|
||||
CPAN::Meta::Requirements 2.120620
|
||||
|
@ -1904,7 +1918,7 @@ DISTRIBUTIONS
|
|||
MIME::Base64 2.1
|
||||
Module::Metadata 0
|
||||
Net::FTP 2.58
|
||||
Net::HTTP 6.07
|
||||
Net::HTTP 6.18
|
||||
Scalar::Util 0
|
||||
Try::Tiny 0
|
||||
URI 1.10
|
||||
|
@ -1914,20 +1928,20 @@ DISTRIBUTIONS
|
|||
perl 5.008001
|
||||
strict 0
|
||||
warnings 0
|
||||
perl-ldap-0.65
|
||||
pathname: M/MA/MARSCHAP/perl-ldap-0.65.tar.gz
|
||||
perl-ldap-0.66
|
||||
pathname: M/MA/MARSCHAP/perl-ldap-0.66.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 0.66
|
||||
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::DontUseCopy 0.02
|
||||
Net::LDAP::Control::EntryChange 0.02
|
||||
Net::LDAP::Control::ManageDsaIT 0.04
|
||||
Net::LDAP::Control::MatchedValues 0.02
|
||||
|
@ -1943,19 +1957,19 @@ DISTRIBUTIONS
|
|||
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::VLV 0.07
|
||||
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::DSML 0.17
|
||||
Net::LDAP::DSML::output 0.17
|
||||
Net::LDAP::DSML::pp 0.17
|
||||
Net::LDAP::Entry 0.28
|
||||
Net::LDAP::Extension 1.04
|
||||
Net::LDAP::Extension::Cancel 0.02
|
||||
Net::LDAP::Extension::Refresh 0.03
|
||||
Net::LDAP::Extension::Refresh 0.04
|
||||
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::AD 0.05
|
||||
Net::LDAP::Extra::eDirectory 0.03
|
||||
Net::LDAP::Filter 0.20
|
||||
Net::LDAP::FilterList 0.02
|
||||
|
@ -1969,14 +1983,15 @@ DISTRIBUTIONS
|
|||
Net::LDAP::RootDSE 0.02
|
||||
Net::LDAP::Schema 0.9908
|
||||
Net::LDAP::Search 0.14
|
||||
Net::LDAP::Util 0.19
|
||||
Net::LDAP::Util 0.20
|
||||
Net::LDAPI 0.04
|
||||
Net::LDAPS 0.06
|
||||
requirements:
|
||||
Authen::SASL 2.00
|
||||
Convert::ASN1 0.2
|
||||
Digest::HMAC_MD5 0
|
||||
Digest::MD5 0
|
||||
ExtUtils::MakeMaker 6.42
|
||||
ExtUtils::MakeMaker 6.59
|
||||
File::Basename 0
|
||||
File::Compare 0
|
||||
File::Path 0
|
||||
|
|
41
lib/Lufi.pm
41
lib/Lufi.pm
|
@ -110,6 +110,47 @@ sub startup {
|
|||
$r->post('/logout')
|
||||
->to('Auth#log_out')
|
||||
->name('logout');
|
||||
|
||||
if (defined $self->config('ldap') && defined $self->config('invitations')) {
|
||||
# Invitation creation page
|
||||
$r->get('/invite')
|
||||
->name('invite')
|
||||
->to('Invitation#new_invite');
|
||||
|
||||
# Send invitation
|
||||
$r->post('/invite')
|
||||
->to('Invitation#send_invite');
|
||||
|
||||
# Get my invitations
|
||||
$r->get('/invite/list')
|
||||
->name('invite_list')
|
||||
->to('Invitation#my_invitations');
|
||||
|
||||
# Delete invitations
|
||||
$r->post('/invite/list/delete')
|
||||
->name('invite_list_delete')
|
||||
->to('Invitation#delete_invitations');
|
||||
|
||||
# Resend invitation mail
|
||||
$r->post('/invite/list/resend')
|
||||
->name('invite_list_resend')
|
||||
->to('Invitation#resend_invitations');
|
||||
|
||||
# Toggle invitations visibility
|
||||
$r->post('/invite/list/visibility')
|
||||
->name('invite_list_visibility')
|
||||
->to('Invitation#toggle_invitations_visibility');
|
||||
|
||||
# I’m a guest
|
||||
$r->get('/guest/:token')
|
||||
->name('guest')
|
||||
->to('Invitation#guest');
|
||||
|
||||
# I’m a guest and I sent all my files
|
||||
$r->post('/guest/:token/send_mail')
|
||||
->name('guest_send_mail')
|
||||
->to('Invitation#send_mail_to_ldap_user');
|
||||
}
|
||||
}
|
||||
|
||||
# About page
|
||||
|
|
|
@ -2,6 +2,7 @@ package Lufi::Command::sqliteToOtherDB;
|
|||
use Mojo::Base 'Mojolicious::Command';
|
||||
use Lufi::DB::File;
|
||||
use Lufi::DB::Slice;
|
||||
use Lufi::DB::Invitation;
|
||||
use Mojo::SQLite;
|
||||
use FindBin qw($Bin);
|
||||
use Term::ProgressBar;
|
||||
|
@ -31,11 +32,12 @@ sub run {
|
|||
exit 1;
|
||||
}
|
||||
|
||||
my $sqlite = Mojo::SQLite->new('sqlite:'.$config->{db_path});
|
||||
my $files = $sqlite->db->select('files', undef)->hashes;
|
||||
my $slices = $sqlite->db->select('slices', undef)->hashes;
|
||||
my $sqlite = Mojo::SQLite->new('sqlite:'.$config->{db_path});
|
||||
my $files = $sqlite->db->select('files', undef)->hashes;
|
||||
my $slices = $sqlite->db->select('slices', undef)->hashes;
|
||||
my $invitations = $sqlite->db->select('invitations', undef)->hashes;
|
||||
|
||||
my $progress = Term::ProgressBar->new({count => $files->size + $slices->size});
|
||||
my $progress = Term::ProgressBar->new({count => $files->size + $slices->size + $invitations->size});
|
||||
|
||||
$files->each(sub {
|
||||
my ($file, $num) = @_;
|
||||
|
@ -72,6 +74,24 @@ sub run {
|
|||
|
||||
$progress->update();
|
||||
});
|
||||
$invitations->each(sub {
|
||||
my ($invitation, $num) = @_;
|
||||
|
||||
Lufi::DB::Invitation->new(app => $c->app)
|
||||
->token($invitation->{token})
|
||||
->ldap_user($invitation->{ldap_user})
|
||||
->ldap_user_mail($invitation->{ldap_user_mail})
|
||||
->guest_mail($invitation->{guest_mail})
|
||||
->created_at($invitation->{created_at})
|
||||
->expire_at($invitation->{expire_at})
|
||||
->files_sent_at($invitation->{files_sent_at})
|
||||
->expend_expire_at($invitation->{expend_expire_at})
|
||||
->files($invitation->{files})
|
||||
->show_in_list($invitation->{show_in_list})
|
||||
->deleted($invitation->{deleted})
|
||||
->write();
|
||||
$progress->update();
|
||||
});
|
||||
}
|
||||
|
||||
=encoding utf8
|
||||
|
|
|
@ -4,26 +4,36 @@ use Mojo::Base 'Mojolicious::Controller';
|
|||
|
||||
sub login_page {
|
||||
my $c = shift;
|
||||
my $redirect = $c->param('redirect') // 'index';
|
||||
|
||||
if ($c->is_user_authenticated) {
|
||||
$c->redirect_to('index');
|
||||
} else {
|
||||
$c->render(template => 'login');
|
||||
$c->render(
|
||||
template => 'login',
|
||||
redirect => $redirect
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sub login {
|
||||
my $c = shift;
|
||||
|
||||
my $login = $c->param('login');
|
||||
my $pwd = $c->param('password');
|
||||
my $login = $c->param('login');
|
||||
my $pwd = $c->param('password');
|
||||
my $redirect = $c->param('redirect') // 'index';
|
||||
|
||||
if ($c->validation->csrf_protect->has_error('csrf_token')) {
|
||||
$c->stash(msg => $c->l('Bad CSRF token.'));
|
||||
$c->render(template => 'login');
|
||||
} else {
|
||||
if($c->authenticate($login, $pwd)) {
|
||||
$c->redirect_to('index');
|
||||
if ($redirect eq 'invite') {
|
||||
return $c->redirect_to('invite');
|
||||
} elsif ($redirect eq 'my_invitations') {
|
||||
return $c->redirect_to('invite_list');
|
||||
}
|
||||
return $c->redirect_to('index');
|
||||
} else {
|
||||
$c->stash(msg => $c->l('Please, check your credentials or your right to access this service: unable to authenticate.'));
|
||||
$c->render(template => 'login');
|
||||
|
|
|
@ -24,7 +24,10 @@ sub files {
|
|||
sub upload {
|
||||
my $c = shift;
|
||||
|
||||
if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) {
|
||||
my $invitation;
|
||||
my $token = $c->session->{guest_token};
|
||||
$invitation = Lufi::DB::Invitation->new(app => $c->app)->from_token($token) if $token;
|
||||
if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated || $invitation) {
|
||||
$c->inactivity_timeout(30000000);
|
||||
|
||||
$c->app->log->debug('Client connected');
|
||||
|
@ -33,6 +36,8 @@ sub upload {
|
|||
message => sub {
|
||||
my ($ws, $text) = @_;
|
||||
|
||||
my $invit = Lufi::DB::Invitation->new(app => $c->app)->from_token($token) if $token;
|
||||
|
||||
my $begin = time;
|
||||
|
||||
my ($json) = split('XXMOJOXX', $text, 2);
|
||||
|
@ -81,7 +86,7 @@ sub upload {
|
|||
)));
|
||||
}
|
||||
# Check against max_size
|
||||
elsif (defined $c->config('max_file_size')) {
|
||||
if (defined $c->config('max_file_size')) {
|
||||
if ($json->{size} > $c->config('max_file_size')) {
|
||||
$stop = 1;
|
||||
return $ws->send(decode('UTF-8', encode_json(
|
||||
|
@ -95,7 +100,7 @@ sub upload {
|
|||
}
|
||||
}
|
||||
# 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}) {
|
||||
if ($json->{part} == 0 && ($json->{size} * 2) >= dfportable($c->config('upload_dir'))->{bavail}) {
|
||||
$stop = 1;
|
||||
return $ws->send(decode('UTF-8', encode_json(
|
||||
{
|
||||
|
@ -106,6 +111,18 @@ sub upload {
|
|||
}
|
||||
)));
|
||||
}
|
||||
# Check that the invitation is still valid, but only if it's the first chunk
|
||||
# (i.e. a new file, we don't want to stop a current uploading)
|
||||
if ($json->{part} == 0 && $invit && !$invit->is_valid()) {
|
||||
$stop = 1;
|
||||
$c->app->log->info(sprintf('Someone (%s) tried to use an expired or deleted invitation.', $invit->guest_mail));
|
||||
$ws->send(decode('UTF-8', encode_json(
|
||||
{
|
||||
success => false,
|
||||
msg => $c->l('Sorry, your invitation has expired or has been deleted. Please contact %1 to have another invitation.', $invit->ldap_user_mail),
|
||||
}
|
||||
)));
|
||||
}
|
||||
|
||||
unless ($stop) {
|
||||
my $f;
|
||||
|
@ -142,9 +159,15 @@ sub upload {
|
|||
}
|
||||
|
||||
my $creator = $c->ip;
|
||||
if (defined($c->config('ldap')) || defined($c->config('htpasswd'))) {
|
||||
$creator = 'User: '.$c->current_user->{username}.', IP: '.$creator;
|
||||
# Authenticated user logging
|
||||
if ((defined($c->config('ldap')) || defined($c->config('htpasswd'))) && !$invitation) {
|
||||
$creator = sprintf('User: %s, IP: %s', $c->current_user->{username}, $creator);
|
||||
}
|
||||
# Guest user logging
|
||||
if ($invitation) {
|
||||
$creator = sprintf('User: %s, IP: %s', $invitation->guest_mail, $creator);
|
||||
}
|
||||
|
||||
my $delete_at_first_view = ($json->{del_at_first_view}) ? 1 : 0;
|
||||
$delete_at_first_view = 1 if $c->app->config('force_burn_after_reading');
|
||||
$f = Lufi::DB::File->new(app => $c->app)->get_empty()
|
||||
|
@ -190,23 +213,22 @@ sub upload {
|
|||
}
|
||||
}
|
||||
|
||||
$ws->send(to_json(
|
||||
{
|
||||
success => true,
|
||||
i => $json->{i},
|
||||
j => $json->{part},
|
||||
parts => $json->{total},
|
||||
short => $f->short,
|
||||
name => $f->filename,
|
||||
size => $f->filesize,
|
||||
del_at_first_view => (($f->delete_at_first_view) ? true : false),
|
||||
created_at => $f->created_at,
|
||||
delay => $f->delete_at_day,
|
||||
token => $f->mod_token,
|
||||
sent_delay => $json->{delay},
|
||||
duration => time - $begin
|
||||
}
|
||||
));
|
||||
my $result = {
|
||||
success => true,
|
||||
i => $json->{i},
|
||||
j => $json->{part},
|
||||
parts => $json->{total},
|
||||
short => $f->short,
|
||||
name => $f->filename,
|
||||
size => $f->filesize,
|
||||
del_at_first_view => (($f->delete_at_first_view) ? true : false),
|
||||
created_at => $f->created_at,
|
||||
delay => $f->delete_at_day,
|
||||
token => $f->mod_token,
|
||||
sent_delay => $json->{delay},
|
||||
duration => time - $begin
|
||||
};
|
||||
$ws->send(to_json($result));
|
||||
} else {
|
||||
$ws->send(decode('UTF-8', encode_json(
|
||||
{
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lufi::Controller::Invitation;
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
use Mojo::Collection 'c';
|
||||
use Mojo::File;
|
||||
use Mojo::JSON qw(true false decode_json encode_json);
|
||||
use Mojo::URL;
|
||||
use Email::Valid;
|
||||
use Lufi::DB::File;
|
||||
use Lufi::DB::Invitation;
|
||||
use Date::Format;
|
||||
|
||||
sub new_invite {
|
||||
my $c = shift;
|
||||
|
||||
# The `if (defined($c->config('ldap')))` is at the router level in lib/Lufi.pm
|
||||
if ($c->is_user_authenticated) {
|
||||
my $mail_attr = $c->config('invitations')->{'mail_attr'} // 'mail';
|
||||
my $max_expire_at = $c->config('invitations')->{'max_invitation_expiration_delay'} // 30;
|
||||
my $send_with_user_email = defined $c->config('invitations')->{'send_invitation_with_ldap_user_mail'};
|
||||
$c->render(
|
||||
template => 'invitations/invite',
|
||||
max_expire_at => $max_expire_at,
|
||||
send_with_user_email => $send_with_user_email,
|
||||
user_mail => ($send_with_user_email) ? $c->current_user->{$mail_attr} : '',
|
||||
fails => [],
|
||||
success => []
|
||||
);
|
||||
} else {
|
||||
$c->redirect_to($c->url_for('login')->query(redirect => 'invite'));
|
||||
}
|
||||
}
|
||||
|
||||
sub send_invite {
|
||||
my $c = shift;
|
||||
my $guest_mail = $c->param('guest_mail');
|
||||
my $expire_at = $c->param('expire_at');
|
||||
|
||||
my $mail_attr = $c->config('invitations')->{'mail_attr'} // 'mail';
|
||||
my $max_expire_at = $c->config('invitations')->{'max_invitation_expiration_delay'} // 30;
|
||||
my $send_with_user_email = defined $c->config('invitations')->{'send_invitation_with_ldap_user_mail'};
|
||||
|
||||
# The `if (defined($c->config('ldap')))` is at the router level in lib/Lufi.pm
|
||||
if ($c->is_user_authenticated) {
|
||||
my @fails = ();
|
||||
my @success = ();
|
||||
unless (Email::Valid->address($guest_mail)) {
|
||||
push @fails, $c->l('The guest email address (%1) is unvalid.', $guest_mail);
|
||||
}
|
||||
unless ($expire_at >= 1 && $expire_at <= $max_expire_at) {
|
||||
push @fails, $c->l('The expiration delay (%1) is not between 1 and %2 days.', $expire_at, $max_expire_at);
|
||||
}
|
||||
|
||||
unless (scalar(@fails)) {
|
||||
my $invitation = Lufi::DB::Invitation->new(app => $c->app);
|
||||
my $mail_attr = $c->config('invitations')->{'mail_attr'} // 'mail';
|
||||
my $expend_expire_at = $c->config('invitations')->{'max_additional_period'} // 10;
|
||||
|
||||
my $token;
|
||||
do {
|
||||
$token = $c->create_invitation_token;
|
||||
} while ($invitation->is_token_used($token));
|
||||
|
||||
$invitation = $invitation->from_token($token);
|
||||
$invitation->ldap_user($c->current_user->{username});
|
||||
$invitation->ldap_user_mail($c->current_user->{$mail_attr});
|
||||
$invitation->created_at(time);
|
||||
$invitation->guest_mail($guest_mail);
|
||||
$invitation->expire_at($invitation->created_at + 86400 * $expire_at);
|
||||
$invitation->expend_expire_at($expend_expire_at);
|
||||
$invitation->show_in_list(1);
|
||||
$invitation = $invitation->write;
|
||||
|
||||
my $from = ($c->config('invitations')->{'send_invitation_with_ldap_user_mail'}) ? $invitation->ldap_user_mail : $c->config('mail_sender');
|
||||
my $url = $c->url_for('guest', token => $invitation->token)->to_abs;
|
||||
$c->mail(
|
||||
from => $from,
|
||||
to => $invitation->guest_mail,
|
||||
template => 'invitations/invite',
|
||||
format => 'mail',
|
||||
ldap_user => ucfirst($invitation->ldap_user),
|
||||
url => $url,
|
||||
invitation => $invitation,
|
||||
expires => time2str($c->l('%A %d %B %Y at %T'), $invitation->expire_at)
|
||||
);
|
||||
|
||||
push @success, $c->l('Invitation sent to %1.<br> URL: %2', $invitation->guest_mail, $url);
|
||||
}
|
||||
|
||||
$c->render(
|
||||
template => 'invitations/invite',
|
||||
max_expire_at => $max_expire_at,
|
||||
send_with_user_email => $send_with_user_email,
|
||||
user_mail => ($send_with_user_email) ? $c->current_user->{$mail_attr} : '',
|
||||
fails => \@fails,
|
||||
success => \@success
|
||||
);
|
||||
} else {
|
||||
$c->redirect_to('login');
|
||||
}
|
||||
}
|
||||
|
||||
sub my_invitations {
|
||||
my $c = shift;
|
||||
|
||||
# The `if (defined($c->config('ldap')))` is at the router level in lib/Lufi.pm
|
||||
if ($c->is_user_authenticated) {
|
||||
my $invitations = Lufi::DB::Invitation->new(app => $c->app)
|
||||
->from_user($c->current_user->{username});
|
||||
$invitations = c() unless $invitations;
|
||||
$c->render(
|
||||
template => 'invitations/my_invitations',
|
||||
invitations => $invitations
|
||||
);
|
||||
} else {
|
||||
$c->redirect_to($c->url_for('login')->query(redirect => 'my_invitations'));
|
||||
}
|
||||
}
|
||||
|
||||
sub delete_invitations {
|
||||
my $c = shift;
|
||||
my @tokens = @{$c->every_param('tokens[]')};
|
||||
|
||||
my @result = ();
|
||||
for my $token (@tokens) {
|
||||
my $i = Lufi::DB::Invitation->new(app => $c->app)
|
||||
->from_token($token)
|
||||
->deleted(1)
|
||||
->write;
|
||||
push @result, { msg => $c->l('The invitation %1 has been deleted.', $i->token), token => $i->token, deleted => $i->deleted };
|
||||
}
|
||||
|
||||
$c->render(json => {
|
||||
success => true,
|
||||
tokens => \@result
|
||||
});
|
||||
}
|
||||
|
||||
sub resend_invitations {
|
||||
my $c = shift;
|
||||
my @tokens = @{$c->every_param('tokens[]')};
|
||||
|
||||
my @success;
|
||||
my @failures;
|
||||
for my $token (@tokens) {
|
||||
my $i = Lufi::DB::Invitation->new(app => $c->app)
|
||||
->from_token($token);
|
||||
|
||||
if ($i->files_sent_at) {
|
||||
push @failures, $c->l('The invitation %1 can’t be resend: %2 has already sent files.<br>Please create a new invitation.', $i->token, $i->guest_mail);
|
||||
} else {
|
||||
if ($c->config('invitations')->{'extend_invitation_expiration_on_resend'}) {
|
||||
$i->expire_at(time + $i->expire_at - $i->created_at)
|
||||
->write;
|
||||
}
|
||||
|
||||
my $from = ($c->config('invitations')->{'send_invitation_with_ldap_user_mail'}) ? $i->ldap_user_mail : $c->config('mail_sender');
|
||||
my $url = $c->url_for('guest', token => $i->token)->to_abs;
|
||||
my $expire = time2str($c->l('%A %d %B %Y at %T'), $i->expire_at);
|
||||
$c->mail(
|
||||
from => $from,
|
||||
to => $i->guest_mail,
|
||||
template => 'invitations/invite',
|
||||
format => 'mail',
|
||||
ldap_user => ucfirst($i->ldap_user),
|
||||
url => $url,
|
||||
invitation => $i,
|
||||
expires => $expire
|
||||
);
|
||||
|
||||
push @success, { msg => $c->l('Invitation resent to %1.<br> URL: %2', $i->guest_mail, $url), expires => $expire, token => $i->token };
|
||||
}
|
||||
}
|
||||
|
||||
$c->render(json => {
|
||||
success => \@success,
|
||||
failures => \@failures
|
||||
});
|
||||
}
|
||||
|
||||
sub toggle_invitations_visibility {
|
||||
my $c = shift;
|
||||
my @tokens = @{$c->every_param('tokens[]')};
|
||||
|
||||
my @result = ();
|
||||
for my $token (@tokens) {
|
||||
my $i = Lufi::DB::Invitation->new(app => $c->app)
|
||||
->from_token($token)
|
||||
->toggle_visibility;
|
||||
push @result, { token => $i->token, show => ($i->show_in_list) ? true : false }
|
||||
}
|
||||
|
||||
$c->render(json => {
|
||||
success => true,
|
||||
tokens => \@result
|
||||
});
|
||||
}
|
||||
|
||||
sub guest {
|
||||
my $c = shift;
|
||||
my $token = $c->param('token');
|
||||
|
||||
my $invitation = Lufi::DB::Invitation->new(app => $c->app)->from_token($token);
|
||||
if ($invitation) {
|
||||
if ($invitation->is_valid) {
|
||||
$c->session->{guest_token} = $token;
|
||||
$c->session(expires => $invitation->expire_at);
|
||||
return $c->render(
|
||||
template => 'index',
|
||||
invitation => $invitation
|
||||
);
|
||||
} else {
|
||||
$c->stash('expired_or_deleted_invitation' => 1);
|
||||
}
|
||||
} else {
|
||||
$c->stash('invitation_not_found' => 1);
|
||||
}
|
||||
return $c->render(template => 'invitations/exception');
|
||||
}
|
||||
|
||||
sub send_mail_to_ldap_user {
|
||||
my $c = shift;
|
||||
my $token = $c->param('token');
|
||||
my $urls = c(@{$c->every_param('urls[]')});
|
||||
|
||||
my $invitation = Lufi::DB::Invitation->new(app => $c->app)->from_token($token);
|
||||
if ($invitation) {
|
||||
my @files = ();
|
||||
if ($c->config('invitations')->{'save_files_url_in_db'} && $urls->size) {
|
||||
my $guest_files = $invitation->files;
|
||||
my %list_token;
|
||||
if ($guest_files) {
|
||||
$guest_files = decode_json($guest_files);
|
||||
for my $file (@{$guest_files}) {
|
||||
$list_token{$file->{token}} = 1;
|
||||
}
|
||||
} else {
|
||||
$guest_files = [];
|
||||
}
|
||||
push @files, @{$guest_files};
|
||||
$urls->each(sub {
|
||||
my ($e, $num) = @_;
|
||||
$e = decode_json($e);
|
||||
if (!defined($list_token{$e->{token}})) {
|
||||
push @{$guest_files}, $e;
|
||||
push @files, $e;
|
||||
}
|
||||
});
|
||||
$invitation->files(encode_json($guest_files));
|
||||
$invitation->write;
|
||||
} else {
|
||||
$urls->each(sub {
|
||||
push @files, decode_json(shift);
|
||||
});
|
||||
}
|
||||
my $already_notified = 1;
|
||||
unless ($invitation->files_sent_at) {
|
||||
$invitation->files_sent_at(time);
|
||||
$invitation->write;
|
||||
$already_notified = 0;
|
||||
}
|
||||
$c->session(expires => $invitation->files_sent_at + 60 * $invitation->expend_expire_at);
|
||||
$c->mail(
|
||||
from => $c->config('mail_sender'),
|
||||
to => $invitation->ldap_user_mail,
|
||||
template => 'invitations/notification_files_sent',
|
||||
format => 'mail',
|
||||
files => c(@files),
|
||||
invitation => $invitation,
|
||||
already_notified => $already_notified
|
||||
);
|
||||
|
||||
return $c->render(
|
||||
json => {
|
||||
success => true,
|
||||
msg => $c->l('The URLs of your files have been sent by email to %1.', $invitation->ldap_user_mail)
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => false,
|
||||
msg => $c->l('Sorry, the invitation doesn’t exist. Are you sure you are on the right URL?')
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,426 @@
|
|||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lufi::DB::Invitation;
|
||||
use Mojo::Base -base;
|
||||
use Mojo::File;
|
||||
use Mojo::Collection 'c';
|
||||
|
||||
has 'token';
|
||||
has 'ldap_user';
|
||||
has 'ldap_user_mail';
|
||||
has 'guest_mail';
|
||||
has 'created_at';
|
||||
has 'expire_at';
|
||||
has 'files_sent_at';
|
||||
has 'expend_expire_at';
|
||||
has 'files';
|
||||
has 'show_in_list' => 1;
|
||||
has 'deleted' => 0;
|
||||
has 'record' => 0;
|
||||
has 'app';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Lufi::DB::Invitation - DB abstraction layer for Lufi invitations
|
||||
|
||||
=head1 Contributing
|
||||
|
||||
When creating a new database accessor, make sure that it provides the following subroutines.
|
||||
After that, modify this file and modify the C<new> subroutine to allow to use your accessor.
|
||||
|
||||
Have a look at Lufi::DB::Invitation::SQLite's code: it's simple and may be more understandable that this doc.
|
||||
|
||||
=head1 Attributes
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<token> : string, invitation token
|
||||
|
||||
=item B<ldap_user> : string, the user who created the invitation
|
||||
|
||||
=item B<ldap_user_mail> : string, the email of the user who created the invitation
|
||||
|
||||
=item B<guest_mail> : string, the email of the guest
|
||||
|
||||
=item B<created_at> : unix timestamp
|
||||
|
||||
=item B<expire_at> : unix timestamp
|
||||
|
||||
=item B<files_sent_at> : unix timestamp
|
||||
|
||||
=item B<expend_expire_at> : integer, "error" delay, in minutes
|
||||
|
||||
=item B<files> : string, optional, list of files sent by the guest
|
||||
|
||||
=item B<show_in_list> : boolean, if the ldap user want to see the invitation in his/her invitations list
|
||||
|
||||
=item B<deleted> : boolean
|
||||
|
||||
=item B<app> : a Mojolicious object
|
||||
|
||||
=back
|
||||
|
||||
=head1 Sub routines
|
||||
|
||||
=head2 new
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c = Lufi::DB::Invitation-E<gt>new(app =E<gt> $self);>
|
||||
|
||||
=item B<Arguments> : any of the attribute above
|
||||
|
||||
=item B<Purpose> : construct a new db accessor object. If the C<short> attribute is provided, it have to load the informations from the database.
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=item B<Info> : the app argument is used by Lufi::DB::Invitation to choose which db accessor will be used, you don't need to use it in new(), but you can use it to access helpers or configuration settings in the other subroutines
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $c = shift;
|
||||
|
||||
$c = $c->SUPER::new(@_);
|
||||
|
||||
if (ref($c) eq 'Lufi::DB::Invitation') {
|
||||
my $dbtype = $c->app->config('dbtype');
|
||||
if ($dbtype eq 'sqlite') {
|
||||
use Lufi::DB::Invitation::SQLite;
|
||||
$c = Lufi::DB::Invitation::SQLite->new(@_);
|
||||
} elsif ($dbtype eq 'postgresql') {
|
||||
use Lufi::DB::Invitation::Pg;
|
||||
$c = Lufi::DB::Invitation::Pg->new(@_);
|
||||
} elsif ($dbtype eq 'mysql') {
|
||||
use Lufi::DB::Invitation::Mysql;
|
||||
$c = Lufi::DB::Invitation::Mysql->new(@_);
|
||||
}
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub to_hash {
|
||||
my $c = shift;
|
||||
|
||||
return {
|
||||
token => $c->token,
|
||||
ldap_user => $c->ldap_user,
|
||||
ldap_user_mail => $c->ldap_user_mail,
|
||||
guest_mail => $c->guest_mail,
|
||||
created_at => $c->created_at,
|
||||
expire_at => $c->expire_at,
|
||||
files_sent_at => $c->files_sent_at,
|
||||
expend_expire_at => $c->expend_expire_at,
|
||||
files => $c->files,
|
||||
show_in_list => $c->show_in_list,
|
||||
deleted => $c->deleted
|
||||
};
|
||||
}
|
||||
|
||||
=head2 delete
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>delete>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : set the C<deleted> flag to true
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub delete {
|
||||
my $c = shift;
|
||||
|
||||
$c->deleted(1);
|
||||
|
||||
$c->write;
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
=head2 hide
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>hide>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : set the C<show_in_list> flag to false
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub hide {
|
||||
my $c = shift;
|
||||
|
||||
$c->show_in_list(0);
|
||||
|
||||
$c->write;
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
=head2 show
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>show>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : set the C<show_in_list> flag to true
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub show {
|
||||
my $c = shift;
|
||||
|
||||
$c->show_in_list(1);
|
||||
|
||||
$c->write;
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
=head2 toggle_visibility
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>toggle_visibility>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : toggle the C<show_in_list> flag
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub toggle_visibility {
|
||||
my $c = shift;
|
||||
|
||||
if ($c->show_in_list) {
|
||||
return $c->hide;
|
||||
} else {
|
||||
return $c->show;
|
||||
}
|
||||
}
|
||||
|
||||
=head2 write
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>write>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : create or update a record in the database, with the values of the object's attributes
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub write {
|
||||
my $c = shift;
|
||||
|
||||
if ($c->record) {
|
||||
$c->app->dbi->db->update('invitations', $c->to_hash, { token => $c->token });
|
||||
} else {
|
||||
$c->app->dbi->db->insert('invitations', $c->to_hash);
|
||||
$c->record(1);
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
=head2 from_token
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>from_token($token)>
|
||||
|
||||
=item B<Arguments> : string
|
||||
|
||||
=item B<Purpose> : find an invitation in the database from its C<token> attribute
|
||||
|
||||
=item B<Returns> : a db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub from_token {
|
||||
my $c = shift;
|
||||
my $token = shift;
|
||||
|
||||
my $r = $c->app->dbi->db->select('invitations', undef, { token => $token })->hashes;
|
||||
|
||||
if ($r->size) {
|
||||
return $c->_slurp($r->first)->record(1);
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
=head2 from_user
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>from_user($mail)>
|
||||
|
||||
=item B<Arguments> : string
|
||||
|
||||
=item B<Purpose> : find invitations in the database from their C<ldap_user_mail> attribute
|
||||
|
||||
=item B<Returns> : a Mojo::Collection of Lufi::DB::Invitation objects, sorted by creation date
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub from_user {
|
||||
my $c = shift;
|
||||
my $user = shift;
|
||||
|
||||
my $r = $c->app->dbi->db
|
||||
->select('invitations', undef, { ldap_user => $user })
|
||||
->hashes;
|
||||
|
||||
if ($r->size) {
|
||||
my @invitations;
|
||||
$r->each(sub {
|
||||
my ($e, $num) = @_;
|
||||
$e->{app} = $c->app;
|
||||
$e->{record} = 1;
|
||||
push @invitations, Lufi::DB::Invitation->new($e);
|
||||
});
|
||||
return c(@invitations);
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
=head2 is_token_used
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>is_token_used($token)>
|
||||
|
||||
=item B<Arguments> : string
|
||||
|
||||
=item B<Purpose> : tells if a token is already used. If not, insert it in database to reserve it
|
||||
|
||||
=item B<Returns> : a boolean
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub is_token_used {
|
||||
my $c = shift;
|
||||
my $token = shift;
|
||||
|
||||
my $r = $c->app->dbi->db->select('invitations', ['token'], { token => $token })->hashes;
|
||||
|
||||
if ($r->size) {
|
||||
return 1;
|
||||
} else {
|
||||
$c->app->dbi->db->insert('invitations', { token => $token });
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
=head2 is_valid
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>is_valid()>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : tells if an invitation is still valid
|
||||
|
||||
=item B<Returns> : a boolean
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub is_valid {
|
||||
my $c = shift;
|
||||
|
||||
my $time = time;
|
||||
# Active After creation date Before expiration date Before files send date plus extension delay
|
||||
return (!$c->deleted && $time >= $c->created_at && $time < $c->expire_at && (!defined($c->files_sent_at) || $time < ($c->files_sent_at + $c->expend_expire_at * 60)));
|
||||
}
|
||||
|
||||
=head2 _slurp
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>_slurp>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : put a database record's columns into the Lufi::DB::Invitation object's attributes
|
||||
|
||||
=item B<Returns> : the Lufi::DB::Invitation object
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub _slurp {
|
||||
my $c = shift;
|
||||
my $r = shift;
|
||||
|
||||
my $invitation;
|
||||
if (defined $r) {
|
||||
$invitation = $r;
|
||||
} else {
|
||||
my $invitations = $c->app->dbi->db->select('invitations', undef, { token => $c->token })->hashes;
|
||||
|
||||
if ($invitations->size) {
|
||||
$invitation = $invitations->first;
|
||||
}
|
||||
}
|
||||
|
||||
if ($invitation) {
|
||||
$c->token( $invitation->{token} );
|
||||
$c->ldap_user( $invitation->{ldap_user} );
|
||||
$c->ldap_user_mail( $invitation->{ldap_user_mail} );
|
||||
$c->guest_mail( $invitation->{guest_mail} );
|
||||
$c->created_at( $invitation->{created_at} );
|
||||
$c->expire_at( $invitation->{expire_at} );
|
||||
$c->files_sent_at( $invitation->{files_sent_at} );
|
||||
$c->expend_expire_at($invitation->{expend_expire_at});
|
||||
$c->files( $invitation->{files} );
|
||||
$c->show_in_list( $invitation->{show_in_list} );
|
||||
$c->deleted( $invitation->{deleted} );
|
||||
|
||||
$c->record(1) unless $c->record;
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,13 @@
|
|||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lufi::DB::Invitation::Mysql;
|
||||
use Mojo::Base 'Lufi::DB::Invitation';
|
||||
|
||||
sub new {
|
||||
my $c = shift;
|
||||
|
||||
$c = $c->SUPER::new(@_);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,13 @@
|
|||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lufi::DB::Invitation::Pg;
|
||||
use Mojo::Base 'Lufi::DB::Invitation';
|
||||
|
||||
sub new {
|
||||
my $c = shift;
|
||||
|
||||
$c = $c->SUPER::new(@_);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,14 @@
|
|||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lufi::DB::Invitation::SQLite;
|
||||
use Mojo::Base 'Lufi::DB::Invitation';
|
||||
|
||||
sub new {
|
||||
my $c = shift;
|
||||
|
||||
$c = $c->SUPER::new(@_);
|
||||
$c = $c->_slurp if defined $c->record;
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
1;
|
|
@ -2,6 +2,7 @@
|
|||
package Lufi::Plugin::Helpers;
|
||||
use Mojo::Base 'Mojolicious::Plugin';
|
||||
use Lufi::DB::File;
|
||||
use Lufi::DB::Invitation;
|
||||
|
||||
sub register {
|
||||
my ($self, $app) = @_;
|
||||
|
@ -11,7 +12,6 @@ sub register {
|
|||
$app->plugin('PgURLHelper');
|
||||
}
|
||||
|
||||
|
||||
if ($app->config('dbtype') eq 'postgresql') {
|
||||
require Mojo::Pg;
|
||||
$app->helper(dbi => \&_pg);
|
||||
|
@ -19,9 +19,9 @@ sub register {
|
|||
# Database migration
|
||||
my $migrations = Mojo::Pg::Migrations->new(pg => $app->dbi);
|
||||
if ($app->mode eq 'development' && $ENV{LUFI_DEV}) {
|
||||
$migrations->from_file('utilities/migrations/pg.sql')->migrate(0)->migrate(3);
|
||||
$migrations->from_file('utilities/migrations/pg.sql')->migrate(0)->migrate($migrations->latest);
|
||||
} else {
|
||||
$migrations->from_file('utilities/migrations/pg.sql')->migrate(3);
|
||||
$migrations->from_file('utilities/migrations/pg.sql')->migrate($migrations->latest);
|
||||
}
|
||||
} elsif ($app->config('dbtype') eq 'mysql') {
|
||||
require Mojo::mysql;
|
||||
|
@ -30,9 +30,9 @@ sub register {
|
|||
# Database migration
|
||||
my $migrations = Mojo::mysql::Migrations->new(mysql => $app->dbi);
|
||||
if ($app->mode eq 'development' && $ENV{LUFI_DEV}) {
|
||||
$migrations->from_file('utilities/migrations/mysql.sql')->migrate(0)->migrate(2);
|
||||
$migrations->from_file('utilities/migrations/mysql.sql')->migrate(0)->migrate($migrations->latest);
|
||||
} else {
|
||||
$migrations->from_file('utilities/migrations/mysql.sql')->migrate(2);
|
||||
$migrations->from_file('utilities/migrations/mysql.sql')->migrate($migrations->latest);
|
||||
}
|
||||
} elsif ($app->config('dbtype') eq 'sqlite') {
|
||||
require Mojo::SQLite;
|
||||
|
@ -43,9 +43,9 @@ sub register {
|
|||
my $sql = $app->dbi;
|
||||
my $migrations = $sql->migrations;
|
||||
if ($app->mode eq 'development' && $ENV{LUFI_DEV}) {
|
||||
$migrations->from_file('utilities/migrations/sqlite.sql')->migrate(0)->migrate(3);
|
||||
$migrations->from_file('utilities/migrations/sqlite.sql')->migrate(0)->migrate($migrations->latest);
|
||||
} else {
|
||||
$migrations->from_file('utilities/migrations/sqlite.sql')->migrate(3);
|
||||
$migrations->from_file('utilities/migrations/sqlite.sql')->migrate($migrations->latest);
|
||||
}
|
||||
|
||||
# Check if passwd column is missing
|
||||
|
@ -58,13 +58,15 @@ sub register {
|
|||
$app->dbi->db->query('ALTER TABLE files ADD COLUMN passwd TEXT') unless $pwd_col;
|
||||
}
|
||||
|
||||
$app->helper(provisioning => \&_provisioning);
|
||||
$app->helper(get_empty => \&_get_empty);
|
||||
$app->helper(ip => \&_ip);
|
||||
$app->helper(default_delay => \&_default_delay);
|
||||
$app->helper(max_delay => \&_max_delay);
|
||||
$app->helper(is_selected => \&_is_selected);
|
||||
$app->helper(stop_upload => \&_stop_upload);
|
||||
$app->helper(provisioning => \&_provisioning);
|
||||
$app->helper(get_empty => \&_get_empty);
|
||||
$app->helper(ip => \&_ip);
|
||||
$app->helper(default_delay => \&_default_delay);
|
||||
$app->helper(max_delay => \&_max_delay);
|
||||
$app->helper(is_selected => \&_is_selected);
|
||||
$app->helper(stop_upload => \&_stop_upload);
|
||||
$app->helper(create_invitation_token => \&_create_invitation_token);
|
||||
$app->helper(is_guest => \&_is_guest);
|
||||
}
|
||||
|
||||
sub _pg {
|
||||
|
@ -170,4 +172,19 @@ sub _stop_upload {
|
|||
return 0;
|
||||
}
|
||||
|
||||
sub _create_invitation_token {
|
||||
my $c = shift;
|
||||
|
||||
return $c->shortener(32);
|
||||
}
|
||||
|
||||
sub _is_guest {
|
||||
my $c = shift;
|
||||
my $token = shift;
|
||||
|
||||
my $invitation = Lufi::DB::Invitation->new(app => $c->app)->from_token($token);
|
||||
return $invitation if ($invitation && $invitation->is_valid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -18,67 +18,67 @@
|
|||
clients => 1,
|
||||
},
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# you can put some HTML in it
|
||||
# Put a way to contact you here and uncomment it
|
||||
# You can put some HTML in it
|
||||
# MANDATORY
|
||||
#contact => '<a href="https://contact.example.com">Contact page</a>',
|
||||
|
||||
# put an URL or an email address to receive file reports and uncomment it
|
||||
# it's for make reporting illegal files easy for users
|
||||
# Put an URL or an email address to receive file reports and uncomment it
|
||||
# It's for make reporting illegal files easy for users
|
||||
# MANDATORY
|
||||
#report => 'report@example.com',
|
||||
|
||||
# array of random strings used to encrypt cookies
|
||||
# Array of random strings used to encrypt cookies
|
||||
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
||||
#secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
# Choose a theme. See the available themes in `themes` directory
|
||||
# Optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the random URL
|
||||
# Length of the random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# How many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# Max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# length of the modify/delete token
|
||||
# Length of the modify/delete token
|
||||
# optional, default is 32
|
||||
#token_length => 32,
|
||||
|
||||
# max file size, in octets
|
||||
# you can write it 100*1024*1024
|
||||
# Max file size, in octets
|
||||
# You can write it 100*1024*1024
|
||||
# optional, no default
|
||||
#max_file_size => 104857600,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# If you want to have piwik statistics, provide a piwik image tracker
|
||||
# Only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# broadcast_message which will displayed on the index page
|
||||
# Broadcast_message which will displayed on the index page
|
||||
# optional, no default
|
||||
#broadcast_message => 'Maintenance',
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# Default time limit for files
|
||||
# Valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
#default_delay => 0,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# Number of days after which the files will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# A warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
#max_delay => 0,
|
||||
|
||||
# size thresholds: if you want to define max delays for different sizes of file
|
||||
# the keys are size in Bytes, you can't have 10*1000*10000 as key
|
||||
# if a file is smaller than the smallest configured size, it will have a expiration delay of max_delay (see above)
|
||||
# Size thresholds: if you want to define max delays for different sizes of file
|
||||
# The keys are size in Bytes, you can't have 10*1000*10000 as key
|
||||
# If a file is smaller than the smallest configured size, it will have a expiration delay of max_delay (see above)
|
||||
# optional, default is using max_delay (see above) for all sizes
|
||||
#delay_for_size => {
|
||||
# 10000000 => 90, # between 10MB and 50MB => max is 90 days, less than 10MB => max is max_delay (see above)
|
||||
|
@ -92,18 +92,50 @@
|
|||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# Array of authorized domains for API calls.
|
||||
# If you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# if set, the shortened URLs will use this domain
|
||||
# If set, the shortened URLs will use this domain
|
||||
# optional
|
||||
#fixed_domain => 'example.org',
|
||||
|
||||
# Define a path to the upload directory, where the uploaded files will be stored
|
||||
# You can define it relative to lufi directory or set an absolute path
|
||||
# Remember that it has to be in a directory writable by Lufi user
|
||||
# DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
|
||||
# optional, default is 'files'
|
||||
#upload_dir => 'files',
|
||||
|
||||
# Allow to add a password on files, asked before allowing to download files
|
||||
# optional, default is 0
|
||||
#allow_pwd_on_files => 0,
|
||||
|
||||
# Force all files to be in "Burn after reading mode"
|
||||
# optional, default is 0
|
||||
#force_burn_after_reading => 0,
|
||||
|
||||
# If set, the files' URLs will always use this domain
|
||||
# optional, no default
|
||||
#fixed_domain => 'example.org',
|
||||
|
||||
# Abuse reasons
|
||||
# Set an integer in the abuse field of a file in the database and it will not be downloadable anymore
|
||||
# The reason will be displayed to the downloader, according to the reasons you will configure here.
|
||||
# optional, no default
|
||||
#abuse => {
|
||||
# 0 => 'Copyright infringment',
|
||||
# 1 => 'Illegal content',
|
||||
#},
|
||||
|
||||
###############
|
||||
# Mail settings
|
||||
###############
|
||||
|
||||
# Mail configuration
|
||||
# See https://metacpan.org/pod/Mojolicious::Plugin::Mail#EXAMPLES
|
||||
# Optional, default to sendmail method with no arguments
|
||||
# optional, default to sendmail method with no arguments
|
||||
#mail => {
|
||||
# # Valid values are 'sendmail' and 'smtp'
|
||||
# how => 'smtp',
|
||||
|
@ -111,23 +143,27 @@
|
|||
#},
|
||||
|
||||
# Email sender address
|
||||
# Optional, default to no-reply@lufi.io
|
||||
# optional, default to no-reply@lufi.io
|
||||
#mail_sender => 'no-reply@lufi.io',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite, postgresql and mysql (all lowercase)
|
||||
#############
|
||||
# DB settings
|
||||
#############
|
||||
|
||||
# Choose what database you want to use
|
||||
# Valid choices are sqlite, postgresql and mysql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
#dbtype => 'sqlite',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lufi directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lufi user
|
||||
# Define a path to the SQLite database
|
||||
# You can define it relative to lufi directory or set an absolute path
|
||||
# Remember that it has to be in a directory writable by Lufi user
|
||||
# optional, default is lufi.db
|
||||
#db_path => 'lufi.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# These are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
#pgdb => {
|
||||
# database => 'lufi',
|
||||
|
@ -142,7 +178,7 @@
|
|||
#},
|
||||
|
||||
# MySQL ONLY - only used if dbtype is set to mysql
|
||||
# these are the credentials to access the MySQL database
|
||||
# These are the credentials to access the MySQL database
|
||||
# mandatory if you choosed mysql as dbtype
|
||||
#mysqldb => {
|
||||
# database => 'lufi',
|
||||
|
@ -156,15 +192,12 @@
|
|||
# #max_connections => 5,
|
||||
#},
|
||||
|
||||
# define a path to the upload directory, where the uploaded files will be stored
|
||||
# you can define it relative to lufi directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lufi user
|
||||
# DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
|
||||
# optional, default is 'files'
|
||||
#upload_dir => 'files',
|
||||
#############################################
|
||||
# LDAP settings (authentication and features)
|
||||
#############################################
|
||||
|
||||
# set `ldap` if you want that only authenticated users can upload files
|
||||
# please note that everybody can still download 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', # server URI
|
||||
|
@ -181,47 +214,70 @@
|
|||
# }
|
||||
#},
|
||||
|
||||
# if you use `ldap` for authentication, you can map some attributes from LDAP to be able to access them in Lufi
|
||||
# those attributes will be accessible with:
|
||||
# If you've set ldap above, the session will last `session_duration` seconds before
|
||||
# the user needs to reauthenticate
|
||||
# optional, default is 3600
|
||||
#session_duration => 3600,
|
||||
|
||||
# If you use `ldap` for authentication, you can map some attributes from LDAP to be able to access them in Lufi
|
||||
# Those attributes will be accessible with:
|
||||
# $c->current_user->{lufi_attribute_name} in Lufi backend files (all that is in `lib` directory)
|
||||
# <%= $self->current_user->{lufi_attribute_name} %> in templates files (in `themes` directory)
|
||||
#
|
||||
# define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
||||
# note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
||||
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
||||
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
||||
# optional, no default
|
||||
#ldap_map_attr => {
|
||||
# displayname => 'cn',
|
||||
# mail => 'mail'
|
||||
#},
|
||||
|
||||
# set `htpasswd` if you want to use an htpasswd file instead of ldap
|
||||
# see 'man htpasswd' to know how to create such file
|
||||
# When using LDAP authentication, LDAP users can invite people (by mail) to use Lufi to send them files without
|
||||
# being authenticated.
|
||||
# This is where you configure the behavior of the invitations.
|
||||
# You may need to fetch some attributes from LDAP to use some invitations settings. See `ldap_map_attr` above.
|
||||
# optional, no default
|
||||
#invitations => {
|
||||
# # The name of the key set in `ldap_map_attr` (above) that corresponds to the mail of the LDAP user
|
||||
# # optional, default is `mail`
|
||||
# mail_attr => 'mail',
|
||||
# # The `From` header of invitation mail can be the mail of the LDAP user
|
||||
# # Be sure to have a mail system that will correctly send the mail from your users! (DKIM, SPF…)
|
||||
# # To enable this feature, set it to 1
|
||||
# # optional, disabled by default
|
||||
# send_invitation_with_ldap_user_mail => 1,
|
||||
# # The user is able to set an expiration delay for the invitation.
|
||||
# # This expiration delay can’t be more than this setting (in days).
|
||||
# # optional, default is 30 days
|
||||
# max_invitation_expiration_delay => 30,
|
||||
# # Once the guest has submitted his files, he has an additional period of time to submit forgotten files.
|
||||
# # You can set that additional period of time in minutes here.
|
||||
# # To disable that feature, set it to 0 or less
|
||||
# # optional, default is 10 minutes
|
||||
# max_additional_period => 10,
|
||||
# # Lufi follows privacy-by-design, so, by default, no files URLs (with the decode secret) are stored in database.
|
||||
# # However, the concern is different for this case. Storing files URLs makes users able to retrieve the guests’ sent files
|
||||
# # from their `invitations` page.
|
||||
# # Set to 1 to store guests’ files URLs in database
|
||||
# # optional, default is 0 (disabled)
|
||||
# save_files_url_in_db => 0,
|
||||
# # Users can resend the invitation to their guest. This does not extend the invitation’s expiration delay unless you
|
||||
# # set this option to 1.
|
||||
# # optional, default is 0 (disabled)
|
||||
# extend_invitation_expiration_on_resend => 0,
|
||||
#},
|
||||
|
||||
#########################
|
||||
# Htpasswd authentication
|
||||
#########################
|
||||
|
||||
# Set `htpasswd` if you want to use an htpasswd file instead of ldap
|
||||
# See 'man htpasswd' to know how to create such file
|
||||
#htpasswd => 'lufi.passwd',
|
||||
|
||||
# if you've set ldap above, the session will last `session_duration` seconds before
|
||||
# the user needs to reauthenticate
|
||||
# optional, default is 3600
|
||||
#session_duration => 3600,
|
||||
|
||||
# allow to add a password on files, asked before allowing to download files
|
||||
# optional, default is 0
|
||||
#allow_pwd_on_files => 0,
|
||||
|
||||
# force all files to be in "Burn after reading mode"
|
||||
# optional, default is 0
|
||||
#force_burn_after_reading => 0,
|
||||
|
||||
# if set, the files' URLs will always use this domain
|
||||
# optional, no default
|
||||
#fixed_domain => 'example.org',
|
||||
|
||||
# abuse reasons
|
||||
# set an integer in the abuse field of a file in the database and it will not be downloadable anymore
|
||||
# the reason will be displayed to the downloader, according to the reasons you will configure here.
|
||||
# optional, no default
|
||||
#abuse => {
|
||||
# 0 => 'Copyright infringment',
|
||||
# 1 => 'Illegal content',
|
||||
#},
|
||||
#######################
|
||||
# HTTP Headers settings
|
||||
#######################
|
||||
|
||||
# Content-Security-Policy header that will be sent by Lufi
|
||||
# Set to '' to disable CSP header
|
||||
|
@ -255,24 +311,24 @@
|
|||
# Lufi cron jobs settings
|
||||
#########################
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lufi cron cleanbdd)
|
||||
# Number of days senders' IP addresses are kept in database
|
||||
# After that delay, they will be deleted from database (used with script/lufi cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lufi cron watch to trigger an action
|
||||
# Max size of the files directory, in octets
|
||||
# Used by script/lufi cron watch to trigger an action
|
||||
# optional, no default
|
||||
#max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lufi cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# Default action when files directory is over max_total_size (used with script/lufi cron watch)
|
||||
# Valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# Please, see README.md
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# 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
|
||||
# Files 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,
|
||||
};
|
||||
|
|
203
t/mysql.conf
203
t/mysql.conf
|
@ -6,6 +6,7 @@
|
|||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
# you can specify a unix socket too, like 'http+unix://%2Ftmp%2Flufi.sock'
|
||||
listen => ['http://127.0.0.1:8081'],
|
||||
# if you use Lufi behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lufi directly, let it commented
|
||||
|
@ -17,67 +18,67 @@
|
|||
clients => 1,
|
||||
},
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# you can put some HTML in it
|
||||
# Put a way to contact you here and uncomment it
|
||||
# You can put some HTML in it
|
||||
# MANDATORY
|
||||
contact => '<a href="https://contact.example.com">Contact page</a>',
|
||||
|
||||
# put an URL or an email address to receive file reports and uncomment it
|
||||
# it's for make reporting illegal files easy for users
|
||||
# Put an URL or an email address to receive file reports and uncomment it
|
||||
# It's for make reporting illegal files easy for users
|
||||
# MANDATORY
|
||||
report => 'report@example.com',
|
||||
|
||||
# array of random strings used to encrypt cookies
|
||||
# Array of random strings used to encrypt cookies
|
||||
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
||||
#secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
# Choose a theme. See the available themes in `themes` directory
|
||||
# Optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the random URL
|
||||
# Length of the random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# How many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# Max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# length of the modify/delete token
|
||||
# Length of the modify/delete token
|
||||
# optional, default is 32
|
||||
#token_length => 32,
|
||||
|
||||
# max file size, in octets
|
||||
# you can write it 100*1024*1024
|
||||
# Max file size, in octets
|
||||
# You can write it 100*1024*1024
|
||||
# optional, no default
|
||||
#max_file_size => 104857600,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# If you want to have piwik statistics, provide a piwik image tracker
|
||||
# Only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# broadcast_message which will displayed on the index page
|
||||
# Broadcast_message which will displayed on the index page
|
||||
# optional, no default
|
||||
#broadcast_message => 'Maintenance',
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# Default time limit for files
|
||||
# Valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
#default_delay => 0,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# Number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# A warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
#max_delay => 0,
|
||||
|
||||
# size thresholds: if you want to define max delays for different sizes of file
|
||||
# the keys are size in Bytes, you can't have 10*1000*10000 as key
|
||||
# if a file is smaller than the smallest configured size, it will have a expiration delay of max_delay (see above)
|
||||
# Size thresholds: if you want to define max delays for different sizes of file
|
||||
# The keys are size in Bytes, you can't have 10*1000*10000 as key
|
||||
# If a file is smaller than the smallest configured size, it will have a expiration delay of max_delay (see above)
|
||||
# optional, default is using max_delay (see above) for all sizes
|
||||
#delay_for_size => {
|
||||
# 10000000 => 90, # between 10MB and 50MB => max is 90 days, less than 10MB => max is max_delay (see above)
|
||||
|
@ -91,18 +92,54 @@
|
|||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# Array of authorized domains for API calls.
|
||||
# If you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# if set, the shortened URLs will use this domain
|
||||
# If set, the shortened URLs will use this domain
|
||||
# optional
|
||||
#fixed_domain => 'example.org',
|
||||
|
||||
# Define a path to the upload directory, where the uploaded files will be stored
|
||||
# You can define it relative to lufi directory or set an absolute path
|
||||
# Remember that it has to be in a directory writable by Lufi user
|
||||
# DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
|
||||
# optional, default is 'files'
|
||||
#upload_dir => 'files',
|
||||
|
||||
# Allow to add a password on files, asked before allowing to download files
|
||||
# optional, default is 0
|
||||
allow_pwd_on_files => 1,
|
||||
|
||||
# Force all files to be in "Burn after reading mode"
|
||||
# optional, default is 0
|
||||
#force_burn_after_reading => 0,
|
||||
|
||||
# If set, the files' URLs will always use this domain
|
||||
# optional, no default
|
||||
#fixed_domain => 'example.org',
|
||||
|
||||
# Abuse reasons
|
||||
# Set an integer in the abuse field of a file in the database and it will not be downloadable anymore
|
||||
# The reason will be displayed to the downloader, according to the reasons you will configure here.
|
||||
# optional, no default
|
||||
#abuse => {
|
||||
# 0 => 'Copyright infringment',
|
||||
# 1 => 'Illegal content',
|
||||
#},
|
||||
abuse => {
|
||||
0 => 'Copyright infringment',
|
||||
1 => 'Illegal content',
|
||||
},
|
||||
|
||||
###############
|
||||
# Mail settings
|
||||
###############
|
||||
|
||||
# Mail configuration
|
||||
# See https://metacpan.org/pod/Mojolicious::Plugin::Mail#EXAMPLES
|
||||
# Optional, default to sendmail method with no arguments
|
||||
# optional, default to sendmail method with no arguments
|
||||
#mail => {
|
||||
# # Valid values are 'sendmail' and 'smtp'
|
||||
# how => 'smtp',
|
||||
|
@ -110,23 +147,28 @@
|
|||
#},
|
||||
|
||||
# Email sender address
|
||||
# Optional, default to no-reply@lufi.io
|
||||
# optional, default to no-reply@lufi.io
|
||||
#mail_sender => 'no-reply@lufi.io',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite, postgresql and mysql (all lowercase)
|
||||
#############
|
||||
# DB settings
|
||||
#############
|
||||
|
||||
# Choose what database you want to use
|
||||
# Valid choices are sqlite, postgresql and mysql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
#dbtype => 'sqlite',
|
||||
dbtype => 'mysql',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lufi directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lufi user
|
||||
# Define a path to the SQLite database
|
||||
# You can define it relative to lufi directory or set an absolute path
|
||||
# Remember that it has to be in a directory writable by Lufi user
|
||||
# optional, default is lufi.db
|
||||
#db_path => 'lufi.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# These are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
#pgdb => {
|
||||
# database => 'lufi',
|
||||
|
@ -135,13 +177,25 @@
|
|||
# #port => 5432,
|
||||
# user => 'DBUSER',
|
||||
# pwd => 'DBPASSWORD',
|
||||
# # https://mojolicious.org/perldoc/Mojo/Pg#max_connections
|
||||
# # optional, default is 1
|
||||
# #max_connections => 1,
|
||||
#},
|
||||
|
||||
# MySQL ONLY - only used if dbtype is set to mysql
|
||||
# these are the credentials to access the MySQL database
|
||||
# These are the credentials to access the MySQL database
|
||||
# mandatory if you choosed mysql as dbtype
|
||||
#mysqldb => {
|
||||
# database => 'lufi',
|
||||
# host => 'localhost',
|
||||
# # optional, default is 3306
|
||||
# #port => 3306,
|
||||
# user => 'DBUSER',
|
||||
# pwd => 'DBPASSWORD',
|
||||
# # https://metacpan.org/pod/Mojo::mysql#max_connections
|
||||
# # optional, default is 5 (set to 0 to disable persistent connections)
|
||||
# #max_connections => 5,
|
||||
#},
|
||||
mysqldb => {
|
||||
database => 'lufi_db',
|
||||
host => 'mariadb',
|
||||
|
@ -153,55 +207,50 @@
|
|||
# #max_connections => 5,
|
||||
},
|
||||
|
||||
# define a path to the upload directory, where the uploaded files will be stored
|
||||
# you can define it relative to lufi directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lufi user
|
||||
# DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
|
||||
# optional, default is 'files'
|
||||
#upload_dir => 'files',
|
||||
#############################################
|
||||
# LDAP settings (authentication and features)
|
||||
#############################################
|
||||
|
||||
# set `ldap` if you want that only authenticated users can upload files
|
||||
# please note that everybody can still download 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 => 'ldap://rroemhild-test-openldap', user_tree => 'ou=people,dc=planetexpress,dc=com', bind_dn => 'cn=admin,dc=planetexpress,dc=com', bind_pwd => 'GoodNewsEveryone', user_attr => 'uid', user_filter => '' },
|
||||
|
||||
# set `htpasswd` if you want to use an htpasswd file instead of ldap
|
||||
# see 'man htpasswd' to know how to create such file
|
||||
#htpasswd => 't/lstu.passwd',
|
||||
|
||||
# if you've set ldap above, the session will last `session_duration` seconds before
|
||||
# If you've set ldap above, the session will last `session_duration` seconds before
|
||||
# the user needs to reauthenticate
|
||||
# optional, default is 3600
|
||||
#session_duration => 3600,
|
||||
|
||||
# allow to add a password on files, asked before allowing to download files
|
||||
# optional, default is 0
|
||||
allow_pwd_on_files => 1,
|
||||
# If you use `ldap` for authentication, you can map some attributes from LDAP to be able to access them in Lufi
|
||||
# Those attributes will be accessible with:
|
||||
# $c->current_user->{lufi_attribute_name} in Lufi backend files (all that is in `lib` directory)
|
||||
# <%= $self->current_user->{lufi_attribute_name} %> in templates files (in `themes` directory)
|
||||
#
|
||||
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
||||
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
||||
#ldap_map_attr => {
|
||||
# displayname => 'cn',
|
||||
# mail => 'mail'
|
||||
#},
|
||||
|
||||
# force all files to be in "Burn after reading mode"
|
||||
# optional, default is 0
|
||||
#force_burn_after_reading => 0,
|
||||
#########################
|
||||
# Htpasswd authentication
|
||||
#########################
|
||||
|
||||
# if set, the files' URLs will always use this domain
|
||||
# optional, no default
|
||||
#fixed_domain => 'example.org',
|
||||
# Set `htpasswd` if you want to use an htpasswd file instead of ldap
|
||||
# See 'man htpasswd' to know how to create such file
|
||||
#htpasswd => 't/lstu.passwd',
|
||||
|
||||
# abuse reasons
|
||||
# set an integer in the abuse field of a file in the database and it will not be downloadable anymore
|
||||
# the reason will be displayed to the downloader, according to the reasons you will configure here.
|
||||
# optional, no default
|
||||
abuse => {
|
||||
0 => 'Copyright infringment',
|
||||
1 => 'Illegal content',
|
||||
},
|
||||
#######################
|
||||
# HTTP Headers settings
|
||||
#######################
|
||||
|
||||
# Content-Security-Policy header that will be sent by Lufi
|
||||
# Set to '' to disable CSP header
|
||||
# https://content-security-policy.com/ provides a good documentation about CSP.
|
||||
# https://report-uri.com/home/generate provides a tool to generate a CSP header.
|
||||
# optional, default is "base-uri 'self'; connect-src 'self'; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
# the default value is good for `default` and `milligram` themes
|
||||
#csp => "base-uri 'self'; connect-src 'self'; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
# optional, default is "base-uri 'self'; connect-src 'self' ws://YOUR_HOST; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
#csp => "",
|
||||
|
||||
# X-Frame-Options header that will be sent by Lufi
|
||||
# Valid values are: 'DENY', 'SAMEORIGIN', 'ALLOW-FROM https://example.com/'
|
||||
|
@ -228,24 +277,24 @@
|
|||
# Lufi cron jobs settings
|
||||
#########################
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lufi cron cleanbdd)
|
||||
# Number of days senders' IP addresses are kept in database
|
||||
# After that delay, they will be deleted from database (used with script/lufi cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lufi cron watch to trigger an action
|
||||
# Max size of the files directory, in octets
|
||||
# Used by script/lufi cron watch to trigger an action
|
||||
# optional, no default
|
||||
#max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lufi cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# Default action when files directory is over max_total_size (used with script/lufi cron watch)
|
||||
# Valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# Please, see README.md
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# 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
|
||||
# Files 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,
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
# you can specify a unix socket too, like 'http+unix://%2Ftmp%2Flufi.sock'
|
||||
listen => ['http://127.0.0.1:8081'],
|
||||
# if you use Lufi behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lufi directly, let it commented
|
||||
|
@ -17,67 +18,67 @@
|
|||
clients => 1,
|
||||
},
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# you can put some HTML in it
|
||||
# Put a way to contact you here and uncomment it
|
||||
# You can put some HTML in it
|
||||
# MANDATORY
|
||||
contact => '<a href="https://contact.example.com">Contact page</a>',
|
||||
|
||||
# put an URL or an email address to receive file reports and uncomment it
|
||||
# it's for make reporting illegal files easy for users
|
||||
# Put an URL or an email address to receive file reports and uncomment it
|
||||
# It's for make reporting illegal files easy for users
|
||||
# MANDATORY
|
||||
report => 'report@example.com',
|
||||
|
||||
# array of random strings used to encrypt cookies
|
||||
# Array of random strings used to encrypt cookies
|
||||
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
||||
#secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
# Choose a theme. See the available themes in `themes` directory
|
||||
# Optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the random URL
|
||||
# Length of the random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# How many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# Max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# length of the modify/delete token
|
||||
# Length of the modify/delete token
|
||||
# optional, default is 32
|
||||
#token_length => 32,
|
||||
|
||||
# max file size, in octets
|
||||
# you can write it 100*1024*1024
|
||||
# Max file size, in octets
|
||||
# You can write it 100*1024*1024
|
||||
# optional, no default
|
||||
#max_file_size => 104857600,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# If you want to have piwik statistics, provide a piwik image tracker
|
||||
# Only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# broadcast_message which will displayed on the index page
|
||||
# Broadcast_message which will displayed on the index page
|
||||
# optional, no default
|
||||
#broadcast_message => 'Maintenance',
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# Default time limit for files
|
||||
# Valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
#default_delay => 0,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# Number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# A warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
#max_delay => 0,
|
||||
|
||||
# size thresholds: if you want to define max delays for different sizes of file
|
||||
# the keys are size in Bytes, you can't have 10*1000*10000 as key
|
||||
# if a file is smaller than the smallest configured size, it will have a expiration delay of max_delay (see above)
|
||||
# Size thresholds: if you want to define max delays for different sizes of file
|
||||
# The keys are size in Bytes, you can't have 10*1000*10000 as key
|
||||
# If a file is smaller than the smallest configured size, it will have a expiration delay of max_delay (see above)
|
||||
# optional, default is using max_delay (see above) for all sizes
|
||||
#delay_for_size => {
|
||||
# 10000000 => 90, # between 10MB and 50MB => max is 90 days, less than 10MB => max is max_delay (see above)
|
||||
|
@ -91,18 +92,50 @@
|
|||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# Array of authorized domains for API calls.
|
||||
# If you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# if set, the shortened URLs will use this domain
|
||||
# If set, the shortened URLs will use this domain
|
||||
# optional
|
||||
#fixed_domain => 'example.org',
|
||||
|
||||
# Define a path to the upload directory, where the uploaded files will be stored
|
||||
# You can define it relative to lufi directory or set an absolute path
|
||||
# Remember that it has to be in a directory writable by Lufi user
|
||||
# DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
|
||||
# optional, default is 'files'
|
||||
#upload_dir => 'files',
|
||||
|
||||
# Allow to add a password on files, asked before allowing to download files
|
||||
# optional, default is 0
|
||||
allow_pwd_on_files => 1,
|
||||
|
||||
# Force all files to be in "Burn after reading mode"
|
||||
# optional, default is 0
|
||||
#force_burn_after_reading => 0,
|
||||
|
||||
# If set, the files' URLs will always use this domain
|
||||
# optional, no default
|
||||
#fixed_domain => 'example.org',
|
||||
|
||||
# Abuse reasons
|
||||
# Set an integer in the abuse field of a file in the database and it will not be downloadable anymore
|
||||
# The reason will be displayed to the downloader, according to the reasons you will configure here.
|
||||
# optional, no default
|
||||
abuse => {
|
||||
0 => 'Copyright infringment',
|
||||
1 => 'Illegal content',
|
||||
},
|
||||
|
||||
###############
|
||||
# Mail settings
|
||||
###############
|
||||
|
||||
# Mail configuration
|
||||
# See https://metacpan.org/pod/Mojolicious::Plugin::Mail#EXAMPLES
|
||||
# Optional, default to sendmail method with no arguments
|
||||
# optional, default to sendmail method with no arguments
|
||||
#mail => {
|
||||
# # Valid values are 'sendmail' and 'smtp'
|
||||
# how => 'smtp',
|
||||
|
@ -110,23 +143,27 @@
|
|||
#},
|
||||
|
||||
# Email sender address
|
||||
# Optional, default to no-reply@lufi.io
|
||||
# optional, default to no-reply@lufi.io
|
||||
#mail_sender => 'no-reply@lufi.io',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite, postgresql and mysql (all lowercase)
|
||||
#############
|
||||
# DB settings
|
||||
#############
|
||||
|
||||
# Choose what database you want to use
|
||||
# Valid choices are sqlite, postgresql and mysql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
dbtype => 'postgresql',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lufi directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lufi user
|
||||
# Define a path to the SQLite database
|
||||
# You can define it relative to lufi directory or set an absolute path
|
||||
# Remember that it has to be in a directory writable by Lufi user
|
||||
# optional, default is lufi.db
|
||||
#db_path => 'lufi.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# These are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
pgdb => {
|
||||
database => 'lufi_db',
|
||||
|
@ -140,7 +177,7 @@
|
|||
},
|
||||
|
||||
# MySQL ONLY - only used if dbtype is set to mysql
|
||||
# these are the credentials to access the MySQL database
|
||||
# These are the credentials to access the MySQL database
|
||||
# mandatory if you choosed mysql as dbtype
|
||||
#mysqldb => {
|
||||
# database => 'lufi',
|
||||
|
@ -149,59 +186,55 @@
|
|||
# #port => 3306,
|
||||
# user => 'DBUSER',
|
||||
# pwd => 'DBPASSWORD',
|
||||
# # https://metacpan.org/pod/Mojo::mysql#max_connections
|
||||
# # optional, default is 5 (set to 0 to disable persistent connections)
|
||||
# #max_connections => 5,
|
||||
#},
|
||||
|
||||
# define a path to the upload directory, where the uploaded files will be stored
|
||||
# you can define it relative to lufi directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lufi user
|
||||
# DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
|
||||
# optional, default is 'files'
|
||||
#upload_dir => 'files',
|
||||
#############################################
|
||||
# LDAP settings (authentication and features)
|
||||
#############################################
|
||||
|
||||
# set `ldap` if you want that only authenticated users can upload files
|
||||
# please note that everybody can still download 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 => 'ldap://rroemhild-test-openldap', user_tree => 'ou=people,dc=planetexpress,dc=com', bind_dn => 'cn=admin,dc=planetexpress,dc=com', bind_pwd => 'GoodNewsEveryone', user_attr => 'uid', user_filter => '' },
|
||||
|
||||
# set `htpasswd` if you want to use an htpasswd file instead of ldap
|
||||
# see 'man htpasswd' to know how to create such file
|
||||
#htpasswd => 't/lstu.passwd',
|
||||
|
||||
# if you've set ldap above, the session will last `session_duration` seconds before
|
||||
# If you've set ldap above, the session will last `session_duration` seconds before
|
||||
# the user needs to reauthenticate
|
||||
# optional, default is 3600
|
||||
#session_duration => 3600,
|
||||
|
||||
# allow to add a password on files, asked before allowing to download files
|
||||
# optional, default is 0
|
||||
allow_pwd_on_files => 1,
|
||||
# If you use `ldap` for authentication, you can map some attributes from LDAP to be able to access them in Lufi
|
||||
# Those attributes will be accessible with:
|
||||
# $c->current_user->{lufi_attribute_name} in Lufi backend files (all that is in `lib` directory)
|
||||
# <%= $self->current_user->{lufi_attribute_name} %> in templates files (in `themes` directory)
|
||||
#
|
||||
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
||||
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
||||
#ldap_map_attr => {
|
||||
# displayname => 'cn',
|
||||
# mail => 'mail'
|
||||
#},
|
||||
|
||||
# force all files to be in "Burn after reading mode"
|
||||
# optional, default is 0
|
||||
#force_burn_after_reading => 0,
|
||||
#########################
|
||||
# Htpasswd authentication
|
||||
#########################
|
||||
|
||||
# if set, the files' URLs will always use this domain
|
||||
# optional, no default
|
||||
#fixed_domain => 'example.org',
|
||||
# Set `htpasswd` if you want to use an htpasswd file instead of ldap
|
||||
# See 'man htpasswd' to know how to create such file
|
||||
#htpasswd => 'lufi.passwd',
|
||||
|
||||
# abuse reasons
|
||||
# set an integer in the abuse field of a file in the database and it will not be downloadable anymore
|
||||
# the reason will be displayed to the downloader, according to the reasons you will configure here.
|
||||
# optional, no default
|
||||
abuse => {
|
||||
0 => 'Copyright infringment',
|
||||
1 => 'Illegal content',
|
||||
},
|
||||
#######################
|
||||
# HTTP Headers settings
|
||||
#######################
|
||||
|
||||
# Content-Security-Policy header that will be sent by Lufi
|
||||
# Set to '' to disable CSP header
|
||||
# https://content-security-policy.com/ provides a good documentation about CSP.
|
||||
# https://report-uri.com/home/generate provides a tool to generate a CSP header.
|
||||
# optional, default is "base-uri 'self'; connect-src 'self'; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
# the default value is good for `default` and `milligram` themes
|
||||
#csp => "base-uri 'self'; connect-src 'self'; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
# optional, default is "base-uri 'self'; connect-src 'self' ws://YOUR_HOST; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
#csp => "",
|
||||
|
||||
# X-Frame-Options header that will be sent by Lufi
|
||||
# Valid values are: 'DENY', 'SAMEORIGIN', 'ALLOW-FROM https://example.com/'
|
||||
|
@ -228,24 +261,24 @@
|
|||
# Lufi cron jobs settings
|
||||
#########################
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lufi cron cleanbdd)
|
||||
# Number of days senders' IP addresses are kept in database
|
||||
# After that delay, they will be deleted from database (used with script/lufi cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lufi cron watch to trigger an action
|
||||
# Max size of the files directory, in octets
|
||||
# Used by script/lufi cron watch to trigger an action
|
||||
# optional, no default
|
||||
#max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lufi cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# Default action when files directory is over max_total_size (used with script/lufi cron watch)
|
||||
# Valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# Please, see README.md
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# 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
|
||||
# Files 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,
|
||||
};
|
||||
|
|
190
t/sqlite.conf
190
t/sqlite.conf
|
@ -6,6 +6,7 @@
|
|||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
# you can specify a unix socket too, like 'http+unix://%2Ftmp%2Flufi.sock'
|
||||
listen => ['http://127.0.0.1:8081'],
|
||||
# if you use Lufi behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lufi directly, let it commented
|
||||
|
@ -17,67 +18,67 @@
|
|||
clients => 1,
|
||||
},
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# you can put some HTML in it
|
||||
# Put a way to contact you here and uncomment it
|
||||
# You can put some HTML in it
|
||||
# MANDATORY
|
||||
contact => '<a href="https://contact.example.com">Contact page</a>',
|
||||
|
||||
# put an URL or an email address to receive file reports and uncomment it
|
||||
# it's for make reporting illegal files easy for users
|
||||
# Put an URL or an email address to receive file reports and uncomment it
|
||||
# It's for make reporting illegal files easy for users
|
||||
# MANDATORY
|
||||
report => 'report@example.com',
|
||||
|
||||
# array of random strings used to encrypt cookies
|
||||
# Array of random strings used to encrypt cookies
|
||||
# optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
|
||||
#secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
# Choose a theme. See the available themes in `themes` directory
|
||||
# Optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the random URL
|
||||
# Length of the random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# How many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# Max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# length of the modify/delete token
|
||||
# Length of the modify/delete token
|
||||
# optional, default is 32
|
||||
#token_length => 32,
|
||||
|
||||
# max file size, in octets
|
||||
# you can write it 100*1024*1024
|
||||
# Max file size, in octets
|
||||
# You can write it 100*1024*1024
|
||||
# optional, no default
|
||||
#max_file_size => 104857600,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# If you want to have piwik statistics, provide a piwik image tracker
|
||||
# Only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# broadcast_message which will displayed on the index page
|
||||
# Broadcast_message which will displayed on the index page
|
||||
# optional, no default
|
||||
#broadcast_message => 'Maintenance',
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# Default time limit for files
|
||||
# Valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
#default_delay => 0,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# Number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# A warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
#max_delay => 0,
|
||||
|
||||
# size thresholds: if you want to define max delays for different sizes of file
|
||||
# the keys are size in Bytes, you can't have 10*1000*10000 as key
|
||||
# if a file is smaller than the smallest configured size, it will have a expiration delay of max_delay (see above)
|
||||
# Size thresholds: if you want to define max delays for different sizes of file
|
||||
# The keys are size in Bytes, you can't have 10*1000*10000 as key
|
||||
# If a file is smaller than the smallest configured size, it will have a expiration delay of max_delay (see above)
|
||||
# optional, default is using max_delay (see above) for all sizes
|
||||
#delay_for_size => {
|
||||
# 10000000 => 90, # between 10MB and 50MB => max is 90 days, less than 10MB => max is max_delay (see above)
|
||||
|
@ -91,18 +92,54 @@
|
|||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# Array of authorized domains for API calls.
|
||||
# If you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# if set, the shortened URLs will use this domain
|
||||
# If set, the shortened URLs will use this domain
|
||||
# optional
|
||||
#fixed_domain => 'example.org',
|
||||
|
||||
# Define a path to the upload directory, where the uploaded files will be stored
|
||||
# You can define it relative to lufi directory or set an absolute path
|
||||
# Remember that it has to be in a directory writable by Lufi user
|
||||
# DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
|
||||
# optional, default is 'files'
|
||||
#upload_dir => 'files',
|
||||
|
||||
# Allow to add a password on files, asked before allowing to download files
|
||||
# optional, default is 0
|
||||
allow_pwd_on_files => 1,
|
||||
|
||||
# Force all files to be in "Burn after reading mode"
|
||||
# optional, default is 0
|
||||
#force_burn_after_reading => 0,
|
||||
|
||||
# If set, the files' URLs will always use this domain
|
||||
# optional, no default
|
||||
#fixed_domain => 'example.org',
|
||||
|
||||
# Abuse reasons
|
||||
# Set an integer in the abuse field of a file in the database and it will not be downloadable anymore
|
||||
# The reason will be displayed to the downloader, according to the reasons you will configure here.
|
||||
# optional, no default
|
||||
#abuse => {
|
||||
# 0 => 'Copyright infringment',
|
||||
# 1 => 'Illegal content',
|
||||
#},
|
||||
abuse => {
|
||||
0 => 'Copyright infringment',
|
||||
1 => 'Illegal content',
|
||||
},
|
||||
|
||||
###############
|
||||
# Mail settings
|
||||
###############
|
||||
|
||||
# Mail configuration
|
||||
# See https://metacpan.org/pod/Mojolicious::Plugin::Mail#EXAMPLES
|
||||
# Optional, default to sendmail method with no arguments
|
||||
# optional, default to sendmail method with no arguments
|
||||
#mail => {
|
||||
# # Valid values are 'sendmail' and 'smtp'
|
||||
# how => 'smtp',
|
||||
|
@ -110,23 +147,27 @@
|
|||
#},
|
||||
|
||||
# Email sender address
|
||||
# Optional, default to no-reply@lufi.io
|
||||
# optional, default to no-reply@lufi.io
|
||||
#mail_sender => 'no-reply@lufi.io',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite, postgresql and mysql (all lowercase)
|
||||
#############
|
||||
# DB settings
|
||||
#############
|
||||
|
||||
# Choose what database you want to use
|
||||
# Valid choices are sqlite, postgresql and mysql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
#dbtype => 'sqlite',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lufi directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lufi user
|
||||
# Define a path to the SQLite database
|
||||
# You can define it relative to lufi directory or set an absolute path
|
||||
# Remember that it has to be in a directory writable by Lufi user
|
||||
# optional, default is lufi.db
|
||||
db_path => 'sqlite.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# These are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
#pgdb => {
|
||||
# database => 'lufi',
|
||||
|
@ -141,7 +182,7 @@
|
|||
#},
|
||||
|
||||
# MySQL ONLY - only used if dbtype is set to mysql
|
||||
# these are the credentials to access the MySQL database
|
||||
# These are the credentials to access the MySQL database
|
||||
# mandatory if you choosed mysql as dbtype
|
||||
#mysqldb => {
|
||||
# database => 'lufi',
|
||||
|
@ -155,55 +196,50 @@
|
|||
# #max_connections => 5,
|
||||
#},
|
||||
|
||||
# define a path to the upload directory, where the uploaded files will be stored
|
||||
# you can define it relative to lufi directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lufi user
|
||||
# DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
|
||||
# optional, default is 'files'
|
||||
#upload_dir => 'files',
|
||||
#############################################
|
||||
# LDAP settings (authentication and features)
|
||||
#############################################
|
||||
|
||||
# set `ldap` if you want that only authenticated users can upload files
|
||||
# please note that everybody can still download 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 => 'ldap://rroemhild-test-openldap', user_tree => 'ou=people,dc=planetexpress,dc=com', bind_dn => 'cn=admin,dc=planetexpress,dc=com', bind_pwd => 'GoodNewsEveryone', user_attr => 'uid', user_filter => '' },
|
||||
|
||||
# set `htpasswd` if you want to use an htpasswd file instead of ldap
|
||||
# see 'man htpasswd' to know how to create such file
|
||||
#htpasswd => 't/lstu.passwd',
|
||||
|
||||
# if you've set ldap above, the session will last `session_duration` seconds before
|
||||
# If you've set ldap above, the session will last `session_duration` seconds before
|
||||
# the user needs to reauthenticate
|
||||
# optional, default is 3600
|
||||
#session_duration => 3600,
|
||||
|
||||
# allow to add a password on files, asked before allowing to download files
|
||||
# optional, default is 0
|
||||
allow_pwd_on_files => 1,
|
||||
# If you use `ldap` for authentication, you can map some attributes from LDAP to be able to access them in Lufi
|
||||
# Those attributes will be accessible with:
|
||||
# $c->current_user->{lufi_attribute_name} in Lufi backend files (all that is in `lib` directory)
|
||||
# <%= $self->current_user->{lufi_attribute_name} %> in templates files (in `themes` directory)
|
||||
#
|
||||
# Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
|
||||
# Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
|
||||
#ldap_map_attr => {
|
||||
# displayname => 'cn',
|
||||
# mail => 'mail'
|
||||
#},
|
||||
|
||||
# force all files to be in "Burn after reading mode"
|
||||
# optional, default is 0
|
||||
#force_burn_after_reading => 0,
|
||||
#########################
|
||||
# Htpasswd authentication
|
||||
#########################
|
||||
|
||||
# if set, the files' URLs will always use this domain
|
||||
# optional, no default
|
||||
#fixed_domain => 'example.org',
|
||||
# Set `htpasswd` if you want to use an htpasswd file instead of ldap
|
||||
# See 'man htpasswd' to know how to create such file
|
||||
#htpasswd => 't/lstu.passwd',
|
||||
|
||||
# abuse reasons
|
||||
# set an integer in the abuse field of a file in the database and it will not be downloadable anymore
|
||||
# the reason will be displayed to the downloader, according to the reasons you will configure here.
|
||||
# optional, no default
|
||||
abuse => {
|
||||
0 => 'Copyright infringment',
|
||||
1 => 'Illegal content',
|
||||
},
|
||||
#######################
|
||||
# HTTP Headers settings
|
||||
#######################
|
||||
|
||||
# Content-Security-Policy header that will be sent by Lufi
|
||||
# Set to '' to disable CSP header
|
||||
# https://content-security-policy.com/ provides a good documentation about CSP.
|
||||
# https://report-uri.com/home/generate provides a tool to generate a CSP header.
|
||||
# optional, default is "base-uri 'self'; connect-src 'self'; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
# the default value is good for `default` and `milligram` themes
|
||||
#csp => "base-uri 'self'; connect-src 'self'; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
# optional, default is "base-uri 'self'; connect-src 'self' ws://YOUR_HOST; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
#csp => "",
|
||||
|
||||
# X-Frame-Options header that will be sent by Lufi
|
||||
# Valid values are: 'DENY', 'SAMEORIGIN', 'ALLOW-FROM https://example.com/'
|
||||
|
@ -230,24 +266,24 @@
|
|||
# Lufi cron jobs settings
|
||||
#########################
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lufi cron cleanbdd)
|
||||
# Number of days senders' IP addresses are kept in database
|
||||
# After that delay, they will be deleted from database (used with script/lufi cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lufi cron watch to trigger an action
|
||||
# Max size of the files directory, in octets
|
||||
# Used by script/lufi cron watch to trigger an action
|
||||
# optional, no default
|
||||
#max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lufi cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# Default action when files directory is over max_total_size (used with script/lufi cron watch)
|
||||
# Valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# Please, see README.md
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# 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
|
||||
# Files 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,
|
||||
};
|
||||
|
|
|
@ -17,11 +17,35 @@ msgstr ""
|
|||
|
||||
#. ($delay)
|
||||
#. (max_delay)
|
||||
#: themes/default/templates/index.html.ep:47 themes/default/templates/index.html.ep:56 themes/default/templates/index.html.ep:57
|
||||
#: themes/default/templates/index.html.ep:56 themes/default/templates/index.html.ep:65 themes/default/templates/index.html.ep:66
|
||||
msgid "%1 days"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:26
|
||||
#. (stash('invitation')
|
||||
#: themes/default/templates/invitations/notification_files_sent.mail.ep:4
|
||||
msgid "%1 have send you files"
|
||||
msgstr ""
|
||||
|
||||
#. (stash('ldap_user')
|
||||
#: themes/default/templates/invitations/invite.mail.ep:2
|
||||
msgid "%1 invites you to send him/her files"
|
||||
msgstr ""
|
||||
|
||||
#. (stash('ldap_user')
|
||||
#: themes/default/templates/invitations/invite.mail.ep:6
|
||||
msgid "%1 invites you to send him/her files through Lufi."
|
||||
msgstr ""
|
||||
|
||||
#. (stash('invitation')
|
||||
#: themes/default/templates/invitations/notification_files_sent.mail.ep:8
|
||||
msgid "%1 used your invitation to send you files:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Invitation.pm:159 lib/Lufi/Controller/Invitation.pm:84 themes/default/templates/invitations/my_invitations.html.ep:51 themes/default/templates/invitations/my_invitations.html.ep:52 themes/default/templates/invitations/my_invitations.html.ep:53 themes/default/templates/invitations/notification_files_sent.mail.ep:12
|
||||
msgid "%A %d %B %Y at %T"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:27
|
||||
msgid "(max size: XXX)"
|
||||
msgstr ""
|
||||
|
||||
|
@ -29,7 +53,7 @@ msgstr ""
|
|||
msgid "1 year"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:4 themes/default/templates/index.html.ep:56
|
||||
#: themes/default/templates/index.html.ep:4 themes/default/templates/index.html.ep:65
|
||||
msgid "24 hours"
|
||||
msgstr ""
|
||||
|
||||
|
@ -41,11 +65,11 @@ msgstr ""
|
|||
msgid "Abort"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:49 themes/default/templates/layouts/default.html.ep:78
|
||||
#: themes/default/templates/layouts/default.html.ep:53 themes/default/templates/layouts/default.html.ep:86
|
||||
msgid "About"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:98
|
||||
#: themes/default/templates/index.html.ep:107
|
||||
msgid "Add a password to file(s)"
|
||||
msgstr ""
|
||||
|
||||
|
@ -53,6 +77,14 @@ msgstr ""
|
|||
msgid "Adding URLs not related to this Lufi instance to the mail body or subject is prohibited."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/invitations.js.ep:3
|
||||
msgid "Are you sure you want to delete the selected invitations?"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/invitations.js.ep:4
|
||||
msgid "Are you sure you want to resend the invitation mail for the selected invitations?"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:17
|
||||
msgid "As Lufi is a free software licensed under of the terms of the <a href=\"https://gnu.org/licenses/agpl.html\" class=\"classic\">AGPLv3</a>, you can install it on you own server. Have a look on the <a href=\"https://framagit.org/luc/lufi/wikis/home\" class=\"classic\">Wiki</a> for the procedure."
|
||||
msgstr ""
|
||||
|
@ -70,7 +102,7 @@ msgstr ""
|
|||
msgid "Bad CSRF token!"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Auth.pm:22 lib/Lufi/Controller/Auth.pm:39
|
||||
#: lib/Lufi/Controller/Auth.pm:27 lib/Lufi/Controller/Auth.pm:49
|
||||
msgid "Bad CSRF token."
|
||||
msgstr ""
|
||||
|
||||
|
@ -78,11 +110,15 @@ msgstr ""
|
|||
msgid "Click here to refresh the page and restart the download."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:119
|
||||
#: themes/default/templates/invitations/invite.mail.ep:8
|
||||
msgid "Click on the following URL to upload files on Lufi:"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:125
|
||||
msgid "Click to open the file browser"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/delays.html.ep:38
|
||||
#: themes/default/templates/delays.html.ep:38 themes/default/templates/invitations/my_invitations.html.ep:80
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
|
@ -90,27 +126,27 @@ msgstr ""
|
|||
msgid "Comma-separated email addresses"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:133
|
||||
#: themes/default/templates/index.html.ep:139
|
||||
msgid "Compressing zip file…"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:14
|
||||
#: themes/default/templates/partial/index.js.ep:15
|
||||
msgid "Copy all links to clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:17
|
||||
#: themes/default/templates/partial/index.js.ep:18
|
||||
msgid "Copy to clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:485
|
||||
#: lib/Lufi/Controller/Files.pm:507
|
||||
msgid "Could not delete the file. You are not authenticated."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:467
|
||||
#: lib/Lufi/Controller/Files.pm:489
|
||||
msgid "Could not find the file. Are you sure of the URL and the token?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:378
|
||||
#: lib/Lufi/Controller/Files.pm:400
|
||||
msgid "Could not find the file. Are you sure of the URL?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -118,11 +154,19 @@ msgstr ""
|
|||
msgid "Counter"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:91
|
||||
#: themes/default/templates/index.html.ep:100
|
||||
msgid "Create a zip archive with the files before uploading?"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/files.html.ep:29 themes/default/templates/index.html.ep:81
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:26
|
||||
msgid "Created at"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:14
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/files.html.ep:29 themes/default/templates/index.html.ep:90
|
||||
msgid "Delete at first download?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -130,7 +174,7 @@ msgstr ""
|
|||
msgid "Delete selected files"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/files.html.ep:32 themes/default/templates/partial/index.js.ep:18
|
||||
#: themes/default/templates/files.html.ep:32 themes/default/templates/partial/index.js.ep:19
|
||||
msgid "Deletion link"
|
||||
msgstr ""
|
||||
|
||||
|
@ -138,7 +182,7 @@ msgstr ""
|
|||
msgid "Don't worry: if a user begins to download the file before the expiration and the download ends after the expiration, he will be able to get the file."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:20 themes/default/templates/render.html.ep:28
|
||||
#: themes/default/templates/partial/index.js.ep:21 themes/default/templates/render.html.ep:28
|
||||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
|
@ -146,7 +190,7 @@ msgstr ""
|
|||
msgid "Download aborted."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/files.html.ep:27 themes/default/templates/partial/index.js.ep:19
|
||||
#: themes/default/templates/files.html.ep:27 themes/default/templates/partial/index.js.ep:20
|
||||
msgid "Download link"
|
||||
msgstr ""
|
||||
|
||||
|
@ -154,10 +198,14 @@ msgstr ""
|
|||
msgid "Drag and drop files in the appropriate area or use the traditional way to send files and the files will be chunked, encrypted and sent to the server. You will get two links per file: a download link, that you give to the people you want to share the file with and a deletion link, allowing you to delete the file whenever you want."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:115
|
||||
#: themes/default/templates/index.html.ep:121
|
||||
msgid "Drop files here"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/invite.html.ep:40
|
||||
msgid "Email address of your guest"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/mail.html.ep:39
|
||||
msgid "Email body"
|
||||
msgstr ""
|
||||
|
@ -170,26 +218,30 @@ msgstr ""
|
|||
msgid "Emails"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:21
|
||||
#: themes/default/templates/partial/index.js.ep:22
|
||||
msgid "Encrypting part XX1 of XX2"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:267
|
||||
#: lib/Lufi/Controller/Files.pm:289
|
||||
msgid "Error: the file existed but was deleted."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:347
|
||||
#: lib/Lufi/Controller/Files.pm:369
|
||||
msgid "Error: the file has not been sent entirely."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:357
|
||||
#: lib/Lufi/Controller/Files.pm:379
|
||||
msgid "Error: unable to find the file. Are you sure of your URL?"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:22
|
||||
#: themes/default/templates/partial/index.js.ep:23
|
||||
msgid "Expiration:"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:27
|
||||
msgid "Expire at"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/files.html.ep:31
|
||||
msgid "Expires at"
|
||||
msgstr ""
|
||||
|
@ -198,7 +250,7 @@ msgstr ""
|
|||
msgid "Export localStorage data"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:449
|
||||
#: lib/Lufi/Controller/Files.pm:471
|
||||
msgid "File deleted"
|
||||
msgstr ""
|
||||
|
||||
|
@ -206,10 +258,22 @@ msgstr ""
|
|||
msgid "File name"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:71
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:61
|
||||
msgid "Files"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:80
|
||||
msgid "Files deleted at first download"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:28
|
||||
msgid "Files sent at"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/invitations.js.ep:8
|
||||
msgid "Files sent in invitation XX1 by XX2"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/render.js.ep:8
|
||||
msgid "Get the file"
|
||||
msgstr ""
|
||||
|
@ -218,6 +282,19 @@ msgstr ""
|
|||
msgid "Get the source code on <a href=\"https://framagit.org/luc/lufi\" class=\"classic\">the official repository</a> or on its <a href=\"https://github.com/ldidry/lufi\" class=\"classic\">Github mirror</a>"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:24
|
||||
msgid "Guest mail"
|
||||
msgstr ""
|
||||
|
||||
#. (ucfirst(stash('invitation')
|
||||
#: themes/default/templates/invitations/notification_files_sent.mail.ep:6
|
||||
msgid "Hello %1,"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/invite.mail.ep:4
|
||||
msgid "Hello,"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/mail.js.ep:35
|
||||
msgid "Hello,\\n\\nHere's some files I want to share with you:\\n"
|
||||
msgstr ""
|
||||
|
@ -226,11 +303,15 @@ msgstr ""
|
|||
msgid "Here's some files"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:24
|
||||
#: themes/default/templates/partial/invitations.js.ep:7
|
||||
msgid "Hide hidden invitations"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:25
|
||||
msgid "Hit Enter, then Ctrl+C to copy all the download links"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:23
|
||||
#: themes/default/templates/partial/index.js.ep:24
|
||||
msgid "Hit Enter, then Ctrl+C to copy the download link"
|
||||
msgstr ""
|
||||
|
||||
|
@ -238,6 +319,10 @@ msgstr ""
|
|||
msgid "How does it work?"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/invite.html.ep:46
|
||||
msgid "How many days would you like the invitation to be valid?"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:16
|
||||
msgid "How to install the software on my server?"
|
||||
msgstr ""
|
||||
|
@ -258,7 +343,7 @@ msgstr ""
|
|||
msgid "Import localStorage data"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:44
|
||||
#: themes/default/templates/index.html.ep:53
|
||||
msgid "Important: more information on delays"
|
||||
msgstr ""
|
||||
|
||||
|
@ -266,6 +351,24 @@ msgstr ""
|
|||
msgid "Information about delays"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:12
|
||||
msgid "Invert selection"
|
||||
msgstr ""
|
||||
|
||||
#. ($i->guest_mail, $url)
|
||||
#: lib/Lufi/Controller/Invitation.pm:171
|
||||
msgid "Invitation resent to %1.<br> URL: %2"
|
||||
msgstr ""
|
||||
|
||||
#. ($invitation->guest_mail, $url)
|
||||
#: lib/Lufi/Controller/Invitation.pm:87
|
||||
msgid "Invitation sent to %1.<br> URL: %2"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/invite.html.ep:27 themes/default/templates/layouts/default.html.ep:36 themes/default/templates/layouts/default.html.ep:69
|
||||
msgid "Invite a guest"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/render.js.ep:6
|
||||
msgid "It seems that the key in your URL is incorrect. Please, verify your URL."
|
||||
msgstr ""
|
||||
|
@ -274,7 +377,7 @@ msgstr ""
|
|||
msgid "Javascript is disabled. You won't be able to use Lufi."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:40 themes/default/templates/layouts/default.html.ep:42 themes/default/templates/layouts/default.html.ep:69 themes/default/templates/layouts/default.html.ep:71
|
||||
#: themes/default/templates/layouts/default.html.ep:44 themes/default/templates/layouts/default.html.ep:46 themes/default/templates/layouts/default.html.ep:77 themes/default/templates/layouts/default.html.ep:79
|
||||
msgid "Language"
|
||||
msgstr ""
|
||||
|
||||
|
@ -282,7 +385,7 @@ msgstr ""
|
|||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:54 themes/default/templates/layouts/default.html.ep:80
|
||||
#: themes/default/templates/layouts/default.html.ep:58 themes/default/templates/layouts/default.html.ep:91
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
|
@ -294,20 +397,28 @@ msgstr ""
|
|||
msgid "Mail"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/files.html.ep:3 themes/default/templates/layouts/default.html.ep:34 themes/default/templates/layouts/default.html.ep:63
|
||||
#: themes/default/templates/files.html.ep:3 themes/default/templates/layouts/default.html.ep:34 themes/default/templates/layouts/default.html.ep:67
|
||||
msgid "My files"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:106
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:5 themes/default/templates/layouts/default.html.ep:37 themes/default/templates/layouts/default.html.ep:70
|
||||
msgid "My invitations"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/notification_files_sent.mail.ep:17
|
||||
msgid "NB: this list includes the list of files that have already been sent to you."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:115
|
||||
msgid "Name of the zip file"
|
||||
msgstr ""
|
||||
|
||||
#. (format_bytes($json->{size})
|
||||
#: lib/Lufi/Controller/Files.pm:103
|
||||
#: lib/Lufi/Controller/Files.pm:108
|
||||
msgid "No enough space available on the server for this file (size: %1)."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/files.js.ep:10 themes/default/templates/partial/index.js.ep:27
|
||||
#: themes/default/templates/partial/files.js.ep:10 themes/default/templates/partial/index.js.ep:28
|
||||
msgid "No expiration delay"
|
||||
msgstr ""
|
||||
|
||||
|
@ -315,7 +426,7 @@ 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/index.html.ep:97 themes/default/templates/login.html.ep:21 themes/default/templates/render.html.ep:26
|
||||
#: themes/default/templates/index.html.ep:106 themes/default/templates/login.html.ep:21 themes/default/templates/render.html.ep:26
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
|
@ -328,7 +439,7 @@ msgstr ""
|
|||
msgid "Please wait while we are getting your file. We first need to download and decrypt all parts before you can get it."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Auth.pm:28
|
||||
#: lib/Lufi/Controller/Auth.pm:38
|
||||
msgid "Please, check your credentials or your right to access this service: unable to authenticate."
|
||||
msgstr ""
|
||||
|
||||
|
@ -340,18 +451,38 @@ msgstr ""
|
|||
msgid "Purge expired files from localStorage"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:31 themes/default/templates/layouts/default.html.ep:60
|
||||
#: themes/default/templates/invitations/notification_files_sent.mail.ep:20
|
||||
msgid "Regards,"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/invite.mail.ep:15
|
||||
msgid "Regards."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:31 themes/default/templates/layouts/default.html.ep:64
|
||||
msgid "Report file"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:15
|
||||
msgid "Resend invitation mail"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:9
|
||||
msgid "Rows in purple mean that the invitations have expired."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/files.html.ep:9
|
||||
msgid "Rows in red mean that the files have expired and are no longer available."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:25
|
||||
#: themes/default/templates/partial/index.js.ep:26
|
||||
msgid "Send all links by email"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/invite.html.ep:50
|
||||
msgid "Send the invitation"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/mail.html.ep:46
|
||||
msgid "Send with this server"
|
||||
msgstr ""
|
||||
|
@ -360,7 +491,7 @@ msgstr ""
|
|||
msgid "Send with your own mail software"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:28
|
||||
#: themes/default/templates/partial/index.js.ep:29
|
||||
msgid "Sending part XX1 of XX2. Please, be patient, the progress bar can take a while to move."
|
||||
msgstr ""
|
||||
|
||||
|
@ -369,22 +500,44 @@ msgstr ""
|
|||
msgid "Share your files in total privacy on %1"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:13 themes/default/templates/partial/invitations.js.ep:9
|
||||
msgid "Show hidden invitations"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/render.js.ep:11
|
||||
msgid "Show zip content"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:36 themes/default/templates/layouts/default.html.ep:65 themes/default/templates/login.html.ep:27 themes/default/templates/logout.html.ep:17
|
||||
#: themes/default/templates/layouts/default.html.ep:40 themes/default/templates/layouts/default.html.ep:73 themes/default/templates/login.html.ep:28 themes/default/templates/logout.html.ep:17
|
||||
msgid "Signin"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:37
|
||||
#: lib/Lufi/Controller/Invitation.pm:283 themes/default/templates/invitations/exception.html.ep:16
|
||||
msgid "Sorry, the invitation doesn’t exist. Are you sure you are on the right URL?"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:46
|
||||
msgid "Sorry, the uploading is currently disabled. Please try again later."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:77
|
||||
#: lib/Lufi/Controller/Files.pm:82
|
||||
msgid "Sorry, uploading is disabled."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/exception.html.ep:7
|
||||
msgid "Sorry, your invitation has expired or has been deleted."
|
||||
msgstr ""
|
||||
|
||||
#. ($invit->ldap_user_mail)
|
||||
#: lib/Lufi/Controller/Files.pm:122
|
||||
msgid "Sorry, your invitation has expired or has been deleted. Please contact %1 to have another invitation."
|
||||
msgstr ""
|
||||
|
||||
#. ($invitation->ldap_user_mail)
|
||||
#: lib/Lufi/Controller/Invitation.pm:276
|
||||
msgid "The URLs of your files have been sent by email to %1."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:7
|
||||
msgid "The administrator can only see the file's name, its size and its mimetype (what kind of file it is: video, text, etc.)."
|
||||
msgstr ""
|
||||
|
@ -405,7 +558,12 @@ msgstr ""
|
|||
msgid "The email subject can't be empty."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:446
|
||||
#. ($expire_at, $max_expire_at)
|
||||
#: lib/Lufi/Controller/Invitation.pm:51
|
||||
msgid "The expiration delay (%1) is not between 1 and %2 days."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:468
|
||||
msgid "The file has already been deleted"
|
||||
msgstr ""
|
||||
|
||||
|
@ -418,10 +576,40 @@ msgstr ""
|
|||
msgid "The following email addresses are not valid: %1"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:15
|
||||
#. ($guest_mail)
|
||||
#: lib/Lufi/Controller/Invitation.pm:48
|
||||
msgid "The guest email address (%1) is unvalid."
|
||||
msgstr ""
|
||||
|
||||
#. ($i->token, $i->guest_mail)
|
||||
#: lib/Lufi/Controller/Invitation.pm:150
|
||||
msgid "The invitation %1 can’t be resend: %2 has already sent files.<br>Please create a new invitation."
|
||||
msgstr ""
|
||||
|
||||
#. ($i->token)
|
||||
#: lib/Lufi/Controller/Invitation.pm:130
|
||||
msgid "The invitation %1 has been deleted."
|
||||
msgstr ""
|
||||
|
||||
#. (stash('user_mail')
|
||||
#: themes/default/templates/invitations/invite.html.ep:34
|
||||
msgid "The invitation mail will be send from your email address (%1)."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:16
|
||||
msgid "The link(s) has been copied to your clipboard"
|
||||
msgstr ""
|
||||
|
||||
#. (stash('invitation')
|
||||
#: themes/default/templates/index.html.ep:30
|
||||
msgid "The link(s) of your file(s) will automatically be sent by mail to %1 (%2)"
|
||||
msgstr ""
|
||||
|
||||
#. (stash('ldap_user')
|
||||
#: themes/default/templates/invitations/invite.mail.ep:11
|
||||
msgid "The links of your file(s) will automatically be send by mail to %1."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Mail.pm:97
|
||||
msgid "The mail has been sent."
|
||||
msgstr ""
|
||||
|
@ -430,42 +618,59 @@ msgstr ""
|
|||
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:214
|
||||
#: lib/Lufi/Controller/Files.pm:236
|
||||
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:273
|
||||
#: lib/Lufi/Controller/Files.pm:295
|
||||
msgid "This file has been deactivated by the admins. Contact them to know why."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:46 themes/default/templates/partial/invitations.js.ep:6
|
||||
msgid "This invitation is normally hidden"
|
||||
msgstr ""
|
||||
|
||||
#. (stash('expires')
|
||||
#: themes/default/templates/invitations/invite.mail.ep:13
|
||||
msgid "This invitation is valid until %1."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/delays.html.ep:10
|
||||
msgid "This server sets limitations according to the file size. The expiration delay of your file will be the minimum between what you choose and the following limitations:"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:16
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:16
|
||||
msgid "Toggle visibility"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/my_invitations.html.ep:25
|
||||
msgid "URL"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:17
|
||||
msgid "Unable to copy the link(s) to your clipboard"
|
||||
msgstr ""
|
||||
|
||||
#. ($short)
|
||||
#: lib/Lufi/Controller/Files.pm:417
|
||||
#: lib/Lufi/Controller/Files.pm:439
|
||||
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:407
|
||||
#: lib/Lufi/Controller/Files.pm:429
|
||||
msgid "Unable to get counter for %1. The token is invalid."
|
||||
msgstr ""
|
||||
|
||||
#. ($short)
|
||||
#: lib/Lufi/Controller/Files.pm:427
|
||||
#: lib/Lufi/Controller/Files.pm:449
|
||||
msgid "Unable to get counter for %1. You are not authenticated."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:33 themes/default/templates/layouts/default.html.ep:62
|
||||
#: themes/default/templates/layouts/default.html.ep:33 themes/default/templates/layouts/default.html.ep:66
|
||||
msgid "Upload files"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:110
|
||||
#: themes/default/templates/index.html.ep:142
|
||||
msgid "Upload generated zip file"
|
||||
msgstr ""
|
||||
|
||||
|
@ -473,11 +678,11 @@ msgstr ""
|
|||
msgid "Uploaded at"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:142
|
||||
#: themes/default/templates/index.html.ep:151
|
||||
msgid "Uploaded files"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:29
|
||||
#: themes/default/templates/partial/index.js.ep:30
|
||||
msgid "Websocket communication error"
|
||||
msgstr ""
|
||||
|
||||
|
@ -489,6 +694,14 @@ msgstr ""
|
|||
msgid "Who wrote this software?"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:13
|
||||
msgid "XXX file has been added to upload queue."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/invitations/invite.html.ep:30
|
||||
msgid "You can invite someone to send you files through this Lufi instance even if they don’t have an account on it."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:11
|
||||
msgid "You can see the list of your files by clicking on the \"My files\" link at the top right of this page."
|
||||
msgstr ""
|
||||
|
@ -509,7 +722,7 @@ msgstr ""
|
|||
msgid "You have attempted to leave this page. The download will be canceled. Are you sure?"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/index.js.ep:13
|
||||
#: themes/default/templates/partial/index.js.ep:14
|
||||
msgid "You have attempted to leave this page. The upload will be canceled. Are you sure?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -521,16 +734,16 @@ msgstr ""
|
|||
msgid "You must give email addresses."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:29
|
||||
#: themes/default/templates/index.html.ep:38
|
||||
msgid "Your browser has not enough entropy to generate a strong encryption key. Please wait (it's better if you do things on your computer while waiting)."
|
||||
msgstr ""
|
||||
|
||||
#. (format_bytes($json->{size})
|
||||
#: lib/Lufi/Controller/Files.pm:90
|
||||
#: lib/Lufi/Controller/Files.pm:95
|
||||
msgid "Your file is too big: %1 (maximum size allowed: %2)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lufi/Controller/Files.pm:329
|
||||
#: lib/Lufi/Controller/Files.pm:351
|
||||
msgid "Your password is not valid. Please refresh the page to retry."
|
||||
msgstr ""
|
||||
|
||||
|
@ -548,6 +761,10 @@ msgstr ""
|
|||
msgid "deadline: "
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/invitations.js.ep:5
|
||||
msgid "expires on XXX"
|
||||
msgstr ""
|
||||
|
||||
#. (format_bytes($keys[$i])
|
||||
#: themes/default/templates/delays.html.ep:26
|
||||
msgid "for %1 and more, the file will be kept %2 day(s)"
|
||||
|
@ -562,6 +779,11 @@ msgstr ""
|
|||
msgid "no time limit"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:117
|
||||
#: themes/default/templates/index.html.ep:123
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
||||
#. ($e->{name}, format_bytes($e->{size})
|
||||
#: themes/default/templates/invitations/notification_files_sent.mail.ep:12
|
||||
msgid "— %1 (%2), that will expire on %3"
|
||||
msgstr ""
|
||||
|
|
|
@ -203,6 +203,26 @@ button.pulse {
|
|||
transform: scale(1.5);
|
||||
}
|
||||
}
|
||||
.margin-bottom-35 {
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
.toast.teal.accent-3,
|
||||
.toast.red.accent-2 {
|
||||
color: black;
|
||||
}
|
||||
.offscreen {
|
||||
clip-path: inset(100%);
|
||||
clip: rect(1px 1px 1px 1px); /* IE 6/7 */
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
white-space: nowrap; /* added line */
|
||||
width: 1px;
|
||||
}
|
||||
.small-h1 {
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
.white-background {
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
function invertSelection(e) {
|
||||
e.preventDefault();
|
||||
$('#myInvitations input[type="checkbox"]').each(function () {
|
||||
var el = $(this);
|
||||
var tr = el.parent().parent();
|
||||
if (!tr.hasClass('hide')) {
|
||||
el.click();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function toggleHidden(e) {
|
||||
e.preventDefault();
|
||||
if ($('#myInvitations').attr('data-visibility') === 'hidden') {
|
||||
$('#toggleHidden').text(i18n.hideText);
|
||||
$('tr[data-visibility="0"]').removeClass('hide');
|
||||
$('#myInvitations').attr('data-visibility', 'shown');
|
||||
} else {
|
||||
$('#toggleHidden').text(i18n.showText);
|
||||
$('tr[data-visibility="0"]').addClass('hide');
|
||||
$('tr[data-visibility="0"] input[type="checkbox"]').each(function() {
|
||||
var el = $(this);
|
||||
if (el.attr('data-checked') === 'data-checked') {
|
||||
$('tr[data-visibility="0"] input[type="checkbox"]').click();
|
||||
}
|
||||
});
|
||||
$('#myInvitations').attr('data-visibility', 'hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function deleteInvit(e) {
|
||||
e.preventDefault();
|
||||
if (confirm(i18n.confirmDeleteInvit)) {
|
||||
var tokens = selectChecked();
|
||||
$.ajax({
|
||||
url: deleteURL,
|
||||
method: 'POST',
|
||||
data: {
|
||||
tokens: tokens
|
||||
},
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
if (data.success) {
|
||||
data.tokens.forEach(function(t) {
|
||||
Materialize.toast(t.msg, 6000, 'teal accent-3');
|
||||
$('#row-' + t.token).remove();
|
||||
});
|
||||
disableButtons();
|
||||
} else {
|
||||
Materialize.toast(data.msg, 10000, 'red accent-2');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function resendMail(e) {
|
||||
e.preventDefault();
|
||||
if (confirm(i18n.confirmResendMail)) {
|
||||
var tokens = selectChecked();
|
||||
$.ajax({
|
||||
url: resendURL,
|
||||
method: 'POST',
|
||||
data: {
|
||||
tokens: tokens
|
||||
},
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
data.success.forEach(function(s) {
|
||||
Materialize.toast(s.msg, 6000, 'teal accent-3');
|
||||
$('#expire-' + s.token).text(s.expires)
|
||||
$('#' + s.token).click();
|
||||
});
|
||||
data.failures.forEach(function(msg) {
|
||||
Materialize.toast(msg, 10000, 'red accent-2');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function toggleVisibility(e) {
|
||||
e.preventDefault();
|
||||
var tokens = selectChecked();
|
||||
$.ajax({
|
||||
url: toggleURL,
|
||||
method: 'POST',
|
||||
data: {
|
||||
tokens: tokens
|
||||
},
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
if (data.success) {
|
||||
data.tokens.forEach(function(t) {
|
||||
var row = $('#row-' + t.token)
|
||||
if (t.show) {
|
||||
row.attr('data-visibility', 1);
|
||||
row.removeClass('hide');
|
||||
$('#row-' + t.token + ' > td:first i').remove();
|
||||
} else {
|
||||
row.attr('data-visibility', 0);
|
||||
if ($('#myInvitations').attr('data-visibility') === 'hidden') {
|
||||
row.addClass('hide');
|
||||
}
|
||||
$('#row-' + t.token + ' > td:first').append(i18n.hiddenMark);
|
||||
}
|
||||
$('#' + t.token).click();
|
||||
});
|
||||
disableButtons();
|
||||
} else {
|
||||
Materialize.toast(data.msg, 10000, 'red accent-2');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function selectChecked() {
|
||||
var tokens = [];
|
||||
$('#myInvitations input[type="checkbox"][data-checked="data-checked"]').each(function() {
|
||||
tokens.push($(this).attr('id'));
|
||||
});
|
||||
return tokens;
|
||||
}
|
||||
|
||||
function handleCheckboxClic() {
|
||||
var el = $(this);
|
||||
if (el.attr('data-checked') === 'data-checked') {
|
||||
el.attr('data-checked', null);
|
||||
} else {
|
||||
el.attr('data-checked', 'data-checked');
|
||||
}
|
||||
if ($('#myInvitations input[type="checkbox"][data-checked="data-checked"]').length !== 0) {
|
||||
$('#deleteInvit').removeClass('disabled');
|
||||
$('#deleteInvit').attr('disabled', null);
|
||||
$('#resendMail').removeClass('disabled');
|
||||
$('#resendMail').attr('disabled', null);
|
||||
$('#toggleVisibility').removeClass('disabled');
|
||||
$('#toggleVisibility').attr('disabled', null);
|
||||
} else {
|
||||
disableButtons();
|
||||
}
|
||||
}
|
||||
|
||||
function disableButtons() {
|
||||
$('#deleteInvit').addClass('disabled');
|
||||
$('#deleteInvit').attr('disabled', 'disabled');
|
||||
$('#resendMail').addClass('disabled');
|
||||
$('#resendMail').attr('disabled', 'disabled');
|
||||
$('#toggleVisibility').addClass('disabled');
|
||||
$('#toggleVisibility').attr('disabled', 'disabled');
|
||||
}
|
||||
|
||||
function fillModal() {
|
||||
var el = $(this);
|
||||
|
||||
$('#files-info h1').text('');
|
||||
$('#files-ul').html('');
|
||||
|
||||
var token = el.attr('data-token');
|
||||
var guest = el.attr('data-guest');
|
||||
$('#files-info h1').text(
|
||||
i18n.listFiles.replace('XX1', token)
|
||||
.replace('XX2', guest)
|
||||
);
|
||||
|
||||
var files = JSON.parse(el.attr('data-files'));
|
||||
var content = [];
|
||||
for (i = 0; i < files.length; i++) {
|
||||
var f = files[i];
|
||||
var expires = i18n.expiration.replace('XXX',
|
||||
moment.unix(f.delay * 86400 + f.created_at).locale(window.navigator.language).format('LLLL')
|
||||
);
|
||||
content.push(
|
||||
'<li>— ',
|
||||
'<a href="', f.url, '">',
|
||||
f.name,
|
||||
'</a> (',
|
||||
filesize(f.size),
|
||||
', ',
|
||||
expires,
|
||||
')',
|
||||
'</li>',
|
||||
);
|
||||
}
|
||||
$('#files-ul').html(content.join(''));
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$('.modal-trigger').leanModal();
|
||||
$('.modal-trigger').on('click', fillModal);
|
||||
$('#invertSelection').on('click', invertSelection);
|
||||
$('#toggleHidden').on('click', toggleHidden);
|
||||
$('#deleteInvit').on('click', deleteInvit);
|
||||
$('#resendMail').on('click', resendMail);
|
||||
$('#toggleVisibility').on('click', toggleVisibility);
|
||||
$('#myInvitations input[type="checkbox"]').on('click', handleCheckboxClic);
|
||||
});
|
|
@ -11,6 +11,8 @@ window.sliceLength = 2000000;
|
|||
// Global zip objects for currently created zip file
|
||||
window.zip = null;
|
||||
window.zipSize = 0;
|
||||
// Init the list of files (used by LDAP invitation feature)
|
||||
window.filesURLs = [];
|
||||
|
||||
// Copy a link to clipboard
|
||||
function copyToClipboard(txt) {
|
||||
|
@ -80,11 +82,9 @@ function addItem(name, url, size, del_at_first_view, created_at, delay, short, t
|
|||
function destroyBlock(el) {
|
||||
$(el).parents('li').remove();
|
||||
|
||||
var a = $('.link-input');
|
||||
var l = $('#results li');
|
||||
if (a.length === 0) {
|
||||
if ($('.link-input').length === 0) {
|
||||
$('#misc').empty();
|
||||
if (l.length === 0 && window.fileList === null) {
|
||||
if ($('#results li').length === 0 && window.fileList === null) {
|
||||
$('#results').hide();
|
||||
}
|
||||
} else {
|
||||
|
@ -134,7 +134,7 @@ function getZipname() {
|
|||
}
|
||||
}
|
||||
|
||||
return zipname;
|
||||
return escapeHtml(zipname);
|
||||
}
|
||||
|
||||
// Update the zip name
|
||||
|
@ -148,20 +148,28 @@ function uploadZip(e) {
|
|||
var delay = $('#delete-day');
|
||||
var del_at_first_view = $('#first-view');
|
||||
$('#zip-files').attr('disabled', 'disabled');
|
||||
$('#file-browser-button').attr('disabled', 'disabled');
|
||||
$('#file-browser-span').addClass('disabled');
|
||||
$('#uploadZip').addClass('hide');
|
||||
$('#zip-parts').text('');
|
||||
|
||||
$('#zip-compressing').removeClass('hide');
|
||||
window.zip.generateAsync({type:"blob"})
|
||||
.then(function(zipFile) {
|
||||
// if $('#zipping') is hidden, the zipping has been aborted
|
||||
if (!$('#zipping').hasClass('hide')) {
|
||||
window.zip = null;
|
||||
$('#zipping').addClass('hide');
|
||||
$('#zipname-input').addClass('hide');
|
||||
$('#zip-compressing').addClass('hide');
|
||||
$('#uploadZip').removeClass('hide');
|
||||
$('#results').show();
|
||||
$('#zip-files').attr('disabled', null);
|
||||
|
||||
var zipname = getZipname();
|
||||
var file = new File([zipFile], zipname, {type: 'application/zip'});
|
||||
|
||||
Materialize.toast(i18n.enqueued.replace('XXX', zipname), 3000, 'teal accent-3');
|
||||
if (window.fileList === undefined || window.fileList === null) {
|
||||
window.fileList = [file];
|
||||
uploadFile(0, delay.val(), del_at_first_view.is(':checked'));
|
||||
|
@ -169,6 +177,8 @@ function uploadZip(e) {
|
|||
window.fileList.push(file);
|
||||
}
|
||||
}
|
||||
$('#file-browser-button').attr('disabled', null);
|
||||
$('#file-browser-span').removeClass('disabled');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -184,6 +194,28 @@ function updateMailLink() {
|
|||
$('#mailto').attr('href', u);
|
||||
}
|
||||
|
||||
// [Invitation feature] Send URLs of files to server
|
||||
function sendFilesURLs() {
|
||||
if (window.filesURLs.length > 0) {
|
||||
$.ajax({
|
||||
url: sendFilesURLsURL,
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
urls: window.filesURLs
|
||||
},
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
if (data.success) {
|
||||
Materialize.toast(data.msg, 6000, 'teal accent-3');
|
||||
} else {
|
||||
Materialize.toast(data.msg, 10000, 'red accent-2');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Start uploading the files (called from <input> and from drop zone)
|
||||
function handleFiles(f) {
|
||||
var delay = $('#delete-day');
|
||||
|
@ -221,6 +253,11 @@ function handleFiles(f) {
|
|||
} else {
|
||||
if (window.fileList === undefined || window.fileList === null) {
|
||||
window.fileList = Array.prototype.slice.call(f);
|
||||
for (var i = 0; i < window.fileList.length; i++) {
|
||||
var file = window.fileList[i];
|
||||
Materialize.toast(i18n.enqueued.replace('XXX', escapeHtml(file.name)), 3000, 'teal accent-3');
|
||||
}
|
||||
window.nbFiles = window.fileList.length;
|
||||
$('#results').show();
|
||||
uploadFile(0, delay.val(), del_at_first_view.is(':checked'));
|
||||
} else {
|
||||
|
@ -405,10 +442,12 @@ function updateProgressBar(data) {
|
|||
window.onbeforeunload = null;
|
||||
$('#delete-day').attr('disabled', null);
|
||||
$('#first-view').attr('disabled', null);
|
||||
if ($('#zip-files').is(':checked')) {
|
||||
if ($('#zip-files').is(':checked') && window.zip === null) {
|
||||
$('label[for="zip-files"]').click();
|
||||
}
|
||||
|
||||
}
|
||||
if ($('#results li').length === 0 && window.fileList === null) {
|
||||
$('#results').hide();
|
||||
}
|
||||
} else {
|
||||
var i = data.i;
|
||||
|
@ -443,28 +482,32 @@ function updateProgressBar(data) {
|
|||
var del_url = actionURL+'d/'+short+'/'+data.token;
|
||||
var links = encodeURIComponent('["'+short+'"]');
|
||||
var limit = (delay === 0) ? i18n.noLimit : i18n.expiration+' '+moment.unix(delay * 86400 + created_at).locale(window.navigator.language).format('LLLL');
|
||||
n.html(n.html()+' '+s.html()+' <a href="'+actionURL+'m?links='+links+'"><i class="mdi-communication-email"></i></a><br>'+limit);
|
||||
d.html(['<div class="card-action">',
|
||||
'<div class="input-field">',
|
||||
'<span class="prefix big-prefix">',
|
||||
'<a href="', url, '" target="_blank">',
|
||||
'<i class="mdi-file-file-download small" title="', i18n.dlText, '"></i>',
|
||||
if (!isGuest) {
|
||||
n.html(n.html()+' '+s.html()+' <a href="'+actionURL+'m?links='+links+'"><i class="mdi-communication-email"></i></a><br>'+limit);
|
||||
d.html(['<div class="card-action">',
|
||||
'<div class="input-field">',
|
||||
'<span class="prefix big-prefix">',
|
||||
'<a href="', url, '" target="_blank">',
|
||||
'<i class="mdi-file-file-download small" title="', i18n.dlText, '"></i>',
|
||||
'</a>',
|
||||
'<a href="#" id="copyurl-', window.fc, '" title="', i18n.cpText, '">',
|
||||
'<i class="mdi-content-content-copy small"></i>',
|
||||
'</a>',
|
||||
'</span>',
|
||||
'<input id="', short, '" class="form-control link-input white-background" value="', url, '" readonly="" type="text">',
|
||||
'<label class="active" for="', short, '">', i18n.dlText, '</label>',
|
||||
'</div>',
|
||||
'<div class="input-field">',
|
||||
'<a href="', del_url, '" target="_blank" class="prefix big-prefix">',
|
||||
'<i class="mdi-action-delete small" title="', i18n.delText, '"></i>',
|
||||
'</a>',
|
||||
'<a href="#" id="copyurl-', window.fc, '" title="', i18n.cpText, '">',
|
||||
'<i class="mdi-content-content-copy small"></i>',
|
||||
'</a>',
|
||||
'</span>',
|
||||
'<input id="', short, '" class="form-control link-input white-background" value="', url, '" readonly="" type="text">',
|
||||
'<label class="active" for="', short, '">', i18n.dlText, '</label>',
|
||||
'</div>',
|
||||
'<div class="input-field">',
|
||||
'<a href="', del_url, '" target="_blank" class="prefix big-prefix">',
|
||||
'<i class="mdi-action-delete small" title="', i18n.delText, '"></i>',
|
||||
'</a>',
|
||||
'<input id="delete-', short, '" class="form-control white-background" value="', del_url, '" readonly="" type="text">',
|
||||
'<label class="active" for="delete-', short, '">', i18n.delText, '</label>',
|
||||
'</div>',
|
||||
'</div>'].join(''));
|
||||
'<input id="delete-', short, '" class="form-control white-background" value="', del_url, '" readonly="" type="text">',
|
||||
'<label class="active" for="delete-', short, '">', i18n.delText, '</label>',
|
||||
'</div>',
|
||||
'</div>'].join(''));
|
||||
} else {
|
||||
n.html(n.html()+' '+s.html());
|
||||
}
|
||||
s.remove();
|
||||
|
||||
var p2 = dp.parent();
|
||||
|
@ -482,7 +525,7 @@ function updateProgressBar(data) {
|
|||
});
|
||||
// Add copy all and mailto buttons
|
||||
var misc = $('#misc');
|
||||
if (misc.html() === '') {
|
||||
if (misc.html() === '' && !isGuest) {
|
||||
misc.html('<a href="#" id="copyall" class="btn btn-info">'+i18n.copyAll+'</a> <a id="mailto" href="'+actionURL+'m?links='+links+'" class="btn btn-info">'+i18n.mailTo+'</a>');
|
||||
$('#copyall').on('click', copyAllToClipboard);
|
||||
} else {
|
||||
|
@ -490,7 +533,13 @@ function updateProgressBar(data) {
|
|||
}
|
||||
|
||||
// Add the file to localStorage
|
||||
addItem(data.name, url, data.size, del_at_first_view, created_at, delay, data.short, data.token);
|
||||
if (!isGuest) {
|
||||
addItem(data.name, url, data.size, del_at_first_view, created_at, delay, data.short, data.token);
|
||||
}
|
||||
|
||||
if (isGuest && short !== null) {
|
||||
window.filesURLs.push(JSON.stringify({ name: data.name, short: data.short, url: url, size: data.size, created_at: created_at, delay: delay, token: data.token }));
|
||||
}
|
||||
|
||||
// Upload next file
|
||||
window.fc++;
|
||||
|
@ -503,10 +552,15 @@ function updateProgressBar(data) {
|
|||
window.onbeforeunload = null;
|
||||
$('#delete-day').attr('disabled', null);
|
||||
$('#first-view').attr('disabled', null);
|
||||
if ($('#zip-files').is(':checked')) {
|
||||
if ($('#zip-files').is(':checked') && window.zip === null) {
|
||||
$('label[for="zip-files"]').click();
|
||||
}
|
||||
|
||||
if (isGuest) {
|
||||
sendFilesURLs();
|
||||
}
|
||||
}
|
||||
if ($('#results li').length === 0 && window.fileList === null) {
|
||||
$('#results').hide();
|
||||
}
|
||||
} else {
|
||||
j++;
|
||||
|
@ -522,6 +576,9 @@ function updateProgressBar(data) {
|
|||
}
|
||||
} else {
|
||||
addAlertOnFile(data.msg, i, delay, del_at_first_view);
|
||||
if (isGuest) {
|
||||
sendFilesURLs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -638,5 +695,9 @@ $(document).ready(function() {
|
|||
$('#reset-zipping').on('click', function() {
|
||||
window.zip = null;
|
||||
$('label[for="zip-files"]').click();
|
||||
$('#zip-files').attr('disabled', null);
|
||||
$('#zip-compressing').addClass('hide');
|
||||
$('#file-browser-button').attr('disabled', null);
|
||||
$('#file-browser-span').removeClass('disabled');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -22,6 +22,15 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% }
|
||||
% if (stash('invitation')) {
|
||||
<div class="col s12">
|
||||
<div class="card blue">
|
||||
<div class="card-content white-text">
|
||||
<strong><%= l('The link(s) of your file(s) will automatically be sent by mail to %1 (%2)', stash('invitation')->ldap_user, stash('invitation')->ldap_user_mail) %></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% }
|
||||
<div class="col s12 hiddendiv" id="not-enough-entropy">
|
||||
<div class="card pink">
|
||||
|
@ -71,12 +80,12 @@
|
|||
<%= l('Files deleted at first download') %>
|
||||
</p>
|
||||
% }
|
||||
<p class="col s12 m6 text-left<%= ' hiddendiv' if $self->config('force_burn_after_reading') %>">
|
||||
<p class="col s12 m6 text-left<%= ' hiddendiv' if (config('force_burn_after_reading') || stash('invitation')) %>">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="first-view"
|
||||
data-checked="<%= 'data-checked' if $self->config('force_burn_after_reading') %>"
|
||||
<%= 'disabled="disabled"' if $self->config('force_burn_after_reading') %>
|
||||
data-checked="<%= 'data-checked' if config('force_burn_after_reading') %>"
|
||||
<%= 'disabled="disabled"' if config('force_burn_after_reading') %>
|
||||
>
|
||||
<label for="first-view"><%= l('Delete at first download?') %></label>
|
||||
</p>
|
||||
|
@ -91,7 +100,7 @@
|
|||
<label for="zip-files"><%= l('Create a zip archive with the files before uploading?') %></label>
|
||||
</p>
|
||||
</div>
|
||||
% if (config('allow_pwd_on_files')) {
|
||||
% if (config('allow_pwd_on_files') && (!stash('invitation'))) {
|
||||
<div class="col s12 m6">
|
||||
<div class="input-field">
|
||||
<input type="password" id="file_pwd" placeholder="<%= l('Password') %>" class="validate" autocomplete="off">
|
||||
|
@ -106,9 +115,6 @@
|
|||
<label for="zipname"><%= l('Name of the zip file') %></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col s12 m6 text-left input-field">
|
||||
<a href="#" id="uploadZip" class="btn waves-effect waves-light"><%= l('Upload generated zip file') %></a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div id="files">
|
||||
|
@ -132,6 +138,9 @@
|
|||
<button class="btn-floating pulse"><i class="mdi-content-archive"></i></button>
|
||||
<%= l('Compressing zip file…') %>
|
||||
</p>
|
||||
<div class="col s12 m6 text-left input-field right">
|
||||
<a href="#" id="uploadZip" class="btn waves-effect waves-light"><%= l('Upload generated zip file') %></a>
|
||||
</div>
|
||||
<ul id="zip-parts">
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -145,7 +154,11 @@
|
|||
</ul>
|
||||
</div>
|
||||
%= include 'delays'
|
||||
% if (defined stash('invitation')) {
|
||||
%= javascript '/partial/index.js?token=' . stash('invitation')->token
|
||||
% } else {
|
||||
%= javascript '/partial/index.js'
|
||||
% }
|
||||
%= javascript '/js/sjcl.js'
|
||||
%= javascript '/js/moment-with-locales.min.js'
|
||||
%= javascript '/js/filesize.min.js'
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
|
||||
|
||||
% if (stash('expired_or_deleted_invitation')) {
|
||||
<div class="col s12">
|
||||
<div class="card pink">
|
||||
<div class="card-content white-text">
|
||||
<strong><%= l('Sorry, your invitation has expired or has been deleted.') %></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% }
|
||||
% if (stash('invitation_not_found')) {
|
||||
<div class="col s12">
|
||||
<div class="card pink">
|
||||
<div class="card-content white-text">
|
||||
<strong><%= l('Sorry, the invitation doesn’t exist. Are you sure you are on the right URL?') %></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% }
|
|
@ -0,0 +1,51 @@
|
|||
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
|
||||
|
||||
% if (scalar(@{$self->stash('fails')})) {
|
||||
<div class="col s12">
|
||||
<div class="card pink">
|
||||
<div class="card-content white-text">
|
||||
% for my $msg (@{$self->stash('fails')}) {
|
||||
<strong><%= $msg %></strong>
|
||||
% }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% }
|
||||
% if (scalar(@{$self->stash('success')})) {
|
||||
<div class="col s12">
|
||||
<div class="card blue">
|
||||
<div class="card-content white-text">
|
||||
% for my $msg (@{$self->stash('success')}) {
|
||||
<strong><%== $msg %></strong>
|
||||
% }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% }
|
||||
|
||||
<form class="row" method="post">
|
||||
<h1><%= l('Invite a guest') %></h1>
|
||||
<div class="margin-bottom-35">
|
||||
<p>
|
||||
<%= l('You can invite someone to send you files through this Lufi instance even if they don’t have an account on it.') %>
|
||||
</p>
|
||||
% if (stash('send_with_user_email')) {
|
||||
<p>
|
||||
<%= l('The invitation mail will be send from your email address (%1).', stash('user_mail')) %>
|
||||
</p>
|
||||
% }
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<label for="guest_mail">
|
||||
<%= l('Email address of your guest') %>
|
||||
</label>
|
||||
<input id="guest_mail" name="guest_mail" type="email" placeholder="nami@example.org" required>
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<label for="expire_at">
|
||||
<%= l('How many days would you like the invitation to be valid?') %>
|
||||
</label>
|
||||
<input id="expire_at" name="expire_at" type="number" min="1" max="<%= stash('max_expire_at') %>" step="1" value="<%= stash('max_expire_at') %>" required>
|
||||
</div>
|
||||
<button class="btn waves-effect waves-light" type="submit"><%= l('Send the invitation') %></button>
|
||||
</form>
|
|
@ -0,0 +1,15 @@
|
|||
% # vim:set sw=4 ts=4 sts=4 ft=mail.epl expandtab:
|
||||
% stash subject => l('%1 invites you to send him/her files', stash('ldap_user'));
|
||||
|
||||
%= l('Hello,')
|
||||
|
||||
%= l('%1 invites you to send him/her files through Lufi.', stash('ldap_user'))
|
||||
|
||||
%= l('Click on the following URL to upload files on Lufi:')
|
||||
%== stash('url')
|
||||
|
||||
%= l('The links of your file(s) will automatically be send by mail to %1.', stash('ldap_user'))
|
||||
|
||||
%= l('This invitation is valid until %1.', stash('expires'))
|
||||
|
||||
%= l('Regards.')
|
|
@ -0,0 +1,87 @@
|
|||
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
|
||||
% use Number::Bytes::Human qw(format_bytes);
|
||||
% use Date::Format;
|
||||
|
||||
<h2><%= l('My invitations') %></h2>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
<%= l('Rows in purple mean that the invitations have expired.') %>
|
||||
</p>
|
||||
<div class="invitations-buttons">
|
||||
<a href="#" id="invertSelection" class="btn left-mg cyan"><%= l('Invert selection') %></a>
|
||||
<a href="#" id="toggleHidden" class="btn left-mg cyan"><%= l('Show hidden invitations') %></a>
|
||||
<a href="#" id="deleteInvit" class="btn left-mg cyan disabled" disabled><%= l('Delete') %></a>
|
||||
<a href="#" id="resendMail" class="btn left-mg cyan disabled" disabled><%= l('Resend invitation mail') %></a>
|
||||
<a href="#" id="toggleVisibility" class="btn left-mg cyan disabled" disabled><%= l('Toggle visibility') %></a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<table class="responsive-table highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="center-align"> </th>
|
||||
<th class="center-align"><%= l('Guest mail') %></th>
|
||||
<th class="center-align"><%= l('URL') %></th>
|
||||
<th class="center-align"><%= l('Created at') %></th>
|
||||
<th class="center-align"><%= l('Expire at') %></th>
|
||||
<th class="center-align"><%= l('Files sent at') %></th>
|
||||
<th class="center-align"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="myInvitations" data-visibility="hidden">
|
||||
% my $time = time;
|
||||
% $invitations->each(sub {
|
||||
% my ($e, $num) = @_;
|
||||
% return if $e->deleted;
|
||||
% my $class = '';
|
||||
% $class = 'purple lighten-4' unless $e->is_valid;
|
||||
% $class .= ' hide' unless $e->show_in_list;
|
||||
<tr id="row-<%= $e->token %>" class="<%= $class %>" data-visibility="<%= ($e->show_in_list) ? 1 : 0 %>">
|
||||
<td>
|
||||
<input type="checkbox" id="<%= $e->token %>" data-checked="">
|
||||
<label for="<%= $e->token %>" hidden></label>
|
||||
|
||||
% unless ($e->show_in_list) {
|
||||
<i class="mdi-navigation-cancel" title="<%= l('This invitation is normally hidden') %>"></i>
|
||||
% }
|
||||
</td>
|
||||
<td><%= $e->guest_mail %></td>
|
||||
<td><%= url_for('guest', token => $e->token)->to_abs %></td>
|
||||
<td><%= time2str(l('%A %d %B %Y at %T'), $e->created_at) %></td>
|
||||
<td id="expire-<%= $e->token %>"><%= time2str(l('%A %d %B %Y at %T'), $e->expire_at) %></td>
|
||||
<td><%= time2str(l('%A %d %B %Y at %T'), $e->files_sent_at) if $e->files_sent_at %></td>
|
||||
<td>
|
||||
% if ($e->files) {
|
||||
<a href="#files-info"
|
||||
data-files="<%= $e->files %>"
|
||||
data-token="<%= $e->token %>"
|
||||
data-guest="<%= $e->guest_mail %>"
|
||||
class="btn left-mg cyan waves-effect waves-light modal-trigger prefix">
|
||||
<%= l('Files') %>
|
||||
</a>
|
||||
% }
|
||||
</td>
|
||||
</tr>
|
||||
% });
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="files-info" class="modal">
|
||||
<div class="modal-content">
|
||||
<h1 class="small-h1"></h1>
|
||||
<div class="text-left">
|
||||
<ul id="files-ul">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class="modal-action modal-close waves-effect waves-green btn-flat"><%= l('Close') %></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
%= javascript '/partial/invitations.js'
|
||||
%= javascript '/js/lufi-list-invitations.js'
|
||||
%= javascript '/js/moment-with-locales.min.js'
|
||||
%= javascript '/js/filesize.min.js'
|
|
@ -0,0 +1,22 @@
|
|||
% # vim:set sw=4 ts=4 sts=4 ft=mail.epl expandtab:
|
||||
% use Number::Bytes::Human qw(format_bytes);
|
||||
% use Date::Format;
|
||||
% stash subject => l('%1 have send you files', stash('invitation')->guest_mail);
|
||||
|
||||
%= l('Hello %1,', ucfirst(stash('invitation')->ldap_user))
|
||||
|
||||
%= l('%1 used your invitation to send you files:', stash('invitation')->guest_mail)
|
||||
|
||||
% stash('files')->each(sub {
|
||||
% my ($e, $num) = @_;
|
||||
%= l('— %1 (%2), that will expire on %3', $e->{name}, format_bytes($e->{size}), time2str(l('%A %d %B %Y at %T'), $e->{created_at} + $e->{delay} * 86400))
|
||||
%= ' '.$e->{url}
|
||||
% });
|
||||
|
||||
% if (config('invitations')->{'save_files_url_in_db'} && stash('already_notified')) {
|
||||
%= l('NB: this list includes the list of files that have already been sent to you.')
|
||||
|
||||
% }
|
||||
%= l('Regards,')
|
||||
--
|
||||
Lufi
|
|
@ -32,6 +32,10 @@
|
|||
% if ((!defined(config('ldap')) && !defined(config('htpasswd'))) || 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>
|
||||
% if (defined config('ldap') && defined config('invitations')) {
|
||||
<li<%== ' class="active"' if (current_route eq 'invite') %>><a href="<%= url_for('/invite') %>"><%= l('Invite a guest') %></a></li>
|
||||
<li<%== ' class="active"' if (current_route eq 'invite/list') %>><a href="<%= url_for('/invite/list') %>"><%= l('My invitations') %></a></li>
|
||||
% }
|
||||
% } else {
|
||||
<li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li>
|
||||
% }
|
||||
|
@ -61,6 +65,10 @@
|
|||
% if ((!defined(config('ldap')) && !defined(config('htpasswd'))) || 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>
|
||||
% if (defined config('ldap') && defined config('invitations')) {
|
||||
<li<%== ' class="active"' if (current_route eq 'invite') %>><a href="<%= url_for('/invite') %>"><%= l('Invite a guest') %></a></li>
|
||||
<li<%== ' class="active"' if (current_route eq 'invite/list') %>><a href="<%= url_for('/invite/list') %>"><%= l('My invitations') %></a></li>
|
||||
% }
|
||||
% } else {
|
||||
<li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li>
|
||||
% }
|
||||
|
@ -77,7 +85,12 @@
|
|||
</li>
|
||||
<li<%== ' class="active"' if (current_route eq 'about') %>><a href="<%= url_for('/about') %>"><%= l('About') %></a></li>
|
||||
% if ((defined(config('ldap')) || defined(config('htpasswd'))) && is_user_authenticated()) {
|
||||
<li><a href="<%= url_for('/logout') %>"><%= l('Logout') %></a></li>
|
||||
<li>
|
||||
<form action="<%= url_for('/logout') %>" method="POST">
|
||||
%= csrf_field
|
||||
<button class="btn-flat" type="submit"><%= l('Logout') %></button>
|
||||
</form>
|
||||
</li>
|
||||
% }
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
</div>
|
||||
</div>
|
||||
%= csrf_field
|
||||
<input name="redirect" value="<%= stash('redirect') %>" type="hidden">
|
||||
<div class="col s8 m8 offset-s2 offset-m2">
|
||||
<button class="btn waves-effect waves-light" type="submit" name="action">
|
||||
<%= l('Signin') %>
|
||||
|
|
|
@ -10,6 +10,7 @@ var baseURL = '<%= url_for('/')->to_abs() %>';
|
|||
% }
|
||||
var actionURL = '<%= url_for('/')->to_abs() %>';
|
||||
var i18n = {
|
||||
enqueued: '<%= l('XXX file has been added to upload queue.') %>',
|
||||
confirmExit: '<%= l('You have attempted to leave this page. The upload will be canceled. Are you sure?') %>',
|
||||
copyAll: '<%= l('Copy all links to clipboard') %>',
|
||||
copySuccess: '<%= l('The link(s) has been copied to your clipboard') %>',
|
||||
|
@ -29,3 +30,10 @@ var i18n = {
|
|||
wsProblem: '<%= l('Websocket communication error') %>',
|
||||
};
|
||||
var maxSize = <%= config('max_file_size') || 0 %>;
|
||||
|
||||
% if (stash('token')) {
|
||||
var isGuest = true;
|
||||
var sendFilesURLsURL = '<%= url_for('guest_send_mail', token => stash('token'))->to_abs() %>';
|
||||
% } else {
|
||||
var isGuest = false;
|
||||
% }
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
% # vim:set sts=4 sw=4 ts=4 ft=javascript expandtab:
|
||||
var i18n = {
|
||||
confirmDeleteInvit: '<%= l('Are you sure you want to delete the selected invitations?') %>',
|
||||
confirmResendMail: '<%= l('Are you sure you want to resend the invitation mail for the selected invitations?') %>',
|
||||
expiration: '<%= l('expires on XXX') %>',
|
||||
hiddenMark: '<i class="mdi-navigation-cancel" title="<%= l('This invitation is normally hidden') %>"></i>',
|
||||
hideText: '<%= l('Hide hidden invitations') %>',
|
||||
listFiles: '<%= l('Files sent in invitation XX1 by XX2') %>',
|
||||
showText: '<%= l('Show hidden invitations') %>'
|
||||
};
|
||||
|
||||
var deleteURL = '<%= url_for('invite_list_delete') %>';
|
||||
var resendURL = '<%= url_for('invite_list_resend') %>';
|
||||
var toggleURL = '<%= url_for('invite_list_visibility') %>';
|
|
@ -31,3 +31,19 @@ DROP TABLE files;
|
|||
ALTER TABLE files ADD COLUMN zipped boolean default false;
|
||||
-- 2 down
|
||||
ALTER TABLE files DROP COLUMN zipped;
|
||||
-- 3 up
|
||||
CREATE TABLE IF NOT EXISTS invitations (
|
||||
token varchar(255) PRIMARY KEY,
|
||||
ldap_user varchar(255),
|
||||
ldap_user_mail varchar(255),
|
||||
guest_mail varchar(255),
|
||||
created_at integer,
|
||||
expire_at integer,
|
||||
files_sent_at integer,
|
||||
expend_expire_at integer,
|
||||
files text,
|
||||
show_in_list boolean,
|
||||
deleted boolean
|
||||
);
|
||||
-- 3 down
|
||||
DROP TABLE invitations;
|
||||
|
|
|
@ -34,3 +34,19 @@ ALTER TABLE files DROP COLUMN abuse;
|
|||
ALTER TABLE files ADD COLUMN zipped boolean default false;
|
||||
-- 3 down
|
||||
ALTER TABLE files DROP COLUMN zipped;
|
||||
-- 4 up
|
||||
CREATE TABLE IF NOT EXISTS invitations (
|
||||
token text PRIMARY KEY,
|
||||
ldap_user text,
|
||||
ldap_user_mail text,
|
||||
guest_mail text,
|
||||
created_at integer,
|
||||
expire_at integer,
|
||||
files_sent_at integer,
|
||||
expend_expire_at integer,
|
||||
files text,
|
||||
show_in_list boolean,
|
||||
deleted boolean
|
||||
);
|
||||
-- 4 down
|
||||
DROP TABLE invitations;
|
||||
|
|
|
@ -78,3 +78,19 @@ BEGIN TRANSACTION;
|
|||
DROP TABLE files;
|
||||
ALTER TABLE files_backup RENAME TO files;
|
||||
COMMIT;
|
||||
-- 4 up
|
||||
CREATE TABLE IF NOT EXISTS invitations (
|
||||
token TEXT PRIMARY KEY,
|
||||
ldap_user TEXT,
|
||||
ldap_user_mail TEXT,
|
||||
guest_mail TEXT,
|
||||
created_at INTEGER,
|
||||
expire_at INTEGER,
|
||||
files_sent_at INTEGER,
|
||||
expend_expire_at INTEGER,
|
||||
files TEXT,
|
||||
show_in_list INTEGER,
|
||||
deleted INTEGER
|
||||
);
|
||||
-- 4 down
|
||||
DROP TABLE invitations;
|
||||
|
|
Loading…
Reference in New Issue