From d0f304c262cc8b00927ce199f5398d28b4bcf7ba Mon Sep 17 00:00:00 2001 From: Patryk Osmaczko Date: Wed, 16 Aug 2023 14:54:55 +0200 Subject: [PATCH] refactor: simplify events creation logic - use `roles_authorization.go` APIs as the ultimate source of truth - unify&simplify community modifications in terms of events creation --- protocol/communities/community.go | 296 +++++++----------- protocol/communities/community_categories.go | 118 +++---- .../communities/community_categories_test.go | 6 +- protocol/communities/community_test.go | 10 +- protocol/communities/manager.go | 23 +- protocol/communities/roles_authorization.go | 5 +- 6 files changed, 180 insertions(+), 278 deletions(-) diff --git a/protocol/communities/community.go b/protocol/communities/community.go index 9fb0310eb..e6ca2b608 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -483,31 +483,26 @@ func (o *Community) CreateChat(chatID string, chat *protobuf.CommunityChat) (*Co o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin - } - - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToCreateChannelCommunityEvent(chatID, chat)) - if err != nil { - return nil, err - } + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_CHANNEL_CREATE)) { + return nil, ErrNotAuthorized } err := o.createChat(chatID, chat) if err != nil { return nil, err } - - if isControlNode { - o.increaseClock() - } - changes := o.emptyCommunityChanges() changes.ChatsAdded[chatID] = chat + + if o.IsControlNode() { + o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToCreateChannelCommunityEvent(chatID, chat)) + if err != nil { + return nil, err + } + } + return changes, nil } @@ -515,34 +510,28 @@ func (o *Community) EditChat(chatID string, chat *protobuf.CommunityChat) (*Comm o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin - } - - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToEditChannelCommunityEvent(chatID, chat)) - if err != nil { - return nil, err - } + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_CHANNEL_EDIT)) { + return nil, ErrNotAuthorized } err := o.editChat(chatID, chat) if err != nil { return nil, err } - - if isControlNode { - o.increaseClock() - } - changes := o.emptyCommunityChanges() changes.ChatsModified[chatID] = &CommunityChatChanges{ ChatModified: chat, } + if o.IsControlNode() { + o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToEditChannelCommunityEvent(chatID, chat)) + if err != nil { + return nil, err + } + } + return changes, nil } @@ -550,24 +539,19 @@ func (o *Community) DeleteChat(chatID string) (*CommunityChanges, error) { o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin - } - - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToDeleteChannelCommunityEvent(chatID)) - if err != nil { - return nil, err - } + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_CHANNEL_DELETE)) { + return nil, ErrNotAuthorized } changes := o.deleteChat(chatID) - if isControlNode { + if o.IsControlNode() { o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToDeleteChannelCommunityEvent(chatID)) + if err != nil { + return nil, err + } } return changes, nil @@ -621,6 +605,15 @@ func (o *Community) isBanned(pk *ecdsa.PublicKey) bool { return false } +func (o *Community) rolesOf(pk *ecdsa.PublicKey) []protobuf.CommunityMember_Roles { + member := o.getMember(pk) + if member == nil { + return nil + } + + return member.Roles +} + func (o *Community) memberHasRoles(member *protobuf.CommunityMember, roles map[protobuf.CommunityMember_Roles]bool) bool { for _, r := range member.Roles { if roles[r] { @@ -709,29 +702,25 @@ func (o *Community) RemoveUserFromOrg(pk *ecdsa.PublicKey) (*protobuf.CommunityD o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK)) { + return nil, ErrNotAuthorized } - if !isControlNode && o.IsPrivilegedMember(pk) { + if !o.IsControlNode() && o.IsPrivilegedMember(pk) { return nil, ErrCannotRemoveOwnerOrAdmin } - if allowedToSendEvents { + o.removeMemberFromOrg(pk) + + if o.IsControlNode() { + o.increaseClock() + } else { err := o.addNewCommunityEvent(o.ToKickCommunityMemberCommunityEvent(common.PubkeyToHex(pk))) if err != nil { return nil, err } } - o.removeMemberFromOrg(pk) - if isControlNode { - o.increaseClock() - } - return o.config.CommunityDescription, nil } @@ -739,23 +728,19 @@ func (o *Community) AddCommunityTokensMetadata(token *protobuf.CommunityTokenMet o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendTokenEvents := o.IsOwnerWithoutCommunityKey() || o.IsTokenMaster() - if !isControlNode && !allowedToSendTokenEvents { - return nil, ErrInvalidManageTokensPermission - } - - if allowedToSendTokenEvents { - err := o.addNewCommunityEvent(o.ToAddTokenMetadataCommunityEvent(token)) - if err != nil { - return nil, err - } + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_TOKEN_ADD)) { + return nil, ErrNotAuthorized } o.config.CommunityDescription.CommunityTokensMetadata = append(o.config.CommunityDescription.CommunityTokensMetadata, token) - if isControlNode { + if o.IsControlNode() { o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToAddTokenMetadataCommunityEvent(token)) + if err != nil { + return nil, err + } } return o.config.CommunityDescription, nil @@ -765,24 +750,19 @@ func (o *Community) UnbanUserFromCommunity(pk *ecdsa.PublicKey) (*protobuf.Commu o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin - } - - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToUnbanCommunityMemberCommunityEvent(common.PubkeyToHex(pk))) - if err != nil { - return nil, err - } + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_UNBAN)) { + return nil, ErrNotAuthorized } o.unbanUserFromCommunity(pk) - if isControlNode { + if o.IsControlNode() { o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToUnbanCommunityMemberCommunityEvent(common.PubkeyToHex(pk))) + if err != nil { + return nil, err + } } return o.config.CommunityDescription, nil @@ -792,28 +772,23 @@ func (o *Community) BanUserFromCommunity(pk *ecdsa.PublicKey) (*protobuf.Communi o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_BAN)) { + return nil, ErrNotAuthorized } - if !isControlNode && o.IsPrivilegedMember(pk) { + if !o.IsControlNode() && o.IsPrivilegedMember(pk) { return nil, ErrCannotBanOwnerOrAdmin } - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToBanCommunityMemberCommunityEvent(common.PubkeyToHex(pk))) - if err != nil { - return nil, err - } - } - o.banUserFromCommunity(pk) - if isControlNode { + if o.IsControlNode() { o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToBanCommunityMemberCommunityEvent(common.PubkeyToHex(pk))) + if err != nil { + return nil, err + } } return o.config.CommunityDescription, nil @@ -1090,6 +1065,15 @@ func (o *Community) HasPermissionToSendCommunityEvents() bool { return !o.IsControlNode() && o.hasRoles(o.config.MemberIdentity, manageCommunityRoles()) } +func (o *Community) hasPermissionToSendCommunityEvent(event protobuf.CommunityEvent_EventType) bool { + return !o.IsControlNode() && canRolesPerformEvent(o.rolesOf(o.config.MemberIdentity), event) +} + +func (o *Community) hasPermissionToSendTokenPermissionCommunityEvent(event protobuf.CommunityEvent_EventType, permissionType protobuf.CommunityTokenPermission_Type) bool { + roles := o.rolesOf(o.config.MemberIdentity) + return !o.IsControlNode() && canRolesPerformEvent(roles, event) && canRolesModifyPermission(roles, permissionType) +} + func (o *Community) IsMemberOwner(publicKey *ecdsa.PublicKey) bool { return o.hasRoles(publicKey, ownerRole()) } @@ -1399,13 +1383,8 @@ func (o *Community) AddTokenPermission(permission *protobuf.CommunityTokenPermis o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToManageMemberPermissions := o.IsTokenMaster() || o.IsAdmin() - allowedToManageAllPermissions := o.IsOwnerWithoutCommunityKey() - - if (!isControlNode && !allowedToManageMemberPermissions && !allowedToManageAllPermissions) || - (allowedToManageMemberPermissions && permission.Type != protobuf.CommunityTokenPermission_BECOME_MEMBER) { - return nil, ErrNotEnoughPermissions + if !(o.IsControlNode() || o.hasPermissionToSendTokenPermissionCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE, permission.Type)) { + return nil, ErrNotAuthorized } changes, err := o.addTokenPermission(permission) @@ -1413,18 +1392,16 @@ func (o *Community) AddTokenPermission(permission *protobuf.CommunityTokenPermis return nil, err } - if allowedToManageMemberPermissions || allowedToManageAllPermissions { + if o.IsControlNode() { + o.updateEncrypted() + o.increaseClock() + } else { err := o.addNewCommunityEvent(o.ToCommunityTokenPermissionChangeCommunityEvent(permission)) if err != nil { return nil, err } } - if isControlNode { - o.updateEncrypted() - o.increaseClock() - } - return changes, nil } @@ -1432,13 +1409,8 @@ func (o *Community) UpdateTokenPermission(permissionID string, tokenPermission * o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToManageMemberPermissions := o.IsTokenMaster() || o.IsAdmin() - allowedToManageAllPermissions := o.IsOwnerWithoutCommunityKey() - - if (!isControlNode && !allowedToManageMemberPermissions && !allowedToManageAllPermissions) || - (allowedToManageMemberPermissions && tokenPermission.Type != protobuf.CommunityTokenPermission_BECOME_MEMBER) { - return nil, ErrNotEnoughPermissions + if !(o.IsControlNode() || o.hasPermissionToSendTokenPermissionCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE, tokenPermission.Type)) { + return nil, ErrNotAuthorized } changes, err := o.updateTokenPermission(tokenPermission) @@ -1446,18 +1418,16 @@ func (o *Community) UpdateTokenPermission(permissionID string, tokenPermission * return nil, err } - if allowedToManageMemberPermissions || allowedToManageAllPermissions { + if o.IsControlNode() { + o.updateEncrypted() + o.increaseClock() + } else { err := o.addNewCommunityEvent(o.ToCommunityTokenPermissionChangeCommunityEvent(tokenPermission)) if err != nil { return nil, err } } - if isControlNode { - o.updateEncrypted() - o.increaseClock() - } - return changes, nil } @@ -1466,18 +1436,12 @@ func (o *Community) DeleteTokenPermission(permissionID string) (*CommunityChange defer o.mutex.Unlock() permission, exists := o.config.CommunityDescription.TokenPermissions[permissionID] - if !exists { return nil, ErrTokenPermissionNotFound } - isControlNode := o.IsControlNode() - allowedToManageMemberPermissions := o.IsTokenMaster() || o.IsAdmin() - allowedToManageAllPermissions := o.IsOwnerWithoutCommunityKey() - - if (!isControlNode && !allowedToManageMemberPermissions && !allowedToManageAllPermissions) || - (allowedToManageMemberPermissions && permission.Type != protobuf.CommunityTokenPermission_BECOME_MEMBER) { - return nil, ErrNotEnoughPermissions + if !(o.IsControlNode() || o.hasPermissionToSendTokenPermissionCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE, permission.Type)) { + return nil, ErrNotAuthorized } changes, err := o.deleteTokenPermission(permissionID) @@ -1485,18 +1449,16 @@ func (o *Community) DeleteTokenPermission(permissionID string) (*CommunityChange return nil, err } - if allowedToManageMemberPermissions || allowedToManageAllPermissions { + if o.IsControlNode() { + o.updateEncrypted() + o.increaseClock() + } else { err := o.addNewCommunityEvent(o.ToCommunityTokenPermissionDeleteCommunityEvent(permission)) if err != nil { return nil, err } } - if isControlNode { - o.updateEncrypted() - o.increaseClock() - } - return changes, nil } @@ -1761,8 +1723,8 @@ func (o *Community) RequestsToJoin() []*RequestToJoin { } func (o *Community) AddMember(publicKey *ecdsa.PublicKey, roles []protobuf.CommunityMember_Roles) (*CommunityChanges, error) { - if !o.IsControlNode() && !o.HasPermissionToSendCommunityEvents() { - return nil, ErrNotAdmin + if !o.IsControlNode() { + return nil, ErrNotControlNode } memberKey := common.PubkeyToHex(publicKey) @@ -1785,8 +1747,8 @@ func (o *Community) AddMemberToChat(chatID string, publicKey *ecdsa.PublicKey, r o.mutex.Lock() defer o.mutex.Unlock() - if !o.IsControlNode() && !o.HasPermissionToSendCommunityEvents() { - return nil, ErrNotAuthorized + if !o.IsControlNode() { + return nil, ErrNotControlNode } memberKey := common.PubkeyToHex(publicKey) @@ -1863,35 +1825,12 @@ func (o *Community) AllowsAllMembersToPinMessage() bool { return o.config.CommunityDescription.AdminSettings != nil && o.config.CommunityDescription.AdminSettings.PinMessageAllMembersEnabled } -func (o *Community) AddMemberRevealedAccounts(memberID string, accounts []*protobuf.RevealedAccount, clock uint64) (*CommunityChanges, error) { - o.mutex.Lock() - defer o.mutex.Unlock() - - if !o.IsControlNode() && !o.HasPermissionToSendCommunityEvents() { - return nil, ErrNotAdmin - } - - if _, ok := o.config.CommunityDescription.Members[memberID]; !ok { - return nil, ErrMemberNotFound - } - - o.config.CommunityDescription.Members[memberID].RevealedAccounts = accounts - o.config.CommunityDescription.Members[memberID].LastUpdateClock = clock - o.increaseClock() - - changes := o.emptyCommunityChanges() - changes.MemberWalletsAdded[memberID] = o.config.CommunityDescription.Members[memberID].RevealedAccounts - return changes, nil -} - func (o *Community) AddMemberWithRevealedAccounts(dbRequest *RequestToJoin, roles []protobuf.CommunityMember_Roles, accounts []*protobuf.RevealedAccount) (*CommunityChanges, error) { o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - - if !isControlNode { - return nil, ErrNotAdmin + if !o.IsControlNode() { + return nil, ErrNotControlNode } changes := o.addMemberWithRevealedAccounts(dbRequest.PublicKey, roles, accounts, dbRequest.Clock) @@ -2139,14 +2078,17 @@ func (o *Community) DeclineRequestToJoin(dbRequest *RequestToJoin) error { o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return ErrNotAdmin + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_REJECT)) { + return ErrNotAuthorized } - if allowedToSendEvents { + if o.IsControlNode() { + // typically, community's clock is increased implicitly when making changes + // to it, however in this scenario there are no changes in the community, yet + // we need to increase the clock to ensure the owner event is processed by other + // nodes. + o.increaseClock() + } else { rejectedRequestsToJoin := make(map[string]*protobuf.CommunityRequestToJoin) rejectedRequestsToJoin[dbRequest.PublicKey] = dbRequest.ToCommunityRequestToJoinProtobuf() @@ -2160,14 +2102,6 @@ func (o *Community) DeclineRequestToJoin(dbRequest *RequestToJoin) error { } } - if isControlNode { - // typically, community's clock is increased implicitly when making changes - // to it, however in this scenario there are no changes in the community, yet - // we need to increase the clock to ensure the owner event is processed by other - // nodes. - o.increaseClock() - } - return nil } diff --git a/protocol/communities/community_categories.go b/protocol/communities/community_categories.go index 13695c5bb..720ff0ade 100644 --- a/protocol/communities/community_categories.go +++ b/protocol/communities/community_categories.go @@ -40,18 +40,8 @@ func (o *Community) CreateCategory(categoryID string, categoryName string, chatI o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin - } - - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToCreateCategoryCommunityEvent(categoryID, categoryName, chatIDs)) - if err != nil { - return nil, err - } + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_CATEGORY_CREATE)) { + return nil, ErrNotAuthorized } changes, err := o.createCategory(categoryID, categoryName, chatIDs) @@ -59,10 +49,6 @@ func (o *Community) CreateCategory(categoryID string, categoryName string, chatI return nil, err } - if isControlNode { - o.increaseClock() - } - changes.CategoriesAdded[categoryID] = o.config.CommunityDescription.Categories[categoryID] for i, cid := range chatIDs { changes.ChatsModified[cid] = &CommunityChatChanges{ @@ -73,6 +59,15 @@ func (o *Community) CreateCategory(categoryID string, categoryName string, chatI } } + if o.IsControlNode() { + o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToCreateCategoryCommunityEvent(categoryID, categoryName, chatIDs)) + if err != nil { + return nil, err + } + } + return changes, nil } @@ -80,19 +75,8 @@ func (o *Community) EditCategory(categoryID string, categoryName string, chatIDs o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin - } - - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToEditCategoryCommunityEvent(categoryID, categoryName, chatIDs)) - if err != nil { - return nil, err - } - + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_CATEGORY_EDIT)) { + return nil, ErrNotAuthorized } changes, err := o.editCategory(categoryID, categoryName, chatIDs) @@ -100,10 +84,6 @@ func (o *Community) EditCategory(categoryID string, categoryName string, chatIDs return nil, err } - if isControlNode { - o.increaseClock() - } - changes.CategoriesModified[categoryID] = o.config.CommunityDescription.Categories[categoryID] for i, cid := range chatIDs { changes.ChatsModified[cid] = &CommunityChatChanges{ @@ -114,6 +94,15 @@ func (o *Community) EditCategory(categoryID string, categoryName string, chatIDs } } + if o.IsControlNode() { + o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToEditCategoryCommunityEvent(categoryID, categoryName, chatIDs)) + if err != nil { + return nil, err + } + } + return changes, nil } @@ -121,18 +110,8 @@ func (o *Community) ReorderCategories(categoryID string, newPosition int) (*Comm o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin - } - - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToReorderCategoryCommunityEvent(categoryID, newPosition)) - if err != nil { - return nil, err - } + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_CATEGORY_REORDER)) { + return nil, ErrNotAuthorized } changes, err := o.reorderCategories(categoryID, newPosition) @@ -140,8 +119,13 @@ func (o *Community) ReorderCategories(categoryID string, newPosition int) (*Comm return nil, err } - if isControlNode { + if o.IsControlNode() { o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToReorderCategoryCommunityEvent(categoryID, newPosition)) + if err != nil { + return nil, err + } } return changes, nil @@ -161,18 +145,8 @@ func (o *Community) ReorderChat(categoryID string, chatID string, newPosition in o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin - } - - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToReorderChannelCommunityEvent(categoryID, chatID, newPosition)) - if err != nil { - return nil, err - } + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_CHANNEL_REORDER)) { + return nil, ErrNotAuthorized } changes, err := o.reorderChat(categoryID, chatID, newPosition) @@ -180,8 +154,13 @@ func (o *Community) ReorderChat(categoryID string, chatID string, newPosition in return nil, err } - if isControlNode { + if o.IsControlNode() { o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToReorderChannelCommunityEvent(categoryID, chatID, newPosition)) + if err != nil { + return nil, err + } } return changes, nil @@ -316,18 +295,8 @@ func (o *Community) DeleteCategory(categoryID string) (*CommunityChanges, error) o.mutex.Lock() defer o.mutex.Unlock() - isControlNode := o.IsControlNode() - allowedToSendEvents := o.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotAdmin - } - - if allowedToSendEvents { - err := o.addNewCommunityEvent(o.ToDeleteCategoryCommunityEvent(categoryID)) - if err != nil { - return nil, err - } + if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_CATEGORY_DELETE)) { + return nil, ErrNotAuthorized } changes, err := o.deleteCategory(categoryID) @@ -335,8 +304,13 @@ func (o *Community) DeleteCategory(categoryID string) (*CommunityChanges, error) return nil, err } - if isControlNode { + if o.IsControlNode() { o.increaseClock() + } else { + err := o.addNewCommunityEvent(o.ToDeleteCategoryCommunityEvent(categoryID)) + if err != nil { + return nil, err + } } return changes, nil diff --git a/protocol/communities/community_categories_test.go b/protocol/communities/community_categories_test.go index dd32c77a4..d93ecdbac 100644 --- a/protocol/communities/community_categories_test.go +++ b/protocol/communities/community_categories_test.go @@ -13,7 +13,7 @@ func (s *CommunitySuite) TestCreateCategory() { org.config.ID = nil _, err := org.CreateCategory(newCategoryID, newCategoryName, []string{}) - s.Require().Equal(ErrNotAdmin, err) + s.Require().Equal(ErrNotAuthorized, err) org.config.PrivateKey = s.identity org.config.ID = &s.identity.PublicKey @@ -90,7 +90,7 @@ func (s *CommunitySuite) TestEditCategory() { org.config.ID = nil _, err = org.EditCategory(newCategoryID, editedCategoryName, []string{testChatID1}) - s.Require().Equal(ErrNotAdmin, err) + s.Require().Equal(ErrNotAuthorized, err) org.config.PrivateKey = s.identity org.config.ID = &s.identity.PublicKey @@ -218,7 +218,7 @@ func (s *CommunitySuite) TestDeleteCategory() { org.config.PrivateKey = nil org.config.ID = nil _, err = org.DeleteCategory(testCategoryID1) - s.Require().Equal(ErrNotAdmin, err) + s.Require().Equal(ErrNotAuthorized, err) org.config.PrivateKey = s.identity org.config.ID = &s.identity.PublicKey diff --git a/protocol/communities/community_test.go b/protocol/communities/community_test.go index 9b3589b55..96e05b134 100644 --- a/protocol/communities/community_test.go +++ b/protocol/communities/community_test.go @@ -119,7 +119,7 @@ func (s *CommunitySuite) TestCreateChat() { Permissions: permissions, }) - s.Require().Equal(ErrNotAdmin, err) + s.Require().Equal(ErrNotAuthorized, err) org.config.PrivateKey = s.identity org.config.ID = &s.identity.PublicKey @@ -189,7 +189,7 @@ func (s *CommunitySuite) TestEditChat() { Identity: editedIdentity, Permissions: editedPermissions, }) - s.Require().Equal(ErrNotAdmin, err) + s.Require().Equal(ErrNotAuthorized, err) description := org.config.CommunityDescription org.config.PrivateKey = s.identity @@ -218,7 +218,7 @@ func (s *CommunitySuite) TestDeleteChat() { org.config.ID = nil _, err := org.DeleteChat(testChatID1) - s.Require().Equal(ErrNotAdmin, err) + s.Require().Equal(ErrNotAuthorized, err) org.config.PrivateKey = s.identity org.config.ID = &s.identity.PublicKey @@ -238,7 +238,7 @@ func (s *CommunitySuite) TestRemoveUserFromChat() { org.config.ID = nil // Not an admin _, err := org.RemoveUserFromOrg(&s.member1.PublicKey) - s.Require().Equal(ErrNotAdmin, err) + s.Require().Equal(ErrNotAuthorized, err) // Add admin to community org.config.PrivateKey = s.identity @@ -266,7 +266,7 @@ func (s *CommunitySuite) TestRemoveUserFormOrg() { org.config.ID = nil // Not an admin _, err := org.RemoveUserFromOrg(&s.member1.PublicKey) - s.Require().Equal(ErrNotAdmin, err) + s.Require().Equal(ErrNotAuthorized, err) // Add admin to community org.config.PrivateKey = s.identity diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index 8d72fba92..93c7728c1 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -840,13 +840,6 @@ func (m *Manager) EditCommunity(request *requests.EditCommunity) (*Community, er return nil, ErrOrgNotFound } - isControlNode := community.IsControlNode() - allowedToSendEvents := community.HasPermissionToSendCommunityEvents() - - if !isControlNode && !allowedToSendEvents { - return nil, ErrNotEnoughPermissions - } - newDescription, err := request.ToCommunityDescription() if err != nil { return nil, fmt.Errorf("Can't create community description: %v", err) @@ -876,11 +869,8 @@ func (m *Manager) EditCommunity(request *requests.EditCommunity) (*Community, er return nil, err } - if allowedToSendEvents { - err := community.addNewCommunityEvent(community.ToCommunityEditCommunityEvent(newDescription)) - if err != nil { - return nil, err - } + if !(community.IsControlNode() || community.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_EDIT)) { + return nil, ErrNotAuthorized } // Edit the community values @@ -889,8 +879,13 @@ func (m *Manager) EditCommunity(request *requests.EditCommunity) (*Community, er return nil, err } - if isControlNode { + if community.IsControlNode() { community.increaseClock() + } else { + err := community.addNewCommunityEvent(community.ToCommunityEditCommunityEvent(newDescription)) + if err != nil { + return nil, err + } } err = m.saveAndPublish(community) @@ -1878,7 +1873,7 @@ func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, err return nil, err } - if community.HasPermissionToSendCommunityEvents() && !community.IsControlNode() { + if community.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_ACCEPT) && !community.IsControlNode() { if dbRequest.MarkedAsPendingByPrivilegedAccount() { // if the request is in any pending state, it means our admin node has either // already made a decision in the past, or previously received a decision by diff --git a/protocol/communities/roles_authorization.go b/protocol/communities/roles_authorization.go index ad32a88d0..e9c981685 100644 --- a/protocol/communities/roles_authorization.go +++ b/protocol/communities/roles_authorization.go @@ -40,11 +40,10 @@ var adminAuthorizedPermissionTypes = []protobuf.CommunityTokenPermission_Type{ protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL, } -var tokenMasterAuthorizedPermissionTypes = append(adminAuthorizedPermissionTypes, []protobuf.CommunityTokenPermission_Type{ - protobuf.CommunityTokenPermission_BECOME_ADMIN, -}...) +var tokenMasterAuthorizedPermissionTypes = append(adminAuthorizedPermissionTypes, []protobuf.CommunityTokenPermission_Type{}...) var ownerAuthorizedPermissionTypes = append(tokenMasterAuthorizedPermissionTypes, []protobuf.CommunityTokenPermission_Type{ + protobuf.CommunityTokenPermission_BECOME_ADMIN, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, }...)