fix: channel members evaluation on request acceptance

If there is only `viewAndPost` permission set on a channel, members who
don't satisfy the criteria shouldn't be able to view the channel.
This commit is contained in:
Patryk Osmaczko 2024-03-09 22:36:40 +01:00 committed by osmaczko
parent 2995518939
commit 1de61d1933
2 changed files with 36 additions and 32 deletions

View File

@ -23,11 +23,13 @@ type HighestRoleResponse struct {
Criteria []*PermissionTokenCriteriaResult `json:"criteria"` Criteria []*PermissionTokenCriteriaResult `json:"criteria"`
} }
var joiningRoleOrders = map[protobuf.CommunityTokenPermission_Type]int{ var roleOrders = map[protobuf.CommunityTokenPermission_Type]int{
protobuf.CommunityTokenPermission_BECOME_MEMBER: 1, protobuf.CommunityTokenPermission_BECOME_MEMBER: 1,
protobuf.CommunityTokenPermission_BECOME_ADMIN: 2, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL: 2,
protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER: 3, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL: 3,
protobuf.CommunityTokenPermission_BECOME_TOKEN_OWNER: 4, protobuf.CommunityTokenPermission_BECOME_ADMIN: 4,
protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER: 5,
protobuf.CommunityTokenPermission_BECOME_TOKEN_OWNER: 6,
} }
type ByRoleDesc []*HighestRoleResponse type ByRoleDesc []*HighestRoleResponse
@ -35,7 +37,7 @@ type ByRoleDesc []*HighestRoleResponse
func (a ByRoleDesc) Len() int { return len(a) } func (a ByRoleDesc) Len() int { return len(a) }
func (a ByRoleDesc) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByRoleDesc) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByRoleDesc) Less(i, j int) bool { func (a ByRoleDesc) Less(i, j int) bool {
return joiningRoleOrders[a[i].Role] > joiningRoleOrders[a[j].Role] return roleOrders[a[i].Role] > roleOrders[a[j].Role]
} }
type rolesAndHighestRole struct { type rolesAndHighestRole struct {
@ -47,7 +49,7 @@ func calculateRolesAndHighestRole(permissions map[string]*PermissionTokenCriteri
item := &rolesAndHighestRole{} item := &rolesAndHighestRole{}
byRoleMap := make(map[protobuf.CommunityTokenPermission_Type]*HighestRoleResponse) byRoleMap := make(map[protobuf.CommunityTokenPermission_Type]*HighestRoleResponse)
for _, p := range permissions { for _, p := range permissions {
if joiningRoleOrders[p.Role] == 0 { if roleOrders[p.Role] == 0 {
continue continue
} }
if byRoleMap[p.Role] == nil { if byRoleMap[p.Role] == nil {

View File

@ -2320,39 +2320,41 @@ func (m *Manager) accountsSatisfyPermissionsToJoin(community *Community, account
} }
func (m *Manager) accountsSatisfyPermissionsToJoinChannels(community *Community, accounts []*protobuf.RevealedAccount) (map[string]*protobuf.CommunityChat, map[string]*protobuf.CommunityChat, error) { func (m *Manager) accountsSatisfyPermissionsToJoinChannels(community *Community, accounts []*protobuf.RevealedAccount) (map[string]*protobuf.CommunityChat, map[string]*protobuf.CommunityChat, error) {
viewChats := make(map[string]*protobuf.CommunityChat)
viewAndPostChats := make(map[string]*protobuf.CommunityChat)
accountsAndChainIDs := revealedAccountsToAccountsAndChainIDsCombination(accounts) accountsAndChainIDs := revealedAccountsToAccountsAndChainIDsCombination(accounts)
viewChats, err := m.accountsSatisfyPermissionTypeToJoinChannels(community, accountsAndChainIDs, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
if err != nil {
return nil, nil, err
}
postChats, err := m.accountsSatisfyPermissionTypeToJoinChannels(community, accountsAndChainIDs, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
if err != nil {
return nil, nil, err
}
return viewChats, postChats, nil
}
func (m *Manager) accountsSatisfyPermissionTypeToJoinChannels(community *Community, accounts []*AccountChainIDsCombination, permissionType protobuf.CommunityTokenPermission_Type) (map[string]*protobuf.CommunityChat, error) {
result := make(map[string]*protobuf.CommunityChat)
for channelID, channel := range community.config.CommunityDescription.Chats { for channelID, channel := range community.config.CommunityDescription.Chats {
permissions := community.ChannelTokenPermissionsByType(community.IDString()+channelID, permissionType) channelViewOnlyPermissions := community.ChannelTokenPermissionsByType(community.IDString()+channelID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
if len(permissions) > 0 { channelViewAndPostPermissions := community.ChannelTokenPermissionsByType(community.IDString()+channelID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
permissionResponse, err := m.PermissionChecker.CheckPermissions(permissions, accounts, true) channelPermissions := append(channelViewOnlyPermissions, channelViewAndPostPermissions...)
if err != nil {
return nil, err if len(channelPermissions) == 0 {
viewAndPostChats[channelID] = channel
continue
}
permissionResponse, err := m.PermissionChecker.CheckPermissions(channelPermissions, accountsAndChainIDs, true)
if err != nil {
return nil, nil, err
}
if permissionResponse.Satisfied {
highestRole := calculateRolesAndHighestRole(permissionResponse.Permissions).HighestRole
if highestRole == nil {
return nil, nil, errors.New("failed to calculate highest role")
} }
if !permissionResponse.Satisfied { switch highestRole.Role {
continue case protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL:
viewChats[channelID] = channel
case protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL:
viewAndPostChats[channelID] = channel
} }
} }
result[channelID] = channel
} }
return result, nil return viewChats, viewAndPostChats, nil
} }
func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, error) { func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, error) {