github.com/status-im/status-go@v1.1.0/protocol/communities/roles_authorization.go (about)

     1  package communities
     2  
     3  import (
     4  	"golang.org/x/exp/slices"
     5  
     6  	"github.com/status-im/status-go/protocol/protobuf"
     7  )
     8  
     9  var adminAuthorizedEventTypes = []protobuf.CommunityEvent_EventType{
    10  	protobuf.CommunityEvent_COMMUNITY_EDIT,
    11  	protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE,
    12  	protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE,
    13  	protobuf.CommunityEvent_COMMUNITY_CATEGORY_CREATE,
    14  	protobuf.CommunityEvent_COMMUNITY_CATEGORY_DELETE,
    15  	protobuf.CommunityEvent_COMMUNITY_CATEGORY_EDIT,
    16  	protobuf.CommunityEvent_COMMUNITY_CHANNEL_CREATE,
    17  	protobuf.CommunityEvent_COMMUNITY_CHANNEL_DELETE,
    18  	protobuf.CommunityEvent_COMMUNITY_CHANNEL_EDIT,
    19  	protobuf.CommunityEvent_COMMUNITY_CATEGORY_REORDER,
    20  	protobuf.CommunityEvent_COMMUNITY_CHANNEL_REORDER,
    21  	protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_ACCEPT,
    22  	protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_REJECT,
    23  	protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK,
    24  	protobuf.CommunityEvent_COMMUNITY_MEMBER_BAN,
    25  	protobuf.CommunityEvent_COMMUNITY_MEMBER_UNBAN,
    26  	protobuf.CommunityEvent_COMMUNITY_DELETE_BANNED_MEMBER_MESSAGES,
    27  }
    28  
    29  var tokenMasterAuthorizedEventTypes = append(adminAuthorizedEventTypes, []protobuf.CommunityEvent_EventType{
    30  	protobuf.CommunityEvent_COMMUNITY_TOKEN_ADD,
    31  }...)
    32  
    33  var ownerAuthorizedEventTypes = tokenMasterAuthorizedEventTypes
    34  
    35  var rolesToAuthorizedEventTypes = map[protobuf.CommunityMember_Roles][]protobuf.CommunityEvent_EventType{
    36  	protobuf.CommunityMember_ROLE_NONE:         []protobuf.CommunityEvent_EventType{},
    37  	protobuf.CommunityMember_ROLE_OWNER:        ownerAuthorizedEventTypes,
    38  	protobuf.CommunityMember_ROLE_ADMIN:        adminAuthorizedEventTypes,
    39  	protobuf.CommunityMember_ROLE_TOKEN_MASTER: tokenMasterAuthorizedEventTypes,
    40  }
    41  
    42  var adminAuthorizedPermissionTypes = []protobuf.CommunityTokenPermission_Type{
    43  	protobuf.CommunityTokenPermission_BECOME_MEMBER,
    44  	protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
    45  	protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL,
    46  }
    47  
    48  var tokenMasterAuthorizedPermissionTypes = append(adminAuthorizedPermissionTypes, []protobuf.CommunityTokenPermission_Type{}...)
    49  
    50  var ownerAuthorizedPermissionTypes = append(tokenMasterAuthorizedPermissionTypes, []protobuf.CommunityTokenPermission_Type{
    51  	protobuf.CommunityTokenPermission_BECOME_ADMIN,
    52  	protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER,
    53  }...)
    54  
    55  var rolesToAuthorizedPermissionTypes = map[protobuf.CommunityMember_Roles][]protobuf.CommunityTokenPermission_Type{
    56  	protobuf.CommunityMember_ROLE_NONE:         []protobuf.CommunityTokenPermission_Type{},
    57  	protobuf.CommunityMember_ROLE_OWNER:        ownerAuthorizedPermissionTypes,
    58  	protobuf.CommunityMember_ROLE_ADMIN:        adminAuthorizedPermissionTypes,
    59  	protobuf.CommunityMember_ROLE_TOKEN_MASTER: tokenMasterAuthorizedPermissionTypes,
    60  }
    61  
    62  func canRolesPerformEvent(roles []protobuf.CommunityMember_Roles, eventType protobuf.CommunityEvent_EventType) bool {
    63  	for _, role := range roles {
    64  		if slices.Contains(rolesToAuthorizedEventTypes[role], eventType) {
    65  			return true
    66  		}
    67  	}
    68  	return false
    69  }
    70  
    71  func canRolesModifyPermission(roles []protobuf.CommunityMember_Roles, permissionType protobuf.CommunityTokenPermission_Type) bool {
    72  	for _, role := range roles {
    73  		if slices.Contains(rolesToAuthorizedPermissionTypes[role], permissionType) {
    74  			return true
    75  		}
    76  	}
    77  	return false
    78  }
    79  
    80  func canRolesKickOrBanMember(senderRoles []protobuf.CommunityMember_Roles, memberRoles []protobuf.CommunityMember_Roles) bool {
    81  	// Owner can kick everyone
    82  	if slices.Contains(senderRoles, protobuf.CommunityMember_ROLE_OWNER) {
    83  		return true
    84  	}
    85  
    86  	// TokenMaster can kick normal members and admins
    87  	if (slices.Contains(senderRoles, protobuf.CommunityMember_ROLE_TOKEN_MASTER)) &&
    88  		!(slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_TOKEN_MASTER) ||
    89  			slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_OWNER)) {
    90  		return true
    91  	}
    92  
    93  	// Admins can kick normal members
    94  	if (slices.Contains(senderRoles, protobuf.CommunityMember_ROLE_ADMIN)) &&
    95  		!(slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_ADMIN) ||
    96  			slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_TOKEN_MASTER) ||
    97  			slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_OWNER)) {
    98  		return true
    99  	}
   100  
   101  	// Normal members can't kick anyone
   102  	return false
   103  }
   104  
   105  func RolesAuthorizedToPerformEvent(senderRoles []protobuf.CommunityMember_Roles, memberRoles []protobuf.CommunityMember_Roles, event *CommunityEvent) bool {
   106  	if !canRolesPerformEvent(senderRoles, event.Type) {
   107  		return false
   108  	}
   109  
   110  	if event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE ||
   111  		event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE {
   112  		return canRolesModifyPermission(senderRoles, event.TokenPermission.Type)
   113  	}
   114  
   115  	if event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_BAN ||
   116  		event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK ||
   117  		event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_UNBAN ||
   118  		event.Type == protobuf.CommunityEvent_COMMUNITY_DELETE_BANNED_MEMBER_MESSAGES {
   119  		return canRolesKickOrBanMember(senderRoles, memberRoles)
   120  	}
   121  
   122  	return true
   123  }