-
Notifications
You must be signed in to change notification settings - Fork 45
/
permissions.go
104 lines (83 loc) · 3.87 KB
/
permissions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/desmos-labs/desmos/v3/x/subspaces/types"
)
// SetUserPermissions sets the given permission for the specific user inside a single subspace
func (k Keeper) SetUserPermissions(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress, permissions types.Permission) {
store := ctx.KVStore(k.storeKey)
store.Set(types.UserPermissionStoreKey(subspaceID, user), types.MarshalPermission(permissions))
k.AfterUserPermissionSet(ctx, subspaceID, user, permissions)
}
// HasPermission checks whether the specific user has the given permission inside a specific subspace
func (k Keeper) HasPermission(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress, permission types.Permission) bool {
// Get the subspace to make sure the request is valid
subspace, found := k.GetSubspace(ctx, subspaceID)
if !found {
return false
}
specificPermissions := k.GetUserPermissions(ctx, subspaceID, user)
// The owner of the subspaces has all the permissions by default
if subspace.Owner == user.String() {
return true
}
// Get the group permissions
groupPermissions := k.GetGroupsInheritedPermissions(ctx, subspaceID, user)
// Check the combination of the permissions
return types.CheckPermission(types.CombinePermissions(specificPermissions, groupPermissions), permission)
}
// GetUserPermissions returns the permissions that are currently set inside
// the subspace with the given id for the given user
func (k Keeper) GetUserPermissions(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress) types.Permission {
store := ctx.KVStore(k.storeKey)
return types.UnmarshalPermission(store.Get(types.UserPermissionStoreKey(subspaceID, user)))
}
// GetGroupsInheritedPermissions returns the permissions that the specified user
// has inherited from all the groups that they are part of.
func (k Keeper) GetGroupsInheritedPermissions(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress) types.Permission {
var permissions []types.Permission
k.IterateSubspaceGroups(ctx, subspaceID, func(index int64, group types.UserGroup) (stop bool) {
if k.IsMemberOfGroup(ctx, subspaceID, group.ID, user) {
permissions = append(permissions, group.Permissions)
}
return false
})
return types.CombinePermissions(permissions...)
}
// GetUsersWithPermission returns all the users that have a given permission inside the specified subspace
func (k Keeper) GetUsersWithPermission(ctx sdk.Context, subspaceID uint64, permission types.Permission) ([]sdk.AccAddress, error) {
subspace, found := k.GetSubspace(ctx, subspaceID)
if !found {
return nil, nil
}
// The owner must always be included as they have all the permissions
ownerAddr, err := sdk.AccAddressFromBech32(subspace.Owner)
if err != nil {
return nil, err
}
users := []sdk.AccAddress{ownerAddr}
// Iterate over the various groups
k.IterateSubspaceGroups(ctx, subspaceID, func(index int64, group types.UserGroup) (stop bool) {
if !types.CheckPermission(group.Permissions, permission) {
// Return early if the group does not have the permission. We will check other groups anyway
return false
}
// If the group has the permission, get all the members
users = append(users, k.GetGroupMembers(ctx, subspaceID, group.ID)...)
return false
})
// Iterate over the various individually-set permissions
k.IterateSubspacePermissions(ctx, subspaceID, func(index int64, user sdk.AccAddress, userPerm types.Permission) (stop bool) {
if types.CheckPermission(userPerm, permission) {
users = append(users, user)
}
return false
})
return users, nil
}
// RemoveUserPermissions removes the permission for the given user inside the provided subspace
func (k Keeper) RemoveUserPermissions(ctx sdk.Context, subspaceID uint64, user sdk.AccAddress) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.UserPermissionStoreKey(subspaceID, user))
k.AfterUserPermissionRemoved(ctx, subspaceID, user)
}