From b5ea181bea06d32e0b8211eaf0b345380bef9cca Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Tue, 24 Jul 2018 21:34:06 +0200 Subject: [PATCH] Improve image CLI command - Add CLI command to remove images - Add CLI command to search images based on the uploader's IP address This commit is dedicated to Schoumi, who is supporting me on Tipeee. Many thanks :-) --- CHANGELOG | 2 + lib/Lutim.pm | 2 + lib/Lutim/Command/image.pm | 74 +++++++++++++++++++++++-- lib/Lutim/DB/Image.pm | 14 +++++ lib/Lutim/DB/Image/Pg.pm | 21 +++++++ lib/Lutim/DB/Image/SQLite.pm | 21 +++++++ themes/default/lib/Lutim/I18N/lutim.pot | 6 +- 7 files changed, 133 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 281672a..4ee30d8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,8 @@ Revision history for Lutim - Add a message saying how many images there is in the gallery - Use ISO::639_1 for languages' native names - Add CLI command to print informations about images + - Add CLI command to remove images + - Add CLI command to search images based on the uploader's IP address 0.10.4 2018-05-07 - Fix bug in cache system that would allow someone to view an image with an incorrect decryption key diff --git a/lib/Lutim.pm b/lib/Lutim.pm index f552f72..b5ca0c5 100644 --- a/lib/Lutim.pm +++ b/lib/Lutim.pm @@ -23,6 +23,8 @@ sub startup { $self->{wait_for_it} = {}; + push @{$self->commands->namespaces}, 'Lutim::Command'; + $self->plugin('DebugDumperHelper'); my $config = $self->plugin('Config', { diff --git a/lib/Lutim/Command/image.pm b/lib/Lutim/Command/image.pm index bf139c2..d98e13c 100644 --- a/lib/Lutim/Command/image.pm +++ b/lib/Lutim/Command/image.pm @@ -13,7 +13,7 @@ has usage => sub { shift->extract_usage }; my $csv_header = 0; sub run { - my $c = shift; + my $c = shift; my @args = @_; my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf'); @@ -59,9 +59,25 @@ sub run { } }); + if (scalar(@{$config->{memcached_servers}})) { + $c->app->plugin(CHI => { + lutim_images_cache => { + driver => 'Memcached', + servers => $config->{memcached_servers}, + expires_in => '1 day', + expires_on_backend => 1, + } + }); + } + getopt \@args, - 'i|info=s{1,}' => \my @info, - 'c|csv' => \my $csv; + 'i|info=s{1,}' => \my @info, + 'c|csv' => \my $csv, + 'r|remove=s{1,}' => \my @remove, + 'y|yes' => \my $yes, + 'q|quiet' => \my $quiet, + 's|search=s' => \my $ip + ; if (scalar @info) { c(@info)->each( @@ -72,6 +88,36 @@ sub run { } ); } + if (scalar @remove) { + c(@remove)->each( + sub { + my ($e, $num) = @_; + my $i = get_short($c, $e); + if ($i) { + if ($i->enabled) { + print_infos($i, 0) unless $quiet; + delete_short($c, $i, $yes); + } else { + say sprintf('The image %s is already disabled', $e); + } + } + } + ); + if ($config->{cache_max_size} && !scalar(@{$config->{memcached_servers}})) { + say "\nPlease reload Lutim to be sure that the deleted images are not in the cache anymore."; + } + } + if ($ip) { + my $u = Lutim::DB::Image->new(app => $c->app)->search_created_by($ip); + my @shorts; + $u->each(sub { + my ($e, $num) = @_; + push @shorts, $e->short; + print_infos($e, $csv); + }); + say sprintf('%d matching URLs', $u->size); + say sprintf("If you want to delete those images, please do:\n carton exec script/lutim image --remove %s", join(' ', @shorts)) if @shorts; + } } sub get_short { @@ -145,6 +191,24 @@ EOF } } +sub delete_short { + my $c = shift; + my $i = shift; + my $y = shift; + + my $confirm = ($y) ? 'yes' : undef; + unless (defined $confirm) { + printf('Are you sure you want to remove this image (%s) ? [N/y] ', $i->short); + $confirm = ; + chomp $confirm; + } + if ($confirm =~ m/^y(es)?$/i) { + $c->app->delete_image($i); + } else { + say 'Answer was not "y" or "yes". Aborting deletion.'; + } +} + =encoding utf8 =head1 NAME @@ -154,7 +218,9 @@ Lutim::Command::image - Manage URL in Lutim's database =head1 SYNOPSIS Usage: - carton exec script/lutim image --info [--csv] Print infos about the space-separated images (--csv creates a CSV output) + carton exec script/lutim image --info [--csv] Print infos about the space-separated images (--csv creates a CSV output) + carton exec script/lutim image --remove [--yes] [--quiet] Delete the space-separated images (--yes disables confirmation, --quiet disables informations printing) + carton exec script/lutim image --search Print infos about the images uploaded by this IP (database LIKE, may include images uploaded by other IPs) =cut diff --git a/lib/Lutim/DB/Image.pm b/lib/Lutim/DB/Image.pm index fd743d0..8f5a1f1 100644 --- a/lib/Lutim/DB/Image.pm +++ b/lib/Lutim/DB/Image.pm @@ -331,6 +331,20 @@ sub to_hash { =back +=head2 search_created_by + +=over 1 + +=item B : C<$c-Esearch_created_by($ip)> + +=item B : an IP address + +=item B : get enabled images that have been uploaded by this IP address (database query: LIKE '$ip%', results may include images uploaded by similar IP addresses) + +=item B : a Mojo::Collection object containing the matching images as Lutim::DB::Image objects + +=back + =cut 1; diff --git a/lib/Lutim/DB/Image/Pg.pm b/lib/Lutim/DB/Image/Pg.pm index e4d8671..9bf2057 100644 --- a/lib/Lutim/DB/Image/Pg.pm +++ b/lib/Lutim/DB/Image/Pg.pm @@ -189,6 +189,27 @@ sub disable { return $c; } +sub search_created_by { + my $c = shift; + my $ip = shift; + + my @images; + + my $records = $c->app->pg->db->select('lutim', undef, { enabled => 1, created_by => { -like => $ip.'%' } })->hashes; + + $records->each( + sub { + my ($e, $num) = @_; + my $i = Lutim::DB::Image->new(app => $c->app); + $i->_slurp($e); + + push @images, $i; + } + ); + + return c(@images); +} + sub _slurp { my $c = shift; my $r = shift; diff --git a/lib/Lutim/DB/Image/SQLite.pm b/lib/Lutim/DB/Image/SQLite.pm index 9915bf5..fd68ebc 100644 --- a/lib/Lutim/DB/Image/SQLite.pm +++ b/lib/Lutim/DB/Image/SQLite.pm @@ -190,6 +190,27 @@ sub disable { return $c; } +sub search_created_by { + my $c = shift; + my $ip = shift; + + my @images; + + my $records = $c->app->sqlite->db->select('lutim', undef, { enabled => 1, created_by => { -like => $ip.'%' } })->hashes; + + $records->each( + sub { + my ($e, $num) = @_; + my $i = Lutim::DB::Image->new(app => $c->app); + $i->_slurp($e); + + push @images, $i; + } + ); + + return c(@images); +} + sub _slurp { my $c = shift; my $r = shift; diff --git a/themes/default/lib/Lutim/I18N/lutim.pot b/themes/default/lib/Lutim/I18N/lutim.pot index 3a54eb2..f0dcc0f 100644 --- a/themes/default/lib/Lutim/I18N/lutim.pot +++ b/themes/default/lib/Lutim/I18N/lutim.pot @@ -32,11 +32,11 @@ msgstr "" msgid "-or-" msgstr "" -#: lib/Lutim.pm:219 lib/Lutim/Command/cron/stats.pm:151 lib/Lutim/Command/cron/stats.pm:165 lib/Lutim/Command/cron/stats.pm:182 themes/default/templates/index.html.ep:5 themes/default/templates/partial/raw.js.ep:25 themes/default/templates/partial/raw.js.ep:8 themes/default/templates/raw.html.ep:10 +#: lib/Lutim.pm:221 lib/Lutim/Command/cron/stats.pm:151 lib/Lutim/Command/cron/stats.pm:165 lib/Lutim/Command/cron/stats.pm:182 themes/default/templates/index.html.ep:5 themes/default/templates/partial/raw.js.ep:25 themes/default/templates/partial/raw.js.ep:8 themes/default/templates/raw.html.ep:10 msgid "1 year" msgstr "" -#: lib/Lutim.pm:218 lib/Lutim/Command/cron/stats.pm:148 lib/Lutim/Command/cron/stats.pm:162 lib/Lutim/Command/cron/stats.pm:179 themes/default/templates/index.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:149 themes/default/templates/partial/raw.js.ep:22 themes/default/templates/partial/raw.js.ep:5 themes/default/templates/raw.html.ep:7 +#: lib/Lutim.pm:220 lib/Lutim/Command/cron/stats.pm:148 lib/Lutim/Command/cron/stats.pm:162 lib/Lutim/Command/cron/stats.pm:179 themes/default/templates/index.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:149 themes/default/templates/partial/raw.js.ep:22 themes/default/templates/partial/raw.js.ep:5 themes/default/templates/raw.html.ep:7 msgid "24 hours" msgstr "" @@ -507,7 +507,7 @@ msgstr "" msgid "core developer" msgstr "" -#: lib/Lutim.pm:217 lib/Lutim/Command/cron/stats.pm:147 lib/Lutim/Command/cron/stats.pm:161 lib/Lutim/Command/cron/stats.pm:178 themes/default/templates/index.html.ep:3 themes/default/templates/partial/raw.js.ep:21 themes/default/templates/partial/raw.js.ep:4 themes/default/templates/raw.html.ep:6 +#: lib/Lutim.pm:219 lib/Lutim/Command/cron/stats.pm:147 lib/Lutim/Command/cron/stats.pm:161 lib/Lutim/Command/cron/stats.pm:178 themes/default/templates/index.html.ep:3 themes/default/templates/partial/raw.js.ep:21 themes/default/templates/partial/raw.js.ep:4 themes/default/templates/raw.html.ep:6 msgid "no time limit" msgstr ""