def create(self, validated_data): users = [] if "users" in validated_data: users = validated_data.pop("users") address_data = validated_data.pop("address") address_data["country"] = address_data["country"].id address_serializer = AddressSerializer(data=address_data) if address_serializer.is_valid(raise_exception=True): address = Address(**address_serializer.validated_data) address.save() site = Site.objects.create(address=address, **validated_data) if users: site.users.set([ get_user_organisation_relationship( user, validated_data["organisation"]) for user in users ]) if "site_records_stored_here" in self.initial_data: if str_to_bool(self.initial_data.get("site_records_stored_here")): site.site_records_located_at = site site.save() return site
def test_cannot_assign_user_to_sites_it_doesnt_have_access_to(self): data = {"sites": [self.site_4.id]} response = self.client.put(self.url, data, **self.exporter_headers) user_organisation_relationship = get_user_organisation_relationship(self.exporter_user_2, self.organisation) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) self.assertEqual(user_organisation_relationship.sites.count(), 0)
def test_assign_sites(self): data = {"sites": [self.site_1.id, self.site_2.id]} response = self.client.put(self.url, data, **self.exporter_headers) user_organisation_relationship = get_user_organisation_relationship(self.exporter_user_2, self.organisation) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(user_organisation_relationship.sites.count(), len(data["sites"]))
def test_user_cannot_be_assigned_to_site_in_another_organisation(self): organisation_2 = OrganisationFactory() data = {"sites": [organisation_2.primary_site.id]} response = self.client.put(self.url, data, **self.exporter_headers) user_organisation_relationship = get_user_organisation_relationship(self.exporter_user_2, self.organisation) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) self.assertEqual(user_organisation_relationship.sites.count(), 0)
def test_user_cannot_assign_themselves_to_sites(self): data = {"sites": [self.site_1.id]} response = self.client.put( reverse_lazy("users:assign_sites", kwargs={"pk": self.exporter_user.pk}), data, **self.exporter_headers ) user_organisation_relationship = get_user_organisation_relationship(self.exporter_user, self.organisation) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(user_organisation_relationship.sites.count(), 3)
def test_user_cannot_be_assigned_to_sites_if_they_have_administer_sites_permission(self): user_organisation_relationship = get_user_organisation_relationship(self.exporter_user, self.organisation) user_organisation_relationship.role.permissions.set([ExporterPermissions.ADMINISTER_SITES.name]) data = {"sites": [self.site_1.id]} response = self.client.put( reverse_lazy("users:assign_sites", kwargs={"pk": self.exporter_user.pk}), data, **self.exporter_headers ) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(user_organisation_relationship.sites.count(), 3)
def test_assign_sites_doesnt_override_existing_sites(self): # Set up the second user with different sites to what exporter_user has user_organisation_relationship = get_user_organisation_relationship(self.exporter_user_2, self.organisation) user_organisation_relationship.sites.set([self.site_4, self.site_5]) data = {"sites": [self.site_1.id, self.site_2.id]} response = self.client.put(self.url, data, **self.exporter_headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(user_organisation_relationship.sites.count(), len(data["sites"]) + 2)
def get(self, request): org_pk = request.headers["ORGANISATION-ID"] user = request.user.exporteruser relationships = UserOrganisationRelationship.objects.select_related( "organisation").filter(user=user) if str_to_bool(request.GET.get("in_review", False)): relationships = relationships.filter( organisation__status=OrganisationStatus.IN_REVIEW) else: relationships = relationships.exclude( organisation__status=OrganisationStatus.IN_REVIEW) # Returning a dict over a serializer for performance reasons # This endpoint is called often, so it needs to be as fast as possible data = { "id": user.pk, "first_name": user.first_name, "last_name": user.last_name, "organisations": [{ "id": relationship.organisation.id, "name": relationship.organisation.name, "joined_at": date_to_drf_date(relationship.created_at), "status": { "key": relationship.organisation.status, "value": get_value_from_enum(relationship.organisation.status, OrganisationStatus), }, } for relationship in relationships], } if org_pk != "None": relationship = get_user_organisation_relationship(user, org_pk) data.update({ "role": { "id": relationship.role.id, "permissions": convert_queryset_to_str( relationship.role.permissions.values_list("id", flat=True)), } }) return JsonResponse(data=data)
def put(self, request, *args, **kwargs): # Ensure that the request user isn't the same as the user being acted upon if str(request.user.pk) == str(kwargs["pk"]): raise PermissionDenied() sites = request.data.get("sites", []) organisation = get_request_user_organisation(request) request_user_relationship = get_user_organisation_relationship( request.user.exporteruser, organisation) user_organisation_relationship = get_user_organisation_relationship( kwargs["pk"], organisation) # Get a list of all the sites that the request user has access to! request_user_sites = list( Site.objects.get_by_user_organisation_relationship( request_user_relationship)) user_sites = list( Site.objects.get_by_user_organisation_relationship( user_organisation_relationship)) diff_sites = [x for x in user_sites if x not in request_user_sites] combined_sites = diff_sites + sites # If (after the PUT) the user isn't assigned to any sites, raise an error if not combined_sites: raise serializers.ValidationError( {"sites": [Users.SELECT_AT_LEAST_ONE_SITE_ERROR]}) # Ensure user has access to the sites they're trying to assign the user to for site in sites: site = get_site(site, organisation) if site not in request_user_sites: raise NotFoundError( "You don't have access to the sites you're trying to assign the user to." ) user_organisation_relationship.sites.set(combined_sites) return JsonResponse(data={"status": "success"})
def setUp(self): super(AssignSitesTest, self).setUp() self.site_1 = SiteFactory(organisation=self.organisation) self.site_2 = SiteFactory(organisation=self.organisation) self.site_3 = SiteFactory(organisation=self.organisation) self.site_4 = SiteFactory(organisation=self.organisation) self.site_5 = SiteFactory(organisation=self.organisation) # Add default sites to the initial user user_organisation_relationship = get_user_organisation_relationship(self.exporter_user, self.organisation) user_organisation_relationship.sites.set([self.site_1, self.site_2, self.site_3]) self.exporter_user_2 = self.create_exporter_user(self.organisation) self.url = reverse_lazy("users:assign_sites", kwargs={"pk": self.exporter_user_2.pk})
def get(self, request, pk): """ Get user from pk """ user = get_user_by_pk(pk) organisation = get_request_user_organisation(request) if request.user.pk != pk: assert_user_has_permission(request.user.exporteruser, ExporterPermissions.ADMINISTER_USERS, organisation) relationship = get_user_organisation_relationship(user, organisation) serializer = ExporterUserViewSerializer(user, context=relationship) return JsonResponse(data={"user": serializer.data})
def test_ensure_user_cannot_see_applications_they_only_have_partial_access_to_(self): """ Ensure that the exporter cannot see applications with sites that they don't have access to AND sites that they are assigned to. """ relationship = get_user_organisation_relationship(self.exporter_user, self.organisation) relationship.sites.set([self.organisation.primary_site]) site_2 = SiteFactory(organisation=self.organisation) application = self.create_draft_standard_application(self.organisation) SiteOnApplication(site=site_2, application=application).save() response = self.client.get(self.url, **self.exporter_headers) response_data = response.json()["results"] self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response_data), 0)
def test_user_can_view_their_own_profile_info(self): """ Tests the 'users/me' endpoint Ensures that the endpoint returns the correct details about the signed in user """ response = self.client.get(reverse("users:me"), **self.exporter_headers) response_data = response.json() relationship = get_user_organisation_relationship( self.exporter_user, self.organisation) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual( response_data, { "id": str(self.exporter_user.pk), "first_name": self.exporter_user.first_name, "last_name": self.exporter_user.last_name, "organisations": [{ "id": str(relationship.organisation.id), "joined_at": date_to_drf_date(relationship.created_at), "name": relationship.organisation.name, "status": generate_key_value_pair(relationship.organisation.status, OrganisationStatus.choices), }], "role": { "id": str(relationship.role.id), "permissions": convert_queryset_to_str( relationship.role.permissions.values_list("id", flat=True)), }, }, )
def test_retrieve_sites_that_a_user_belongs_to(self): """ Ensure that the sites that a user is assigned to is returned when viewing their information """ user_organisation_relationship = get_user_organisation_relationship(self.exporter_user, self.organisation) user_organisation_relationship.sites.set([self.organisation.primary_site]) response = self.client.get( reverse("organisations:user", kwargs={"org_pk": self.organisation.id, "user_pk": self.exporter_user.pk}), **self.exporter_headers, ) site = response.json()["sites"][0] self.assertEquals( site["id"], str(self.organisation.primary_site.id), ) self.assertEquals( site["name"], str(self.organisation.primary_site.name), )
def get(self, request, org_pk, user_pk): """ Return a user from the specified organisation """ is_self = str(request.user.pk) == str(user_pk) if not is_self and hasattr(request.user, "exporteruser"): assert_user_has_permission(request.user.exporteruser, ExporterPermissions.ADMINISTER_USERS, org_pk) relationship = get_user_organisation_relationship(user_pk, org_pk) sites = Site.objects.get_by_user_organisation_relationship( relationship) return JsonResponse( data={ "id": relationship.user.pk, "first_name": relationship.user.first_name, "last_name": relationship.user.last_name, "email": relationship.user.email, "status": relationship.status, "role": RoleListSerializer(relationship.role).data, "sites": SiteListSerializer(sites, many=True).data, })
def get_by_user_and_organisation(self, exporter_user, organisation): exporter_user_relationship = get_user_organisation_relationship( exporter_user, organisation) return self.get_by_user_organisation_relationship( exporter_user_relationship)