status-go/protocol/communities/roles_authorization.go

124 lines
5.0 KiB
Go

package communities
import (
"golang.org/x/exp/slices"
"github.com/status-im/status-go/protocol/protobuf"
)
var adminAuthorizedEventTypes = []protobuf.CommunityEvent_EventType{
protobuf.CommunityEvent_COMMUNITY_EDIT,
protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE,
protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE,
protobuf.CommunityEvent_COMMUNITY_CATEGORY_CREATE,
protobuf.CommunityEvent_COMMUNITY_CATEGORY_DELETE,
protobuf.CommunityEvent_COMMUNITY_CATEGORY_EDIT,
protobuf.CommunityEvent_COMMUNITY_CHANNEL_CREATE,
protobuf.CommunityEvent_COMMUNITY_CHANNEL_DELETE,
protobuf.CommunityEvent_COMMUNITY_CHANNEL_EDIT,
protobuf.CommunityEvent_COMMUNITY_CATEGORY_REORDER,
protobuf.CommunityEvent_COMMUNITY_CHANNEL_REORDER,
protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_ACCEPT,
protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_REJECT,
protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK,
protobuf.CommunityEvent_COMMUNITY_MEMBER_BAN,
protobuf.CommunityEvent_COMMUNITY_MEMBER_UNBAN,
protobuf.CommunityEvent_COMMUNITY_DELETE_BANNED_MEMBER_MESSAGES,
}
var tokenMasterAuthorizedEventTypes = append(adminAuthorizedEventTypes, []protobuf.CommunityEvent_EventType{
protobuf.CommunityEvent_COMMUNITY_TOKEN_ADD,
}...)
var ownerAuthorizedEventTypes = tokenMasterAuthorizedEventTypes
var rolesToAuthorizedEventTypes = map[protobuf.CommunityMember_Roles][]protobuf.CommunityEvent_EventType{
protobuf.CommunityMember_ROLE_NONE: []protobuf.CommunityEvent_EventType{},
protobuf.CommunityMember_ROLE_OWNER: ownerAuthorizedEventTypes,
protobuf.CommunityMember_ROLE_ADMIN: adminAuthorizedEventTypes,
protobuf.CommunityMember_ROLE_TOKEN_MASTER: tokenMasterAuthorizedEventTypes,
}
var adminAuthorizedPermissionTypes = []protobuf.CommunityTokenPermission_Type{
protobuf.CommunityTokenPermission_BECOME_MEMBER,
protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL,
}
var tokenMasterAuthorizedPermissionTypes = append(adminAuthorizedPermissionTypes, []protobuf.CommunityTokenPermission_Type{}...)
var ownerAuthorizedPermissionTypes = append(tokenMasterAuthorizedPermissionTypes, []protobuf.CommunityTokenPermission_Type{
protobuf.CommunityTokenPermission_BECOME_ADMIN,
protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
}...)
var rolesToAuthorizedPermissionTypes = map[protobuf.CommunityMember_Roles][]protobuf.CommunityTokenPermission_Type{
protobuf.CommunityMember_ROLE_NONE: []protobuf.CommunityTokenPermission_Type{},
protobuf.CommunityMember_ROLE_OWNER: ownerAuthorizedPermissionTypes,
protobuf.CommunityMember_ROLE_ADMIN: adminAuthorizedPermissionTypes,
protobuf.CommunityMember_ROLE_TOKEN_MASTER: tokenMasterAuthorizedPermissionTypes,
}
func canRolesPerformEvent(roles []protobuf.CommunityMember_Roles, eventType protobuf.CommunityEvent_EventType) bool {
for _, role := range roles {
if slices.Contains(rolesToAuthorizedEventTypes[role], eventType) {
return true
}
}
return false
}
func canRolesModifyPermission(roles []protobuf.CommunityMember_Roles, permissionType protobuf.CommunityTokenPermission_Type) bool {
for _, role := range roles {
if slices.Contains(rolesToAuthorizedPermissionTypes[role], permissionType) {
return true
}
}
return false
}
func canRolesKickOrBanMember(senderRoles []protobuf.CommunityMember_Roles, memberRoles []protobuf.CommunityMember_Roles) bool {
// Owner can kick everyone
if slices.Contains(senderRoles, protobuf.CommunityMember_ROLE_OWNER) {
return true
}
// TokenMaster can kick normal members and admins
if (slices.Contains(senderRoles, protobuf.CommunityMember_ROLE_TOKEN_MASTER)) &&
!(slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_TOKEN_MASTER) ||
slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_OWNER)) {
return true
}
// Admins can kick normal members
if (slices.Contains(senderRoles, protobuf.CommunityMember_ROLE_ADMIN)) &&
!(slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_ADMIN) ||
slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_TOKEN_MASTER) ||
slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_OWNER)) {
return true
}
// Normal members can't kick anyone
return false
}
func RolesAuthorizedToPerformEvent(senderRoles []protobuf.CommunityMember_Roles, memberRoles []protobuf.CommunityMember_Roles, event *CommunityEvent) bool {
if !canRolesPerformEvent(senderRoles, event.Type) {
return false
}
if event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE ||
event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE {
return canRolesModifyPermission(senderRoles, event.TokenPermission.Type)
}
if event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_BAN ||
event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK ||
event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_UNBAN ||
event.Type == protobuf.CommunityEvent_COMMUNITY_DELETE_BANNED_MEMBER_MESSAGES {
return canRolesKickOrBanMember(senderRoles, memberRoles)
}
return true
}