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 1 year 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