diff options
-rwxr-xr-x | bin/update-schema | 1 | ||||
-rw-r--r-- | db/downgrade_0065---0064.sql | 14 | ||||
-rw-r--r-- | db/schema.sql | 1 | ||||
-rw-r--r-- | db/schema_0065-add-moderation-admin-log.sql | 13 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Moderate.pm | 44 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Comment.pm | 24 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/ModerationOriginalData.pm | 10 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Problem.pm | 24 | ||||
-rw-r--r-- | perllib/FixMyStreet/Roles/Moderation.pm | 41 | ||||
-rw-r--r-- | templates/web/base/admin/report_edit.html | 4 | ||||
-rw-r--r-- | templates/web/base/admin/update_edit.html | 4 |
11 files changed, 115 insertions, 65 deletions
diff --git a/bin/update-schema b/bin/update-schema index 55a052ccc..1e1afa72c 100755 --- a/bin/update-schema +++ b/bin/update-schema @@ -212,6 +212,7 @@ else { # (assuming schema change files are never half-applied, which should be the case) sub get_db_version { return 'EMPTY' if ! table_exists('problem'); + return '0065' if constraint_contains('admin_log_object_type_check', 'moderation'); return '0064' if index_exists('moderation_original_data_problem_id_comment_id_idx'); return '0063' if column_exists('moderation_original_data', 'extra'); return '0062' if column_exists('users', 'created'); diff --git a/db/downgrade_0065---0064.sql b/db/downgrade_0065---0064.sql new file mode 100644 index 000000000..455627b77 --- /dev/null +++ b/db/downgrade_0065---0064.sql @@ -0,0 +1,14 @@ +BEGIN; + +DELETE FROM admin_log WHERE object_type = 'moderation'; + +ALTER TABLE admin_log DROP CONSTRAINT admin_log_object_type_check; + +ALTER TABLE admin_log ADD CONSTRAINT admin_log_object_type_check CHECK ( + object_type = 'problem' + OR object_type = 'update' + OR object_type = 'user' +); + +COMMIT; + diff --git a/db/schema.sql b/db/schema.sql index d5d63f478..c97e8d585 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -427,6 +427,7 @@ create table admin_log ( object_type = 'problem' or object_type = 'update' or object_type = 'user' + or object_type = 'moderation' ), object_id integer not null, action text not null, diff --git a/db/schema_0065-add-moderation-admin-log.sql b/db/schema_0065-add-moderation-admin-log.sql new file mode 100644 index 000000000..9a5385db7 --- /dev/null +++ b/db/schema_0065-add-moderation-admin-log.sql @@ -0,0 +1,13 @@ +BEGIN; + +ALTER TABLE admin_log DROP CONSTRAINT admin_log_object_type_check; + +ALTER TABLE admin_log ADD CONSTRAINT admin_log_object_type_check CHECK ( + object_type = 'problem' + OR object_type = 'update' + OR object_type = 'user' + OR object_type = 'moderation' +); + +COMMIT; + diff --git a/perllib/FixMyStreet/App/Controller/Moderate.pm b/perllib/FixMyStreet/App/Controller/Moderate.pm index 3ed2022ee..154f09176 100644 --- a/perllib/FixMyStreet/App/Controller/Moderate.pm +++ b/perllib/FixMyStreet/App/Controller/Moderate.pm @@ -119,23 +119,32 @@ sub moderating_user_name { return $user->from_body ? $user->from_body->name : _('an administrator'); } -sub report_moderate_audit : Private { - my ($self, $c, @types) = @_; +sub moderate_log_entry : Private { + my ($self, $c, $object_type, @types) = @_; my $user = $c->user->obj; my $reason = $c->stash->{'moderation_reason'}; - my $problem = $c->stash->{problem} or die; + my $object = $object_type eq 'update' ? $c->stash->{comment} : $c->stash->{problem}; my $types_csv = join ', ' => @types; + # We attach the log to the moderation entry if present, or the object if not (hiding) $c->model('DB::AdminLog')->create({ action => 'moderation', user => $user, admin_user => moderating_user_name($user), - object_id => $problem->id, - object_type => 'problem', + object_id => $c->stash->{history}->id || $object->id, + object_type => $c->stash->{history}->id ? 'moderation' : $object_type, reason => (sprintf '%s (%s)', $reason, $types_csv), }); +} + +sub report_moderate_audit : Private { + my ($self, $c, @types) = @_; + + my $problem = $c->stash->{problem} or die; + + $c->forward('moderate_log_entry', [ 'problem', @types ]); if ($problem->user->email_verified && $c->cobrand->send_moderation_notifications) { my $token = $c->model("DB::Token")->create({ @@ -143,6 +152,7 @@ sub report_moderate_audit : Private { data => { id => $problem->id } }); + my $types_csv = join ', ' => @types; $c->send_email( 'problem-moderated.txt', { to => [ [ $problem->user->email, $problem->name ] ], types => $types_csv, @@ -316,27 +326,7 @@ sub moderate_update : Chained('update') : PathPart('') : Args(0) { $c->forward('moderate_extra'), $c->forward('moderate_boolean', [ 'photo' ]); - $c->detach( 'update_moderate_audit', \@types ) -} - -sub update_moderate_audit : Private { - my ($self, $c, @types) = @_; - - my $user = $c->user->obj; - my $reason = $c->stash->{'moderation_reason'}; - my $problem = $c->stash->{problem} or die; - my $comment = $c->stash->{comment} or die; - - my $types_csv = join ', ' => @types; - - $c->model('DB::AdminLog')->create({ - action => 'moderation', - user => $user, - admin_user => moderating_user_name($user), - object_id => $comment->id, - object_type => 'update', - reason => (sprintf '%s (%s)', $reason, $types_csv), - }); + $c->detach('moderate_log_entry', [ 'update', @types ]); } sub update_moderate_hide : Private { @@ -347,7 +337,7 @@ sub update_moderate_hide : Private { if ($c->get_param('update_hide')) { $comment->hide; - $c->detach( 'update_moderate_audit', ['hide'] ); # break chain here. + $c->detach('moderate_log_entry', [ 'update', 'hide' ]); # break chain here. } return; } diff --git a/perllib/FixMyStreet/DB/Result/Comment.pm b/perllib/FixMyStreet/DB/Result/Comment.pm index 3a2b7d84b..31e9f3e63 100644 --- a/perllib/FixMyStreet/DB/Result/Comment.pm +++ b/perllib/FixMyStreet/DB/Result/Comment.pm @@ -102,6 +102,7 @@ use FixMyStreet::Template; with 'FixMyStreet::Roles::Abuser', 'FixMyStreet::Roles::Extra', + 'FixMyStreet::Roles::Moderation', 'FixMyStreet::Roles::PhotoSet'; my $stz = sub { @@ -176,17 +177,6 @@ sub url { return "/report/" . $self->problem_id . '#update_' . $self->id; } -=head2 latest_moderation_log_entry - -Return most recent ModerationLog object - -=cut - -sub latest_moderation_log_entry { - my $self = shift; - return $self->admin_log_entries->search({ action => 'moderation' }, { order_by => { -desc => 'id' } })->first; -} - __PACKAGE__->has_many( "admin_log_entries", "FixMyStreet::DB::Result::AdminLog", @@ -197,13 +187,6 @@ __PACKAGE__->has_many( } ); -sub moderation_history { - my $self = shift; - return $self->moderation_original_datas->search({ - problem_id => $self->problem_id, - }, { order_by => { -desc => 'id' } })->all; -} - # This will return the oldest moderation_original_data, if any. # The plural can be used to return all entries. __PACKAGE__->might_have( @@ -217,6 +200,11 @@ __PACKAGE__->might_have( cascade_copy => 0, cascade_delete => 1 }, ); +sub moderation_filter { + my $self = shift; + { problem_id => $self->problem_id }; +} + =head2 meta_line Returns a string to be used on a report update, describing some of the metadata diff --git a/perllib/FixMyStreet/DB/Result/ModerationOriginalData.pm b/perllib/FixMyStreet/DB/Result/ModerationOriginalData.pm index 42ff75295..01ae1d6e1 100644 --- a/perllib/FixMyStreet/DB/Result/ModerationOriginalData.pm +++ b/perllib/FixMyStreet/DB/Result/ModerationOriginalData.pm @@ -78,6 +78,16 @@ with 'FixMyStreet::Roles::Extra'; __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); __PACKAGE__->rabx_column('extra'); +sub admin_log { + my $self = shift; + my $rs = $self->result_source->schema->resultset("AdminLog"); + my $log = $rs->search({ + object_id => $self->id, + object_type => 'moderation', + })->first; + return $log; +} + sub compare_with { my ($self, $other) = @_; if ($self->comment_id) { diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index a7884f7d2..a222ea1f6 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -210,6 +210,7 @@ my $IM = eval { with 'FixMyStreet::Roles::Abuser', 'FixMyStreet::Roles::Extra', + 'FixMyStreet::Roles::Moderation', 'FixMyStreet::Roles::Translatable', 'FixMyStreet::Roles::PhotoSet'; @@ -962,24 +963,6 @@ sub as_hashref { return $out; } -=head2 latest_moderation_log_entry - -Return most recent ModerationLog object - -=cut - -sub latest_moderation_log_entry { - my $self = shift; - return $self->admin_log_entries->search({ action => 'moderation' }, { order_by => { -desc => 'id' } })->first; -} - -sub moderation_history { - my $self = shift; - return $self->moderation_original_datas->search({ - comment_id => undef, - }, { order_by => { -desc => 'id' } })->all; -} - __PACKAGE__->has_many( "admin_log_entries", "FixMyStreet::DB::Result::AdminLog", @@ -990,6 +973,11 @@ __PACKAGE__->has_many( } ); +sub moderation_filter { + my $self = shift; + { comment_id => undef }; +} + sub get_time_spent { my $self = shift; my $admin_logs = $self->admin_log_entries->search({}, diff --git a/perllib/FixMyStreet/Roles/Moderation.pm b/perllib/FixMyStreet/Roles/Moderation.pm new file mode 100644 index 000000000..f43b65208 --- /dev/null +++ b/perllib/FixMyStreet/Roles/Moderation.pm @@ -0,0 +1,41 @@ +package FixMyStreet::Roles::Moderation; +use Moo::Role; + +=head2 latest_moderation_log_entry + +Return most recent AdminLog object concerning moderation + +=cut + +sub latest_moderation_log_entry { + my $self = shift; + + my $latest = $self->moderation_original_datas->search( + $self->moderation_filter, + { order_by => { -desc => 'id' } })->first; + return unless $latest; + + my $rs = $self->result_source->schema->resultset("AdminLog"); + my $log = $rs->search({ + object_id => $latest->id, + object_type => 'moderation', + })->first; + return $log if $log; + + return $self->admin_log_entries->search({ action => 'moderation' }, { order_by => { -desc => 'id' } })->first; +} + +=head2 moderation_history + +Returns all moderation history, most recent first. + +=cut + +sub moderation_history { + my $self = shift; + return $self->moderation_original_datas->search( + $self->moderation_filter, + { order_by => { -desc => 'id' } })->all; +} + +1; diff --git a/templates/web/base/admin/report_edit.html b/templates/web/base/admin/report_edit.html index a38bacb00..175863549 100644 --- a/templates/web/base/admin/report_edit.html +++ b/templates/web/base/admin/report_edit.html @@ -190,7 +190,9 @@ class="admin-offsite-link">[% problem.latitude %], [% problem.longitude %]</a> <ul> [% FOR history IN moderation_history %] [% SET diff = history.compare_with(last_history) %] - <li>[% PROCESS format_time time=history.created %]: + [% SET log = history.admin_log %] + <li><i>[% tprintf(loc('Moderated by %s at %s'), log.user.name OR loc('an administrator'), prettify_dt(history.created)) %] + [%~ IF log.reason %]<br>“[% log.reason %]”[% END %]</i> [% IF diff.title %]<br>[% loc('Subject:') %] [% diff.title %][% END %] [% IF diff.detail %]<br>[% loc('Details:') %] [% diff.detail %][% END %] [% IF diff.photo %]<br>[% loc('Photo') %]: [% diff.photo %][% END %] diff --git a/templates/web/base/admin/update_edit.html b/templates/web/base/admin/update_edit.html index d997b89e8..fca9b1904 100644 --- a/templates/web/base/admin/update_edit.html +++ b/templates/web/base/admin/update_edit.html @@ -88,7 +88,9 @@ <ul> [% FOR history IN moderation_history %] [% SET diff = history.compare_with(last_history) %] - <li>[% PROCESS format_time time=history.created %]: + [% SET log = history.admin_log %] + <li><i>[% tprintf(loc('Moderated by %s at %s'), log.user.name OR loc('an administrator'), prettify_dt(history.created)) %] + [%~ IF log.reason %]<br>“[% log.reason %]”[% END %]</i> [% IF diff.detail %]<br>[% loc('Text:') %] [% diff.detail %][% END %] [% IF diff.photo %]<br>[% loc('Photo') %]: [% diff.photo %][% END %] [% IF diff.anonymous %]<br>[% loc('Anonymous:') %] [% diff.anonymous %][% END %] |