strawberry-django-plus
strawberry-django-plus copied to clipboard
unable to resolve object permissions on objects with integer primary keys using Postgres
The issue flagged in this ancient django-guardian issue is rearing its head with the permissions checking with this package. The HasObjPerm
directive is generating SQL code which cannot be executed against Postgres because it is using the IN
operator without a typecast.
The django-guardian shortcuts library has handled this here, but it looks like this package is usingObjectPermissionChecker
directly.
exception
django.db.utils.ProgrammingError: operator does not exist: bigint = character varying
LINE 1: ...odename" = 'view_offer') LIMIT 1) OR "offer"."id" IN ((SELEC...
generated SQL
SELECT "offer"."id",
"organization"."id"
FROM "offer"
LEFT OUTER JOIN "organization"
ON ("offer"."organization_id" = "organization"."id")
WHERE (EXISTS(SELECT (1) AS "a" FROM "auth_permission" U0 INNER JOIN "auth_user_user_permissions" U1 ON (U0."id" = U1."permission_id") WHERE (U1."user_id" = 6 AND U0."content_type_id" = 26 AND U0."codename" = 'view_offer') LIMIT 1) OR EXISTS(SELECT (1) AS "a" FROM "auth_group" U0 INNER JOIN "auth_user_groups" U1 ON (U0."id" = U1."group_id") INNER JOIN "auth_group_permissions" U3 ON (U0."id" = U3."group_id") INNER JOIN "auth_permission" U4 ON (U3."permission_id" = U4."id") WHERE (U1."user_id" = 6 AND U4."content_type_id" = 26 AND U4."codename" = 'view_offer') LIMIT 1) OR "offer"."id" IN ((SELECT DISTINCT "guardian_userobjectpermission"."object_pk" FROM "guardian_userobjectpermission" INNER JOIN "auth_permission" ON ("guardian_userobjectpermission"."permission_id" = "auth_permission"."id") WHERE ("guardian_userobjectpermission"."user_id" = 6 AND "auth_permission"."content_type_id" = 26 AND "auth_permission"."codename" = 'view_offer' AND "guardian_userobjectpermission"."content_type_id" = ("auth_permission"."content_type_id"))) UNION (SELECT DISTINCT "guardian_groupobjectpermission"."object_pk" FROM "guardian_groupobjectpermission" INNER JOIN "auth_group" ON ("guardian_groupobjectpermission"."group_id" = "auth_group"."id") INNER JOIN "auth_user_groups" ON ("auth_group"."id" = "auth_user_groups"."group_id") INNER JOIN "auth_permission" ON ("guardian_groupobjectpermission"."permission_id" = "auth_permission"."id") WHERE ("auth_user_groups"."user_id" = 6 AND "auth_permission"."content_type_id" = 26 AND "auth_permission"."codename" = 'view_offer' AND "guardian_groupobjectpermission"."content_type_id" = ("auth_permission"."content_type_id")))))
models
class Organization(models.Model):
id = models.AutoField(primary_key=True)
class Offer(models.Model):
id = models.AutoField(primary_key=True)
organization = models.ForeignKey(Organization)
schema:
@gql.django.type(Organization)
class OrganizationType:
id: gql.auto
@gql.django.type(Offer, filters=OfferFilter, directives=[HasObjPerm("app.view_offer")])
class OfferType:
id: gql.auto
organization: "OrganizationType"
class Query:
offers: List[Optional[OfferType]] = gql.django.field(
directives=[IsAuthenticated()],
filters=OfferFilter,
)
query:
{
offers { id organization { id } }
}
This pull request works around this issue and hints at a more general fix. Don't know when I'll get the time to make a contribution back. https://github.com/zacatac/strawberry-django-plus/pull/1
Hey @zacatac ,
The fix seems fine, the only issue I see with it is that the object_pk
might not be an integer. For example, some people use UUIDField
for pks
Probably it would be nice to introspect the model at the time of doing that query and check which kind of field the pk is, and cast object_pk
to that kind. What do you think?
hey @bellini666. Totally agree that introspecting on object_pk
. The django-guardian lib handles that introspection here.