@@ -408,7 +408,7 @@ func (e *engine) UpdateRole(ctx context.Context, actor, roleResource types.Resou
408
408
return types.Role {}, err
409
409
}
410
410
411
- err = e .store . LockRoleForUpdate (dbCtx , roleResource . ID )
411
+ err = e .lockRoleForUpdate (dbCtx , roleResource )
412
412
if err != nil {
413
413
sErr := fmt .Errorf ("failed to lock role: %s: %w" , roleResource .ID , err )
414
414
@@ -913,12 +913,18 @@ func (e *engine) ListRoles(ctx context.Context, resource types.Resource) ([]type
913
913
914
914
// listRoleResourceActions returns all resources and action relations for the provided resource type to the provided role.
915
915
// Note: The actions returned by this function are the spicedb relationship action.
916
- func (e * engine ) listRoleResourceActions (ctx context.Context , role types.Resource , resTypeName string ) (map [types.Resource ][]string , error ) {
917
- resType := e .namespace + "/" + resTypeName
916
+ func (e * engine ) listRoleResourceActions (ctx context.Context , role storage.Role ) ([]string , error ) {
917
+ roleOwnerResource , err := e .NewResourceFromID (role .ResourceID )
918
+ if err != nil {
919
+ return nil , err
920
+ }
921
+
922
+ resType := e .namespace + "/" + roleOwnerResource .Type
918
923
roleType := e .namespace + "/role"
919
924
920
925
filter := & pb.RelationshipFilter {
921
- ResourceType : resType ,
926
+ ResourceType : resType ,
927
+ OptionalResourceId : roleOwnerResource .ID .String (),
922
928
OptionalSubjectFilter : & pb.SubjectFilter {
923
929
SubjectType : roleType ,
924
930
OptionalSubjectId : role .ID .String (),
@@ -933,84 +939,47 @@ func (e *engine) listRoleResourceActions(ctx context.Context, role types.Resourc
933
939
return nil , err
934
940
}
935
941
936
- resourceIDActions := make (map [gidx. PrefixedID ][] string )
942
+ out := make ([] string , 0 , len ( relationships ) )
937
943
938
944
for _ , rel := range relationships {
939
- resourceID , err := gidx .Parse (rel .Resource .ObjectId )
940
- if err != nil {
941
- return nil , err
942
- }
943
-
944
- resourceIDActions [resourceID ] = append (resourceIDActions [resourceID ], rel .Relation )
945
- }
946
-
947
- resourceActions := make (map [types.Resource ][]string , len (resourceIDActions ))
948
-
949
- for resID , actions := range resourceIDActions {
950
- res , err := e .NewResourceFromID (resID )
951
- if err != nil {
952
- return nil , err
953
- }
945
+ action := relationToAction (rel .Relation )
954
946
955
- resourceActions [ res ] = actions
947
+ out = append ( out , action )
956
948
}
957
949
958
- return resourceActions , nil
950
+ return out , nil
959
951
}
960
952
961
- // GetRole gets the role with it's actions.
953
+ // GetRole gets the given role and its actions.
962
954
func (e * engine ) GetRole (ctx context.Context , roleResource types.Resource ) (types.Role , error ) {
963
- var (
964
- resActions map [types.Resource ][]string
965
- err error
966
- )
967
-
968
- for _ , resType := range e .schemaRoleables {
969
- resActions , err = e .listRoleResourceActions (ctx , roleResource , resType .Name )
970
- if err != nil {
971
- return types.Role {}, err
972
- }
973
-
974
- // roles are only ever created for a single resource, so we can break after the first one is found.
975
- if len (resActions ) != 0 {
976
- break
977
- }
955
+ dbRole , err := e .getStorageRole (ctx , roleResource )
956
+ if err != nil {
957
+ return types.Role {}, err
978
958
}
979
959
980
- if len (resActions ) > 1 {
981
- return types.Role {}, ErrRoleHasTooManyResources
960
+ actions , err := e .listRoleResourceActions (ctx , dbRole )
961
+ if err != nil {
962
+ return types.Role {}, err
982
963
}
983
964
984
- // returns the first resources actions.
985
- for _ , actions := range resActions {
986
- for i , action := range actions {
987
- actions [i ] = relationToAction (action )
988
- }
989
-
990
- dbRole , err := e .store .GetRoleByID (ctx , roleResource .ID )
991
- if err != nil && ! errors .Is (err , storage .ErrNoRoleFound ) {
992
- e .logger .Error ("error while getting role" , zap .Error (err ))
993
- }
965
+ out := types.Role {
966
+ ID : roleResource .ID ,
967
+ Name : dbRole .Name ,
968
+ Actions : actions ,
994
969
995
- return types.Role {
996
- ID : roleResource .ID ,
997
- Name : dbRole .Name ,
998
- Actions : actions ,
999
-
1000
- ResourceID : dbRole .ResourceID ,
1001
- CreatedBy : dbRole .CreatedBy ,
1002
- UpdatedBy : dbRole .UpdatedBy ,
1003
- CreatedAt : dbRole .CreatedAt ,
1004
- UpdatedAt : dbRole .UpdatedAt ,
1005
- }, nil
970
+ ResourceID : dbRole .ResourceID ,
971
+ CreatedBy : dbRole .CreatedBy ,
972
+ UpdatedBy : dbRole .UpdatedBy ,
973
+ CreatedAt : dbRole .CreatedAt ,
974
+ UpdatedAt : dbRole .UpdatedAt ,
1006
975
}
1007
976
1008
- return types. Role {}, ErrRoleNotFound
977
+ return out , nil
1009
978
}
1010
979
1011
980
// GetRoleResource gets the role's assigned resource.
1012
981
func (e * engine ) GetRoleResource (ctx context.Context , roleResource types.Resource ) (types.Resource , error ) {
1013
- dbRole , err := e .store . GetRoleByID (ctx , roleResource . ID )
982
+ dbRole , err := e .getStorageRole (ctx , roleResource )
1014
983
if err != nil {
1015
984
return types.Resource {}, err
1016
985
}
@@ -1029,7 +998,17 @@ func (e *engine) DeleteRole(ctx context.Context, roleResource types.Resource) er
1029
998
return err
1030
999
}
1031
1000
1032
- err = e .store .LockRoleForUpdate (dbCtx , roleResource .ID )
1001
+ dbRole , err := e .getStorageRole (ctx , roleResource )
1002
+ if err != nil {
1003
+ return err
1004
+ }
1005
+
1006
+ roleOwnerResource , err := e .NewResourceFromID (dbRole .ResourceID )
1007
+ if err != nil {
1008
+ return err
1009
+ }
1010
+
1011
+ err = e .lockRoleForUpdate (dbCtx , roleResource )
1033
1012
if err != nil {
1034
1013
sErr := fmt .Errorf ("failed to lock role: %s: %w" , roleResource .ID , err )
1035
1014
@@ -1041,20 +1020,11 @@ func (e *engine) DeleteRole(ctx context.Context, roleResource types.Resource) er
1041
1020
return err
1042
1021
}
1043
1022
1044
- var resActions map [types.Resource ][]string
1045
-
1046
- for _ , resType := range e .schemaRoleables {
1047
- resActions , err = e .listRoleResourceActions (ctx , roleResource , resType .Name )
1048
- if err != nil {
1049
- logRollbackErr (e .logger , e .store .RollbackContext (dbCtx ))
1050
-
1051
- return err
1052
- }
1023
+ actions , err := e .listRoleResourceActions (ctx , dbRole )
1024
+ if err != nil {
1025
+ logRollbackErr (e .logger , e .store .RollbackContext (dbCtx ))
1053
1026
1054
- // roles are only ever created for a single resource, so we can break after the first one is found.
1055
- if len (resActions ) != 0 {
1056
- break
1057
- }
1027
+ return err
1058
1028
}
1059
1029
1060
1030
roleType := e .namespace + "/role"
@@ -1069,15 +1039,16 @@ func (e *engine) DeleteRole(ctx context.Context, roleResource types.Resource) er
1069
1039
},
1070
1040
}
1071
1041
1072
- for resource , relActions := range resActions {
1073
- for _ , relAction := range relActions {
1074
- filters = append (filters , & pb.RelationshipFilter {
1075
- ResourceType : e .namespace + "/" + resource .Type ,
1076
- OptionalResourceId : resource .ID .String (),
1077
- OptionalRelation : relAction ,
1078
- OptionalSubjectFilter : roleSubjectFilter ,
1079
- })
1080
- }
1042
+ ownerType := e .namespace + "/" + roleOwnerResource .Type
1043
+ ownerIDStr := roleOwnerResource .ID .String ()
1044
+
1045
+ for _ , relAction := range actions {
1046
+ filters = append (filters , & pb.RelationshipFilter {
1047
+ ResourceType : ownerType ,
1048
+ OptionalResourceId : ownerIDStr ,
1049
+ OptionalRelation : relAction ,
1050
+ OptionalSubjectFilter : roleSubjectFilter ,
1051
+ })
1081
1052
}
1082
1053
1083
1054
_ , err = e .store .DeleteRole (dbCtx , roleResource .ID )
@@ -1229,3 +1200,29 @@ func (e *engine) applyUpdates(ctx context.Context, updates []*pb.RelationshipUpd
1229
1200
1230
1201
return nil
1231
1202
}
1203
+
1204
+ func (e * engine ) getStorageRole (ctx context.Context , roleResource types.Resource ) (storage.Role , error ) {
1205
+ dbRole , err := e .store .GetRoleByID (ctx , roleResource .ID )
1206
+
1207
+ switch {
1208
+ case err == nil :
1209
+ return dbRole , nil
1210
+ case errors .Is (err , storage .ErrNoRoleFound ):
1211
+ return storage.Role {}, ErrRoleNotFound
1212
+ default :
1213
+ return storage.Role {}, err
1214
+ }
1215
+ }
1216
+
1217
+ func (e * engine ) lockRoleForUpdate (ctx context.Context , roleResource types.Resource ) error {
1218
+ err := e .store .LockRoleForUpdate (ctx , roleResource .ID )
1219
+
1220
+ switch {
1221
+ case err == nil :
1222
+ return nil
1223
+ case errors .Is (err , storage .ErrNoRoleFound ):
1224
+ return ErrRoleNotFound
1225
+ default :
1226
+ return err
1227
+ }
1228
+ }
0 commit comments