def test_filter_simple_object_permission(self) -> None: product = Product.objects.create() add_perms_shortcut(self.user, product, "r") queryset = filter_queryset_by_perms_shortcut( "r", self.user, Product.objects.all() ) self.assertEqual(queryset.count(), 1)
def clear(request): shell("python3 manage.py flush --no-input") cache.clear() reset_permissions([Product, Brand]) add_perms_shortcut(default_groups.anyone, Product, "rwcd") add_perms_shortcut(default_groups.anyone, Brand, "rwcd") return HttpResponse("Successfully deleted all.")
def test_object_perm_implies_field_perm(self) -> None: product = Product.objects.create() add_perms_shortcut(self.user, product, "r") queryset = filter_queryset_by_perms_shortcut( "r", self.user, Product.objects.all(), field_name="barcode" ) self.assertEqual(queryset.count(), 1)
def test_simple_object_permission_multiple_fields(self) -> None: add_perms_shortcut(self.user, self.product, "rwcd", field_name="barcode") self.assertEqual(UserObjectPermission.objects.count(), 4) for uop in UserObjectPermission.objects.all(): self.assertEqual(uop.user, self.user) self.assertEqual(uop.content_object, self.product) self.assertEqual(uop.permission.field_name, "barcode")
def test_model_perm_implies_object_perm(self) -> None: Product.objects.create() add_perms_shortcut(self.user, Product, "rw") queryset = filter_queryset_by_perms_shortcut( "r", self.user, Product.objects.all() ) self.assertEqual(queryset.count(), 1)
def test_get_only_parent_permission_correct_reverse_perm_ver_2(self) -> None: p.add_perms_shortcut(self.user, Product, "r") p.add_perms_shortcut(self.user, Brand, "r") resp = self.user_client.get(f"/product/{self.pr1.id}/brand") self.assertEqual(200, resp.status_code, resp.content) data = resp.json() self.assertDictContainsSubset({"id": str(self.br1.id), "name": "br1"}, data)
def test_correct_parent_incorrect_reverse_perms_get(self) -> None: p.add_perms_shortcut(self.user, Brand, "r", field_name="products") p.add_perms_shortcut(self.user, Product, "wcd") resp = self.user_client.get(f"/brand/{self.brand.id}/products") data = resp.json() self.assertEquals(0, data["objects_count"]) self.assertEquals(len(data["objects"]), 0)
def test_when_multiple_perms_with_fields_assigned(self) -> None: product = Product.objects.create() add_perms_shortcut(self.user, product, "rwc", field_name="barcode") queryset = filter_queryset_by_perms_shortcut( "rw", self.user, Product.objects.all(), field_name="barcode" ) self.assertEqual(queryset.count(), 1)
def patch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: # permission check deferred to .perform_update() instance = self.model_object has_read_permissions = False if p.has_perms_shortcut(self.user_object, instance, "r"): has_read_permissions = True serializer = self.get_serializer( instance=instance, data=self.request_data, partial=True, ) serializer.is_valid(raise_exception=True) # User must have write permission on the field being modified. for field_name, field_val in serializer.validated_data.items(): # Note that in case field_name is a foreign key, there are two # cases: # 1. brand # 2. brand_id # If the field_name is brand then field_val is usually a brand # object. If the field name is brand_id, then field val is UUID. field = self.get_model_field(field_name) if not field: continue # For foreign keys, user must have 3-way permissions. See # .check_3way_permissions(). if isinstance(field, ForeignKey): field_name = field.name # this removes "_id" if isinstance(field_val, DCFModel): field_val_pk = field_val.pk else: field_val_pk = field_val new_related_obj: QuerySet = QuerySet(model=field.related_model).filter( pk=field_val_pk ) if not new_related_obj.exists(): raise e.NotFound(f"Related object {field_val_pk} does not exist.") self.check_3way_permissions( self.user_object, self.model_object, field_name, new_related_obj, "w", ) elif not p.has_perms_shortcut( self.user_object, self.model_object, "w", field_name ): raise APIPermissionDenied(self.model_object, "w", field=field_name) # when permited serializer.save() if has_read_permissions: p.add_perms_shortcut(self.user_object, instance, "r") if p.has_perms_shortcut(self.user_object, instance, "r"): return Response( self.get_serializer(instance=instance).data, status=200, ) else: raise UpdatedHiddenObject()
def test_post_read_create_permissions(self) -> None: p.add_perms_shortcut(self.user, Product, "rc") resp = self.user_client.post("/product", {"barcode": "pr3"}) data = resp.json() self.assertDictContainsSubset({ "barcode": "pr3", "brand_id": None }, data)
def test_patch_incorrect_permission(self) -> None: p.add_perms_shortcut(self.user, Product, "rcd") resp = self.user_client.patch( f"/product/{self.pr1.id}/brand", data=self.br2.id, format="json", ) self.assertEqual(403, resp.status_code, resp.content)
def test_patch_wrong_field(self) -> None: p.add_perms_shortcut(self.user, Product, "w", field_name="brand_id") resp = self.user_client.patch( f"/product/{self.pr1.id}", {"barcode": "xxxxx"}, format="json", ) self.assertEquals(404, resp.status_code)
def test_patch_incorrect_permissions(self) -> None: p.add_perms_shortcut(self.user, Product, "rcd") resp = self.user_client.patch( f"/product/{self.pr1.id}", {"barcode": "p1"}, format="json", ) self.assertEquals(403, resp.status_code)
def test_only_parent_permissions_get_2(self) -> None: p.add_perms_shortcut(self.user, Brand, "r", field_name="products") p.add_perms_shortcut(self.user, self.products[2], "r") resp = self.user_client.get(f"/brand/{self.brand.id}/products") data = resp.json() objects = data["objects"] self.assertEquals(len(objects), 1) self.assertDictContainsSubset({"barcode": "product_3"}, objects[0])
def test_patch_only_parent_permission(self) -> None: p.add_perms_shortcut(self.user, Product, "w") resp = self.user_client.patch( f"/product/{self.pr1.id}/brand", data=self.br2.id, format="json", ) self.assertEqual(404, resp.status_code)
def test_post_correct_parent_perms(self) -> None: p.add_perms_shortcut(self.user, Brand, "w", field_name="products") resp = self.user_client.post( f"/brand/{self.brand.id}/products", data=[self.product.id], format="json", ) self.assertEquals(404, resp.status_code)
def test_incorrect_permissions(self) -> None: p.add_perms_shortcut(self.user, Product, "wcd") resp = self.user_client.get("/product") data = resp.json() self.assertDictContainsSubset({ "objects_count": 0, "objects": [] }, data) self.assertEqual(resp.status_code, 200)
def test_post_with_fk_without_read(self) -> None: """Post FK without read permission. The API should hide the existence of the FK object by responding 404.""" p.add_perms_shortcut(self.user, Product, "c") resp = self.user_client.post("/product", { "barcode": "pr3", "brand_id": str(self.br1.id) }) self.assertEquals(resp.status_code, 404)
def test_post_with_fk_incorrect_perm(self) -> None: """""" p.add_perms_shortcut(self.user, Product, "c") p.add_perms_shortcut(self.user, Brand, "rcd") resp = self.user_client.post("/product", { "barcode": "pr3", "brand_id": str(self.br1.id) }) self.assertEquals(resp.status_code, 403)
def test_patch_parent_but_incorrect_related_perms(self) -> None: p.add_perms_shortcut(self.user, Product, "w") p.add_perms_shortcut(self.user, Brand, "rcd") resp = self.user_client.patch( f"/product/{self.pr1.id}/brand", data=self.br2.id, format="json", ) self.assertEqual(403, resp.status_code)
def test_filter_multiple_objects_permission(self) -> None: for _ in range(4): product = Product.objects.create() add_perms_shortcut(self.user, product, "r") for _ in range(6): product = Product.objects.create() queryset = filter_queryset_by_perms_shortcut( "r", self.user, Product.objects.all() ) self.assertEqual(queryset.count(), 4)
def test_patch_fk_no_permissions_except_product_w(self) -> None: p.add_perms_shortcut(self.user, Product, "w", field_name="brand") resp = self.user_client.patch( f"/product/{self.pr1.id}", { "brand_id": str(self.br2.id), }, format="json", ) self.assertEquals(404, resp.status_code)
def test_get_correct_permissions(self) -> None: p.add_perms_shortcut(self.user, Product, "r") resp = self.user_client.get(f"/product/{self.pr1.id}") self.assertDictContainsSubset( { "id": str(self.pr1.id), "barcode": "pr1", "brand_id": str(self.br1.id) }, resp.json(), )
def test_correct_patch_perms_can_read(self) -> None: p.add_perms_shortcut(self.user, Brand, "rw") p.add_perms_shortcut(self.user, Product, "rw") resp = self.user_client.patch( f"/product/{self.pr1.id}/brand", data=self.br2.id, format="json", ) self.pr1.refresh_from_db() self.assertEqual(self.br2, self.pr1.brand) self.assertDictContainsSubset({"id": str(self.br2.id)}, resp.json())
def test_patch_fk_incorrect_perms(self) -> None: p.add_perms_shortcut(self.user, Product, "w", field_name="brand") p.add_perms_shortcut(self.user, Brand, "rcd") resp = self.user_client.patch( f"/product/{self.pr1.id}", data={ "brand_id": str(self.br2.id), }, format="json", ) self.assertEquals(403, resp.status_code, resp.content)
def test_post_foreignkey(self) -> None: p.add_perms_shortcut(self.user, Product, "rc") p.add_perms_shortcut(self.user, Brand, "w") resp = self.user_client.post("/product", { "barcode": "pr3", "brand_id": str(self.br1.id) }) data = resp.json() self.assertDictContainsSubset( { "barcode": "pr3", "brand_id": str(self.br1.id) }, data)
def test_get_all_with_model_permissions(self) -> None: p.add_perms_shortcut(self.user, Product, "r") resp = self.user_client.get("/product") data = resp.json() self.assertDictContainsSubset( { "page": 1, "limit": 50, "objects_count": 2 }, data) objects = data["objects"] self.assertEqual(len(objects), 2)
def test_post_only_create_permissions(self) -> None: """You can create by can't see""" p.add_perms_shortcut(self.user, Product, "c") resp = self.user_client.post("/product", {"barcode": "pr3"}) data = resp.json() self.assertDictContainsSubset( { "message": "The object has been created but you have no permission to view it.", "code": "success_hidden", }, data, )
def test_correct_patch_perms_no_read_v2(self) -> None: p.add_perms_shortcut(self.user, Product, "w") p.add_perms_shortcut(self.user, Brand, "wr") resp = self.user_client.patch( f"/product/{self.pr1.id}/brand", data=self.br2.id, format="json", ) self.pr1.refresh_from_db() self.assertEqual(self.br2, self.pr1.brand) self.assertEqual(resp.status_code, 200) self.assertContains( resp, "Action was successful but you have no permission to view the result." )
def test_no_parent_perm(self) -> None: """ Has no brand perm, should 404. """ p.add_perms_shortcut(self.user, self.product, "w", field_name="brand") p.add_perms_shortcut(self.user, self.product, "r") resp = self.user_client.post( f"/brand/{self.brand.id}/products", data=[self.product.id], format="json", ) self.assertEquals(404, resp.status_code) self.assertEqual(f"Not Found: brand({self.brand.id})", resp.json()) self.assertIsNone(self.product.brand_id) # product is not updated self.assertEqual(0, self.brand.products.count()) # product is not updated