diff --git a/.gitignore b/.gitignore index 66ca220..8850a34 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ *.swp lutim.conf -lutim.db +*.db *.db-shm *.db-wal script/hypnotoad.pid diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..3ce11b4 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,18 @@ +image: hatsoftwares/test-ci:latest +stages: + - sqlite +before_script: + - carton install + - rm -f *db +sqlite: + stage: sqlite + cache: + key: "$CI_BUILD_REF_NAME" + untracked: true + paths: + - local + script: + - MOJO_CONFIG=t/sqlite.conf make test + tags: + - Debian + - Jessie diff --git a/Makefile b/Makefile index 3629796..23631ba 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ OC=themes/default/lib/Lutim/I18N/oc.po XGETTEXT=carton exec local/bin/xgettext.pl CARTON=carton exec LUTIM=script/lutim +REAL_LUTIM=script/application locales: $(XGETTEXT) $(EXTRACTDIR) -o $(EN) 2>/dev/null @@ -15,6 +16,14 @@ locales: $(XGETTEXT) $(EXTRACTDIR) -o $(ES) 2>/dev/null $(XGETTEXT) $(EXTRACTDIR) -o $(OC) 2>/dev/null +podcheck: + podchecker lib/Lutim/DB/Image.pm + +test-sqlite: + MOJO_CONFIG=t/sqlite.conf $(CARTON) $(REAL_LUTIM) test + +test: podcheck test-sqlite + clean: rm -rf lutim.db files/ diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 62286ff..7ea7c60 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -309,19 +309,19 @@ DISTRIBUTIONS Data::Validate::Domain 0 Data::Validate::IP 0 ExtUtils::MakeMaker 0 - DateTime-1.42 - pathname: D/DR/DROLSKY/DateTime-1.42.tar.gz + DateTime-1.43 + pathname: D/DR/DROLSKY/DateTime-1.43.tar.gz provides: - DateTime 1.42 - DateTime::Duration 1.42 - DateTime::Helpers 1.42 - DateTime::Infinite 1.42 - DateTime::Infinite::Future 1.42 - DateTime::Infinite::Past 1.42 - DateTime::LeapSecond 1.42 - DateTime::PP 1.42 - DateTime::PPExtra 1.42 - DateTime::Types 1.42 + DateTime 1.43 + DateTime::Duration 1.43 + DateTime::Helpers 1.43 + DateTime::Infinite 1.43 + DateTime::Infinite::Future 1.43 + DateTime::Infinite::Past 1.43 + DateTime::LeapSecond 1.43 + DateTime::PP 1.43 + DateTime::PPExtra 1.43 + DateTime::Types 1.43 requirements: Carp 0 DateTime::Locale 1.06 diff --git a/lib/Lutim/Command/cron/cleanbdd.pm b/lib/Lutim/Command/cron/cleanbdd.pm index c554a6e..c13b744 100644 --- a/lib/Lutim/Command/cron/cleanbdd.pm +++ b/lib/Lutim/Command/cron/cleanbdd.pm @@ -2,6 +2,7 @@ package Lutim::Command::cron::cleanbdd; use Mojo::Base 'Mojolicious::Command'; use Lutim::DB::Image; +use Mojo::File; use FindBin qw($Bin); use File::Spec qw(catfile); @@ -11,8 +12,15 @@ has usage => sub { shift->extract_usage }; sub run { my $c = shift; + my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } my $config = $c->app->plugin('Config', { - file => File::Spec->catfile($Bin, '..' ,'lutim.conf'), + file => $cfile, default => { keep_ip_during => 365, dbtype => 'sqlite', diff --git a/lib/Lutim/Command/cron/cleanfiles.pm b/lib/Lutim/Command/cron/cleanfiles.pm index a30e019..59a2def 100644 --- a/lib/Lutim/Command/cron/cleanfiles.pm +++ b/lib/Lutim/Command/cron/cleanfiles.pm @@ -4,6 +4,7 @@ use Mojo::Base 'Mojolicious::Command'; use Mojo::Util qw(slurp decode); use Lutim::DB::Image; use Lutim; +use Mojo::File; use FindBin qw($Bin); use File::Spec qw(catfile); @@ -13,8 +14,15 @@ has usage => sub { shift->extract_usage }; sub run { my $c = shift; + my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } my $config = $c->app->plugin('Config', { - file => File::Spec->catfile($Bin, '..' ,'lutim.conf'), + file => $cfile, default => { dbtype => 'sqlite', } diff --git a/lib/Lutim/Command/cron/stats.pm b/lib/Lutim/Command/cron/stats.pm index 4c6733a..7c83920 100644 --- a/lib/Lutim/Command/cron/stats.pm +++ b/lib/Lutim/Command/cron/stats.pm @@ -15,8 +15,15 @@ has usage => sub { shift->extract_usage }; sub run { my $c = shift; + my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } my $config = $c->app->plugin('Config', { - file => File::Spec->catfile($Bin, '..' ,'lutim.conf'), + file => $cfile, theme => 'default', default => { stats_day_num => 365, diff --git a/lib/Lutim/Command/cron/watch.pm b/lib/Lutim/Command/cron/watch.pm index 1e0f1a7..4eb2ba5 100644 --- a/lib/Lutim/Command/cron/watch.pm +++ b/lib/Lutim/Command/cron/watch.pm @@ -5,6 +5,7 @@ use Mojo::Util qw(slurp decode); use Filesys::DiskUsage qw/du/; use Lutim::DB::Image; use Lutim; +use Mojo::File; use Switch; use FindBin qw($Bin); use File::Spec qw(catfile); @@ -15,8 +16,15 @@ has usage => sub { shift->extract_usage }; sub run { my $c = shift; + my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } my $config = $c->app->plugin('Config', { - file => File::Spec->catfile($Bin, '..' ,'lutim.conf'), + file => $cfile, default => { policy_when_full => 'warn', dbtype => 'sqlite', diff --git a/lib/Lutim/Controller.pm b/lib/Lutim/Controller.pm index 0c452e3..bff11ee 100644 --- a/lib/Lutim/Controller.pm +++ b/lib/Lutim/Controller.pm @@ -405,7 +405,7 @@ sub add { } my $key; - if ($c->param('crypt') || $c->config->{always_encrypt}) { + if ($c->param('crypt') || $c->config('always_encrypt')) { ($upload, $key) = $c->crypt($upload, $filename); } $upload->move_to($path); diff --git a/lib/Lutim/DB/SQLite.pm b/lib/Lutim/DB/SQLite.pm index b6d1530..83bc9c2 100644 --- a/lib/Lutim/DB/SQLite.pm +++ b/lib/Lutim/DB/SQLite.pm @@ -6,9 +6,16 @@ use FindBin qw($Bin); BEGIN { my $m = Mojolicious->new; + my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } our $config = $m->plugin('Config' => { - file => Mojo::File->new($Bin, '..' ,'lutim.conf')->to_abs->to_string, + file => $cfile->to_abs->to_string, default => { db_path => 'lutim.db' } diff --git a/lib/Mounter.pm b/lib/Mounter.pm index 5887a57..19d21cb 100644 --- a/lib/Mounter.pm +++ b/lib/Mounter.pm @@ -1,6 +1,7 @@ # vim:set sw=4 ts=4 sts=4 ft=perl expandtab: package Mounter; use Mojo::Base 'Mojolicious'; +use Mojo::File; use FindBin qw($Bin); use File::Spec qw(catfile); @@ -10,9 +11,16 @@ sub startup { push @{$self->commands->namespaces}, 'Lutim::Command'; + my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } my $config = $self->plugin('Config' => { - file => File::Spec->catfile($Bin, '..' ,'lutim.conf'), + file => $cfile, default => { prefix => '/', theme => 'default', diff --git a/t/basic.t b/t/basic.t deleted file mode 100644 index 5f257e5..0000000 --- a/t/basic.t +++ /dev/null @@ -1,9 +0,0 @@ -use Mojo::Base -strict; - -use Test::More; -use Test::Mojo; - -my $t = Test::Mojo->new('Lutim'); -$t->get_ok('/')->status_is(200)->content_like(qr/Mojolicious/i); - -done_testing(); diff --git a/t/sqlite.conf b/t/sqlite.conf new file mode 100644 index 0000000..6d09e79 --- /dev/null +++ b/t/sqlite.conf @@ -0,0 +1,169 @@ +# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: +{ + #################### + # Hypnotoad settings + #################### + # 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 + listen => ['http://127.0.0.1:8080'], + # if you use Lutim behind a reverse proxy like Nginx, you want to set proxy to 1 + # if you use Lutim directly, let it commented + #proxy => 1, + }, + + ################ + # Lutim settings + ################ + + # put a way to contact you here and uncomment it + # mandatory + contact => 'John Doe, admin[at]example.com', + + # random string used to encrypt cookies + # mandatory + secrets => ['fdjsofjoihrei'], + + # choose a theme. See the available themes in `themes` directory + # optional, default is 'default' + #theme => 'default', + + # length of the images random URL + # optional, default is 8 + #length => 8, + + # length of the encryption key + # optional, default is 8 + #crypto_key_length => 8, + + # how many URLs will be provisioned in a batch ? + # optional, default is 5 + #provis_step => 5, + + # max number of URLs to be provisioned + # optional, default is 100 + #provisioning => 100, + + # anti-flood protection delay, in seconds + # users won't be able to ask Lutim to download images more than one per anti_flood_delay seconds + # optional, default is 5 + #anti_flood_delay => 5, + + # twitter account which will appear on twitter cards + # see https://dev.twitter.com/docs/cards/validation/validator to register your Lutim instance on twitter + # optional, default is @framasky + #tweet_card_via => '@framasky', + + # max image size, in octets + # you can write it 10*1024*1024 + # optional, default is 10485760 + max_file_size => 1048576, + + # 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', + + # if you want to include something in the right of the screen, put it here + # here's an example to put the logo of your hoster + # optional, no default + #hosted_by => 'My super hoster Hoster logo', + + # DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED + # Lutim now checks if the X-Forwarded-Proto header is present and equal to https. + # set to 1 if you use Lutim behind a secure web server + # optional, default is 0 + #https => 0, + + # broadcast_message which will displayed on all pages of Lutim (but no in json response) + # optional, no default + broadcast_message => 'test broadcast message', + + # 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'], + + # default time limit for files + # valid values are 0, 1, 7, 30 and 365 + # optional, default is 0 (no limit) + default_delay => 30, + + # 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 => 200, + + # if set to 1, all the images will be encrypted and the encryption option will no be displayed + # optional, default is 0 + #always_encrypt => 0, + + # length of the image's delete token + # optional, default is 24 + #token_length => 24, + + # URL sub-directory in which you want Lutim to be accessible + # example: you want to have Lutim under https://example.org/lutim/ + # => set prefix to '/lutim' or to '/lutim/', it doesn't matter + # optional, defaut is / + #prefix => '/', + + # choose what database you want to use + # valid choices are sqlite and postgresql (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 lutim directory or set an absolute path + # remember that it has to be in a directory writable by Lutim user + # optional, default is lutim.db + db_path => 'test.db', + + # PostgreSQL ONLY - only used if dbtype is set to postgresql + # these are the credentials to access the PostgreSQL database + # mandatory if you choosed postgresql as dbtype + #pgdb => { + # database => 'lutim', + # host => 'localhost', + # #user => 'DBUSER', + # #pwd => 'DBPASSWORD' + #}, + + # define the height of the thumbnails generated at users' will + # this is not the height of the thumbnails send after upload, + # we're talking about thumbnails generated when someone asked for + # https://example.org/lutim/tesrinp?thumb + # this works only if you have ImageMagick + # optional, default is 100 (pixels) + #thumbnail_size => 100, + + ########################## + # Lutim cron jobs settings + ########################## + + # number of days shown in /stats page (used with script/lutim cron stats) + # optional, default is 365 + #stats_day_num => 365, + + # number of days senders' IP addresses are kept in database + # after that delay, they will be deleted from database (used with script/lutim cron cleanbdd) + # optional, default is 365 + #keep_ip_during => 365, + + # max size of the files directory, in octets + # used by script/lutim 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/lutim cron watch) + # valid values are 'warn', 'stop-upload' and 'delete' + # please, see readme + # 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 + # optional, no default + #delete_no_longer_viewed_files => 90 +}; diff --git a/t/test.t b/t/test.t new file mode 100644 index 0000000..2c999c2 --- /dev/null +++ b/t/test.t @@ -0,0 +1,107 @@ +# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: +use Mojo::Base -strict; +use Mojo::File; +use Mojo::JSON qw(true false); +use Mojolicious; + +use Test::More; +use Test::Mojo; + +use FindBin qw($Bin); +use Digest::file qw(digest_file_hex); + +my ($m, $cfile); + +BEGIN { + use lib 'lib'; + $m = Mojolicious->new; + $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } + my $config = $m->plugin('Config' => + { + file => $cfile->to_abs->to_string, + default => { + dbtype => 'sqlite' + } + } + ); + $m->plugin('Lutim::Plugin::Helpers'); + $m->plugin('DebugDumperHelper'); +} + +# Home page +my $t = Test::Mojo->new('Lutim'); +$t->get_ok('/') + ->status_is(200) + ->content_like(qr/Let's Upload That IMage/i); + +# Instance settings informations +$t->get_ok('/infos') + ->status_is(200) + ->json_is( + { + always_encrypt => false, + broadcast_message => 'test broadcast message', + contact => 'John Doe, admin[at]example.com', + default_delay => 30, + image_magick => true, + max_delay => 200, + max_file_size => 1048576 + } + ); + +# Post image +my $image = Mojo::File->new($Bin, '..', 'themes', 'default', 'public', 'img', 'Lutim.png')->to_string; +$t->post_ok('/' => form => { file => { file => $image }, format => 'json' }) + ->status_is(200) + ->json_has('msg', 'success') + ->json_is('/success' => true, '/msg/filename' => 'Lutim.png') + ->json_like('/msg/short' => qr#[-_a-zA-Z0-9]{8}#, '/msg/real_short' => qr#[-_a-zA-Z0-9]{8}#, '/msg/token' => qr#[-_a-zA-Z0-9]{24}#); + +# Post delete-at-first-view image +my $raw = $t->ua->post('/' => form => { file => { file => $image }, 'first-view' => 1, format => 'json' })->res; +my $short = $raw->json('/msg/short'); + +$t->get_ok('/'.$short) + ->status_is(200); + +$t->get_ok('/'.$short) + ->status_is(302); + +# Delete image with token +$raw = $t->ua->post('/' => form => { file => { file => $image }, format => 'json' })->res; +my $rshort = $raw->json('/msg/real_short'); +my $token = $raw->json('/msg/token'); + +$t->get_ok('/'.$rshort) + ->status_is(200); + +$t->get_ok('/d/'.$rshort.'/'.$token, form => { format => 'json' }) + ->status_is('200') + ->json_is( + { + success => true, + msg => 'The image Lutim.png has been successfully deleted' + } + ); + +$t->get_ok('/'.$rshort) + ->status_is(302); + +# Get image counter +$t->post_ok('/c', form => { short => $rshort, token => $token }) + ->status_is(200) + ->json_is( + { + success => true, + counter => 1, + enabled => false + } + ); + +done_testing();