@@ -3,6 +3,7 @@ package auth
33import (
44 "context"
55 "fmt"
6+ "slices"
67
78 "github.com/google/uuid"
89 "github.com/modernice/goes/aggregate"
@@ -23,15 +24,17 @@ import (
2324//
2425// For example, if an actor is a member of an "admin" role, and the following
2526// permissions are granted and revoked in the following order:
26- // 1. Actor is granted "view" permission on a "foo" aggregate.
27- // 2. Role is granted "view" permission on the same "foo" aggregate.
28- // 3. Role is revoked "view" permission on the aggregate.
27+ // 1. Actor is granted "view" permission on a "foo" aggregate.
28+ // 2. Role is granted "view" permission on the same "foo" aggregate.
29+ // 3. Role is revoked "view" permission on the aggregate.
30+ //
2931// Then the actor is still allowed to perform the "view" action on the aggregate.
3032//
3133// Another example:
32- // 1. Role is granted "view" permission on a "foo" aggregate.
34+ // 1. Role is granted "view" permission on a "foo" aggregate.
3335// 2. Actor is granted "view" permission on the same aggregate.
3436// 2. Actor is revoked "view" permission on the aggregate.
37+ //
3538// Then the actor is also allowed to perform the "view" action on the aggregate
3639// because the role still grants the permission its members.
3740type Permissions struct {
@@ -54,6 +57,7 @@ type PermissionsDTO struct {
5457// The returned projection has an empty state. A *Projector can be used to
5558// continuously project the permission read-models for all actors. Use a
5659// PermissionRepository to fetch the projected permissions of an actor:
60+ //
5761// var repo auth.PermissionRepository
5862// var actorID uuid.UUID
5963// perms, err := repo.Fetch(context.TODO(), actorID)
@@ -125,27 +129,51 @@ func (perms PermissionsDTO) Equal(other PermissionsDTO) bool {
125129func (perms * Permissions ) granted (evt event.Of [PermissionGrantedData ]) {
126130 switch pick .AggregateName (evt ) {
127131 case ActorAggregate :
132+ if perms .ActorID != pick .AggregateID (evt ) {
133+ return
134+ }
135+
128136 perms .OfActor .granted (evt )
129137 case RoleAggregate :
138+ if ! slices .Contains (perms .Roles , pick .AggregateID (evt )) {
139+ return
140+ }
141+
130142 perms .OfRoles .granted (evt )
131143 }
132144}
133145
134146func (perms * Permissions ) revoked (evt event.Of [PermissionRevokedData ]) {
135147 switch pick .AggregateName (evt ) {
136148 case ActorAggregate :
149+ if perms .ActorID != pick .AggregateID (evt ) {
150+ return
151+ }
152+
137153 perms .OfActor .revoked (evt )
138154 case RoleAggregate :
155+ if ! slices .Contains (perms .Roles , pick .AggregateID (evt )) {
156+ return
157+ }
158+
139159 perms .OfRoles .revoked (evt )
140160 }
141161}
142162
143163func (perms * Permissions ) roleGiven (evt event.Of [[]uuid.UUID ]) {
164+ if perms .ActorID != pick .AggregateID (evt ) {
165+ return
166+ }
167+
144168 perms .Roles = append (perms .Roles , pick .AggregateID (evt ))
145169 perms .rolesHaveChanged = true
146170}
147171
148172func (perms * Permissions ) roleRemoved (evt event.Of [[]uuid.UUID ]) {
173+ if perms .ActorID != pick .AggregateID (evt ) {
174+ return
175+ }
176+
149177 roleID := pick .AggregateID (evt )
150178 for i , role := range perms .Roles {
151179 if roleID == role {
0 commit comments