55from dataclasses import dataclass , field
66from enum import StrEnum
77from functools import wraps
8- from typing import ClassVar , Concatenate , ParamSpec , Protocol , TypeVar
8+ from typing import ClassVar , Concatenate , ParamSpec , Protocol , TypeVar , cast
99
1010from authzed .api .v1 import AsyncClient
1111from authzed .api .v1 .core_pb2 import ObjectReference , Relationship , RelationshipUpdate , SubjectReference , ZedToken
@@ -162,12 +162,12 @@ def all_users() -> ObjectReference:
162162 return ObjectReference (object_type = ResourceType .user , object_id = "*" )
163163
164164 @staticmethod
165- def group (id : str ) -> ObjectReference :
166- return ObjectReference (object_type = ResourceType .group , object_id = id )
165+ def group (id : ULID ) -> ObjectReference :
166+ return ObjectReference (object_type = ResourceType .group , object_id = str ( id ) )
167167
168168 @staticmethod
169- def user_namespace (id : str ) -> ObjectReference :
170- return ObjectReference (object_type = ResourceType .user_namespace , object_id = id )
169+ def user_namespace (id : ULID ) -> ObjectReference :
170+ return ObjectReference (object_type = ResourceType .user_namespace , object_id = str ( id ) )
171171
172172 @staticmethod
173173 def to_object (resource_type : ResourceType , resource_id : str | int ) -> ObjectReference :
@@ -178,9 +178,9 @@ def to_object(resource_type: ResourceType, resource_id: str | int) -> ObjectRefe
178178 return _AuthzConverter .user (sid )
179179 case (ResourceType .anonymous_user , _):
180180 return _AuthzConverter .anonymous_users ()
181- case (ResourceType .user_namespace , rid ) if isinstance (rid , str ):
181+ case (ResourceType .user_namespace , rid ) if isinstance (rid , ULID ):
182182 return _AuthzConverter .user_namespace (rid )
183- case (ResourceType .group , rid ) if isinstance (rid , str ):
183+ case (ResourceType .group , rid ) if isinstance (rid , ULID ):
184184 return _AuthzConverter .group (rid )
185185 raise errors .ProgrammingError (
186186 message = f"Unexpected or unknown resource type when checking permissions { resource_type } "
@@ -575,7 +575,7 @@ def _add_project(self, project: Project) -> _AuthzChange:
575575 object = (
576576 _AuthzConverter .user_namespace (project .namespace .id )
577577 if project .namespace .kind == NamespaceKind .user
578- else _AuthzConverter .group (project .namespace .underlying_resource_id )
578+ else _AuthzConverter .group (cast ( ULID , project .namespace .underlying_resource_id ) )
579579 )
580580 )
581581 project_in_platform = Relationship (
@@ -752,10 +752,14 @@ async def _update_project_namespace(
752752 else SubjectReference (object = _AuthzConverter .user_namespace (project .namespace .id ))
753753 )
754754 old_namespace_sub = (
755- SubjectReference (object = _AuthzConverter .group (current_namespace .relationship .subject .object .object_id ))
755+ SubjectReference (
756+ object = _AuthzConverter .group (ULID .from_str (current_namespace .relationship .subject .object .object_id ))
757+ )
756758 if current_namespace .relationship .subject .object .object_type == ResourceType .group .value
757759 else SubjectReference (
758- object = _AuthzConverter .user_namespace (current_namespace .relationship .subject .object .object_id )
760+ object = _AuthzConverter .user_namespace (
761+ ULID .from_str (current_namespace .relationship .subject .object .object_id )
762+ )
759763 )
760764 )
761765 new_namespace = Relationship (
@@ -1084,7 +1088,7 @@ async def _remove_group(
10841088 message = "Cannot remove a group in the authorization database if the group has no ID"
10851089 )
10861090 consistency = Consistency (at_least_as_fresh = zed_token ) if zed_token else Consistency (fully_consistent = True )
1087- rel_filter = RelationshipFilter (resource_type = ResourceType .group .value , optional_resource_id = group .id )
1091+ rel_filter = RelationshipFilter (resource_type = ResourceType .group .value , optional_resource_id = str ( group .id ) )
10881092 responses = self .client .ReadRelationships (
10891093 ReadRelationshipsRequest (consistency = consistency , relationship_filter = rel_filter )
10901094 )
@@ -1104,7 +1108,7 @@ async def upsert_group_members(
11041108 self ,
11051109 user : base_models .APIUser ,
11061110 resource_type : ResourceType ,
1107- resource_id : str ,
1111+ resource_id : ULID ,
11081112 members : list [Member ],
11091113 * ,
11101114 zed_token : ZedToken | None = None ,
@@ -1115,8 +1119,9 @@ async def upsert_group_members(
11151119 add_members : list [RelationshipUpdate ] = []
11161120 undo : list [RelationshipUpdate ] = []
11171121 output : list [MembershipChange ] = []
1122+ resource_id_str = str (resource_id )
11181123 expected_user_roles = {_Relation .viewer .value , _Relation .owner .value , _Relation .editor .value }
1119- existing_owners_rels = await self ._get_resource_owners (resource_type , resource_id , consistency )
1124+ existing_owners_rels = await self ._get_resource_owners (resource_type , resource_id_str , consistency )
11201125 n_existing_owners = len (existing_owners_rels )
11211126 for member in members :
11221127 rel = Relationship (
@@ -1126,7 +1131,7 @@ async def upsert_group_members(
11261131 )
11271132 existing_rel_filter = RelationshipFilter (
11281133 resource_type = resource_type .value ,
1129- optional_resource_id = resource_id ,
1134+ optional_resource_id = resource_id_str ,
11301135 optional_subject_filter = SubjectFilter (
11311136 subject_type = ResourceType .user , optional_subject_id = member .user_id
11321137 ),
@@ -1222,7 +1227,7 @@ async def remove_group_members(
12221227 self ,
12231228 user : base_models .APIUser ,
12241229 resource_type : ResourceType ,
1225- resource_id : str ,
1230+ resource_id : ULID ,
12261231 user_ids : list [str ],
12271232 * ,
12281233 zed_token : ZedToken | None = None ,
@@ -1233,12 +1238,13 @@ async def remove_group_members(
12331238 remove_members : list [RelationshipUpdate ] = []
12341239 output : list [MembershipChange ] = []
12351240 existing_owners_rels : list [ReadRelationshipsResponse ] | None = None
1241+ resource_id_str = str (resource_id )
12361242 for user_id in user_ids :
12371243 if user_id == "*" :
12381244 raise errors .ValidationError (message = "Cannot remove a group member with ID '*'" )
12391245 existing_rel_filter = RelationshipFilter (
12401246 resource_type = resource_type .value ,
1241- optional_resource_id = resource_id ,
1247+ optional_resource_id = resource_id_str ,
12421248 optional_subject_filter = SubjectFilter (subject_type = ResourceType .user , optional_subject_id = user_id ),
12431249 )
12441250 existing_rels : AsyncIterable [ReadRelationshipsResponse ] = self .client .ReadRelationships (
@@ -1249,7 +1255,9 @@ async def remove_group_members(
12491255 async for existing_rel in existing_rels :
12501256 if existing_rel .relationship .relation == _Relation .owner .value :
12511257 if existing_owners_rels is None :
1252- existing_owners_rels = await self ._get_resource_owners (resource_type , resource_id , consistency )
1258+ existing_owners_rels = await self ._get_resource_owners (
1259+ resource_type , resource_id_str , consistency
1260+ )
12531261 if len (existing_owners_rels ) == 1 :
12541262 raise errors .ValidationError (
12551263 message = "You are trying to remove the single last owner of the group, "
0 commit comments