strawberry-django-plus icon indicating copy to clipboard operation
strawberry-django-plus copied to clipboard

unable to resolve object permissions on objects with integer primary keys using Postgres

Open zacatac opened this issue 2 years ago • 3 comments

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 } }
}

zacatac avatar Aug 25 '22 00:08 zacatac

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

zacatac avatar Aug 25 '22 00:08 zacatac

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?

bellini666 avatar Aug 25 '22 13:08 bellini666

hey @bellini666. Totally agree that introspecting on object_pk. The django-guardian lib handles that introspection here.

zacatac avatar Aug 26 '22 17:08 zacatac