aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet')
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm84
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm83
-rw-r--r--perllib/FixMyStreet/Cobrand/UKCouncils.pm37
3 files changed, 177 insertions, 27 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index ea8633db0..17425ad77 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -669,6 +669,13 @@ sub report_edit : Path('report_edit') : Args(1) {
$c->detach( '/page_error_404_not_found' )
unless $problem;
+ unless (
+ $c->cobrand->moniker eq 'zurich'
+ || $c->user->has_permission_to(report_edit => $problem->bodies_str)
+ ) {
+ $c->detach( '/page_error_403_access_denied', [] );
+ }
+
$c->stash->{problem} = $problem;
$c->forward('/auth/get_csrf_token');
@@ -913,7 +920,7 @@ sub users: Path('users') : Args(0) {
my $search_n = 0;
$search_n = int($search) if $search =~ /^\d+$/;
- my $users = $c->model('DB::User')->search(
+ my $users = $c->cobrand->users->search(
{
-or => [
email => { ilike => $isearch },
@@ -945,7 +952,7 @@ sub users: Path('users') : Args(0) {
$c->forward('fetch_all_bodies');
# Admin users by default
- my $users = $c->model('DB::User')->search(
+ my $users = $c->cobrand->users->search(
{ from_body => { '!=', undef } },
{ order_by => 'name' }
);
@@ -1113,9 +1120,19 @@ sub user_edit : Path('user_edit') : Args(1) {
$c->forward('/auth/get_csrf_token');
- my $user = $c->model('DB::User')->find( { id => $id } );
+ my $user = $c->cobrand->users->find( { id => $id } );
+ $c->detach( '/page_error_404_not_found' ) unless $user;
+
+ unless ( $c->user->is_superuser || ( $c->user->has_permission_to('user_edit', $c->user->from_body->id) ) ) {
+ $c->detach('/page_error_403_access_denied', []);
+ }
+
$c->stash->{user} = $user;
+ if ( $user->from_body && $c->user->has_permission_to('user_manage_permissions', $user->from_body->id) ) {
+ $c->stash->{available_permissions} = $c->cobrand->available_permissions;
+ }
+
$c->forward('fetch_all_bodies');
if ( $c->get_param('submit') ) {
@@ -1126,7 +1143,7 @@ sub user_edit : Path('user_edit') : Args(1) {
if ( $user->email ne $c->get_param('email') ||
$user->name ne $c->get_param('name') ||
($user->phone || "") ne $c->get_param('phone') ||
- ($user->from_body && $user->from_body->id ne $c->get_param('body')) ||
+ ($user->from_body && $c->get_param('body') && $user->from_body->id ne $c->get_param('body')) ||
(!$user->from_body && $c->get_param('body'))
) {
$edited = 1;
@@ -1135,10 +1152,37 @@ sub user_edit : Path('user_edit') : Args(1) {
$user->name( $c->get_param('name') );
$user->email( $c->get_param('email') );
$user->phone( $c->get_param('phone') ) if $c->get_param('phone');
- $user->from_body( $c->get_param('body') || undef );
$user->flagged( $c->get_param('flagged') || 0 );
# Only superusers can grant superuser status
$user->is_superuser( ( $c->user->is_superuser && $c->get_param('is_superuser') ) || 0 );
+ # Superusers can set from_body to any value, but other staff can only
+ # set from_body to the same value as their own from_body.
+ if ( $c->user->is_superuser ) {
+ $user->from_body( $c->get_param('body') || undef );
+ } elsif ( $c->user->has_permission_to('user_assign_body', $c->user->from_body->id ) &&
+ $c->get_param('body') && $c->get_param('body') eq $c->user->from_body->id ) {
+ $user->from_body( $c->user->from_body );
+ } else {
+ $user->from_body( undef );
+ }
+
+ if (!$user->from_body) {
+ # Non-staff users aren't allowed any permissions
+ $user->user_body_permissions->delete_all;
+ } elsif ($c->stash->{available_permissions}) {
+ my @all_permissions = map { keys %$_ } values %{ $c->stash->{available_permissions} };
+ my @user_permissions = grep { $c->get_param("permissions[$_]") ? 1 : undef } @all_permissions;
+ $user->user_body_permissions->search({
+ body_id => $user->from_body->id,
+ permission_type => { '!=' => \@user_permissions },
+ })->delete;
+ foreach my $permission_type (@user_permissions) {
+ $user->user_body_permissions->find_or_create({
+ body_id => $user->from_body->id,
+ permission_type => $permission_type,
+ });
+ }
+ }
unless ($user->email) {
$c->stash->{field_errors}->{email} = _('Please enter a valid email');
@@ -1229,7 +1273,13 @@ sub stats_fix_rate : Path('stats/fix-rate') : Args(0) {
sub stats : Path('stats') : Args(0) {
my ( $self, $c ) = @_;
- $c->forward('fetch_all_bodies');
+ my $selected_body;
+ if ( $c->user->is_superuser ) {
+ $c->forward('fetch_all_bodies');
+ $selected_body = $c->get_param('body');
+ } else {
+ $selected_body = $c->user->from_body->id;
+ }
if ( $c->cobrand->moniker eq 'seesomething' || $c->cobrand->moniker eq 'zurich' ) {
return $c->cobrand->admin_stats();
@@ -1259,7 +1309,7 @@ sub stats : Path('stats') : Args(0) {
my $bymonth = $c->get_param('bymonth');
$c->stash->{bymonth} = $bymonth;
- $c->stash->{selected_body} = $c->get_param('body');
+ $c->stash->{selected_body} = $selected_body;
my $field = 'confirmed';
@@ -1288,7 +1338,7 @@ sub stats : Path('stats') : Args(0) {
);
}
- my $p = $c->cobrand->problems->to_body($c->get_param('body'))->search(
+ my $p = $c->cobrand->problems->to_body($selected_body)->search(
{
-AND => [
$field => { '>=', $start_date},
@@ -1318,24 +1368,6 @@ sub set_allowed_pages : Private {
my $pages = $c->cobrand->admin_pages;
- if( !$pages ) {
- $pages = {
- 'summary' => [_('Summary'), 0],
- 'bodies' => [_('Bodies'), 1],
- 'reports' => [_('Reports'), 2],
- 'timeline' => [_('Timeline'), 3],
- 'users' => [_('Users'), 5],
- 'flagged' => [_('Flagged'), 6],
- 'stats' => [_('Stats'), 7],
- 'config' => [ _('Configuration'), 8],
- 'user_edit' => [undef, undef],
- 'body' => [undef, undef],
- 'report_edit' => [undef, undef],
- 'update_edit' => [undef, undef],
- 'abuse_edit' => [undef, undef],
- }
- }
-
my @allowed_links = sort {$pages->{$a}[1] <=> $pages->{$b}[1]} grep {$pages->{$_}->[0] } keys %$pages;
$c->stash->{allowed_pages} = $pages;
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm
index 686684a05..043d0b8e6 100644
--- a/perllib/FixMyStreet/Cobrand/Default.pm
+++ b/perllib/FixMyStreet/Cobrand/Default.pm
@@ -140,6 +140,30 @@ sub problems_on_map_restriction {
return $rs;
}
+=head1 users
+
+Returns a ResultSet of Users, potentially restricted to a subset if we're on
+a cobrand that only wants some of the data.
+
+=cut
+
+sub users {
+ my $self = shift;
+ return $self->users_restriction($self->{c}->model('DB::User'));
+}
+
+=head1 users_restriction
+
+Used to restricts users in the admin in a cobrand in a particular way. Do
+nothing by default.
+
+=cut
+
+sub users_restriction {
+ my ($self, $rs) = @_;
+ return $rs;
+}
+
sub site_key { return 0; }
=head2 restriction
@@ -613,7 +637,33 @@ List of names of pages to display on the admin interface
=cut
-sub admin_pages { 0 }
+sub admin_pages {
+ my $self = shift;
+
+ my $user = $self->{c}->user;
+
+ my $pages = {
+ 'summary' => [_('Summary'), 0],
+ 'bodies' => [_('Bodies'), 1],
+ 'reports' => [_('Reports'), 2],
+ 'timeline' => [_('Timeline'), 3],
+ 'users' => [_('Users'), 5],
+ 'flagged' => [_('Flagged'), 6],
+ 'stats' => [_('Stats'), 7],
+ 'user_edit' => [undef, undef],
+ 'body' => [undef, undef],
+ 'report_edit' => [undef, undef],
+ 'update_edit' => [undef, undef],
+ 'abuse_edit' => [undef, undef],
+ };
+
+ # There are some pages that only super users can see
+ if ( $user->is_superuser ) {
+ $pages->{config} = [ _('Configuration'), 8];
+ };
+
+ return $pages;
+}
=head2 admin_show_creation_graph
@@ -634,6 +684,37 @@ sub admin_allow_user {
return 1 if $user->is_superuser;
}
+=head2 available_permissions
+
+Grouped lists of permission types available for use in the admin
+
+=cut
+
+sub available_permissions {
+ my $self = shift;
+
+ return {
+ _("Problems") => {
+ moderate => _("Moderate report details"),
+ report_edit => _("Edit reports"),
+ report_edit_category => _("Edit report category"), # future use
+ report_edit_priority => _("Edit report priority"), # future use
+ report_inspect => _("Markup problem details"),
+ report_instruct => _("Instruct contractors to fix problems"), # future use
+ planned_reports => _("Manage planned reports list"),
+ contribute_as_another_user => _("Create reports/updates on a user's behalf"),
+ contribute_as_body => _("Create reports/updates as the council"),
+ },
+ _("Users") => {
+ user_edit => _("Edit other users' details"),
+ user_manage_permissions => _("Edit other users' permissions"),
+ user_assign_body => _("Grant access to the admin"),
+ user_assign_areas => _("Assign users to areas"), # future use
+ },
+ };
+}
+
+
=head2 area_types
The MaPit types this site handles
diff --git a/perllib/FixMyStreet/Cobrand/UKCouncils.pm b/perllib/FixMyStreet/Cobrand/UKCouncils.pm
index 43f10130a..5d72c4962 100644
--- a/perllib/FixMyStreet/Cobrand/UKCouncils.pm
+++ b/perllib/FixMyStreet/Cobrand/UKCouncils.pm
@@ -50,6 +50,33 @@ sub updates_restriction {
return $rs->to_body($self->council_id);
}
+sub users_restriction {
+ my ($self, $rs) = @_;
+
+ # Council admins can only see users who are members of the same council or
+ # users who have sent a report or update to that council.
+
+ my $problem_user_ids = $self->problems->search(
+ undef,
+ {
+ columns => [ 'user_id' ],
+ distinct => 1
+ }
+ )->as_query;
+ my $update_user_ids = $self->updates->search(
+ undef,
+ {
+ columns => [ 'user_id' ],
+ distinct => 1
+ }
+ )->as_query;
+
+ return $rs->search([
+ from_body => $self->council_id,
+ id => [ { -in => $problem_user_ids }, { -in => $update_user_ids } ],
+ ]);
+}
+
sub base_url {
my $self = shift;
my $base_url = FixMyStreet->config('BASE_URL');
@@ -157,4 +184,14 @@ sub admin_allow_user {
return $user->from_body->id == $self->council_id;
}
+sub available_permissions {
+ my $self = shift;
+
+ my $perms = $self->next::method();
+ $perms->{Problems}->{contribute_as_body} = "Create reports/updates as " . $self->council_name;
+ $perms->{Users}->{user_assign_areas} = "Assign users to areas in " . $self->council_name;
+
+ return $perms;
+}
+
1;