Don’t allow editing of users from other services

Currently when you load the ‘edit user’ page (which has a URL like
`/service/<service_id>/users/<user_id>`) we check that:
- you belong to the service represented by `service_id`
- you have permission to edit users on this service

We don’t check that:
- the user represented by `user_id` belongs to this service

This means that if you could somehow determine another user’s `user_id`
(which I don’t think is possible if you don’t already have the manage
service permission for that service) then you could:
- edit their permissions on your service (weird, but wouldn’t have any
  effect)
- change their email address (bad)

This commit adds checks to return a `404` any time you’re looking at a
service and trying to do stuff to a user who doesn’t belong to that
service.

We can’t add this check to the API easily because there are still times
that we want to get/modify users outside the context of a service (eg
platform admin pages, or users who have no services).
This commit is contained in:
Chris Hill-Scott
2019-02-25 16:51:37 +00:00
parent 6ac713c978
commit d82f410325
5 changed files with 190 additions and 52 deletions

View File

@@ -98,13 +98,18 @@ class Service():
def has_jobs(self):
return job_api_client.has_jobs(self.id)
@cached_property
def invited_users(self):
return invite_api_client.get_invites_for_service(service_id=self.id)
@cached_property
def active_users(self):
return user_api_client.get_users_for_service(service_id=self.id)
@cached_property
def team_members(self):
return sorted(
(
invite_api_client.get_invites_for_service(service_id=self.id) +
user_api_client.get_users_for_service(service_id=self.id)
),
self.invited_users + self.active_users,
key=lambda user: user.email_address.lower(),
)
@@ -114,6 +119,23 @@ class Service():
self.id, 'manage_service'
) > 1
def cancel_invite(self, invited_user_id):
if str(invited_user_id) not in {user.id for user in self.invited_users}:
abort(404)
return invite_api_client.cancel_invited_user(
service_id=self.id,
invited_user_id=str(invited_user_id),
)
def get_team_member(self, user_id):
if str(user_id) not in {user.id for user in self.active_users}:
abort(404)
return user_api_client.get_user(user_id)
@cached_property
def all_templates(self):