chore(community)_: reevaluateMembers optimization (#5169)
* chore(community)_: reevaluateMembers optinizations
This commit is contained in:
parent
948e09af03
commit
77541725aa
|
@ -2186,6 +2186,14 @@ func (o *Community) AddMemberToChat(chatID string, publicKey *ecdsa.PublicKey,
|
||||||
return changes, nil
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Community) PopulateChannelsWithAllMembers() {
|
||||||
|
members := o.Members()
|
||||||
|
for _, channel := range o.Chats() {
|
||||||
|
channel.Members = members
|
||||||
|
}
|
||||||
|
o.increaseClock()
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Community) PopulateChatWithAllMembers(chatID string) (*CommunityChanges, error) {
|
func (o *Community) PopulateChatWithAllMembers(chatID string) (*CommunityChanges, error) {
|
||||||
o.mutex.Lock()
|
o.mutex.Lock()
|
||||||
defer o.mutex.Unlock()
|
defer o.mutex.Unlock()
|
||||||
|
@ -2479,6 +2487,7 @@ func (o *Community) deleteTokenPermission(permissionID string) (*CommunityChange
|
||||||
changes := o.emptyCommunityChanges()
|
changes := o.emptyCommunityChanges()
|
||||||
|
|
||||||
changes.TokenPermissionsRemoved[permissionID] = NewCommunityTokenPermission(permission)
|
changes.TokenPermissionsRemoved[permissionID] = NewCommunityTokenPermission(permission)
|
||||||
|
|
||||||
return changes, nil
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -991,6 +991,11 @@ func (m *Manager) EditCommunityTokenPermission(request *requests.EditCommunityTo
|
||||||
return community, changes, nil
|
return community, changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use it only for testing purposes
|
||||||
|
func (m *Manager) ReevaluateMembers(communityID types.HexBytes) (*Community, map[protobuf.CommunityMember_Roles][]*ecdsa.PublicKey, error) {
|
||||||
|
return m.reevaluateMembers(communityID)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map[protobuf.CommunityMember_Roles][]*ecdsa.PublicKey, error) {
|
func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map[protobuf.CommunityMember_Roles][]*ecdsa.PublicKey, error) {
|
||||||
m.communityLock.Lock(communityID)
|
m.communityLock.Lock(communityID)
|
||||||
defer m.communityLock.Unlock(communityID)
|
defer m.communityLock.Unlock(communityID)
|
||||||
|
@ -1006,16 +1011,23 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
return nil, nil, ErrNotEnoughPermissions
|
return nil, nil, ErrNotEnoughPermissions
|
||||||
}
|
}
|
||||||
|
|
||||||
becomeMemberPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_MEMBER)
|
communityPermissionsPreParsedData, channelPermissionsPreParsedData := PreParsePermissionsData(community.tokenPermissions())
|
||||||
becomeAdminPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_ADMIN)
|
|
||||||
becomeTokenMasterPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
|
|
||||||
|
|
||||||
hasMemberPermissions := len(becomeMemberPermissions) > 0
|
hasMemberPermissions := communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_MEMBER] != nil
|
||||||
|
|
||||||
|
if len(channelPermissionsPreParsedData) == 0 {
|
||||||
|
community.PopulateChannelsWithAllMembers()
|
||||||
|
}
|
||||||
|
|
||||||
newPrivilegedRoles := make(map[protobuf.CommunityMember_Roles][]*ecdsa.PublicKey)
|
newPrivilegedRoles := make(map[protobuf.CommunityMember_Roles][]*ecdsa.PublicKey)
|
||||||
newPrivilegedRoles[protobuf.CommunityMember_ROLE_TOKEN_MASTER] = []*ecdsa.PublicKey{}
|
newPrivilegedRoles[protobuf.CommunityMember_ROLE_TOKEN_MASTER] = []*ecdsa.PublicKey{}
|
||||||
newPrivilegedRoles[protobuf.CommunityMember_ROLE_ADMIN] = []*ecdsa.PublicKey{}
|
newPrivilegedRoles[protobuf.CommunityMember_ROLE_ADMIN] = []*ecdsa.PublicKey{}
|
||||||
|
|
||||||
|
membersAccounts, err := m.persistence.GetCommunityRequestsToJoinRevealedAddresses(community.ID())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
for memberKey := range community.Members() {
|
for memberKey := range community.Members() {
|
||||||
memberPubKey, err := common.HexToPubkey(memberKey)
|
memberPubKey, err := common.HexToPubkey(memberKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1028,13 +1040,9 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
|
|
||||||
isCurrentRoleTokenMaster := community.IsMemberTokenMaster(memberPubKey)
|
isCurrentRoleTokenMaster := community.IsMemberTokenMaster(memberPubKey)
|
||||||
isCurrentRoleAdmin := community.IsMemberAdmin(memberPubKey)
|
isCurrentRoleAdmin := community.IsMemberAdmin(memberPubKey)
|
||||||
requestID := CalculateRequestID(memberKey, community.ID())
|
|
||||||
revealedAccounts, err := m.persistence.GetRequestToJoinRevealedAddresses(requestID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
memberHasWallet := len(revealedAccounts) > 0
|
revealedAccount, exists := membersAccounts[memberKey]
|
||||||
|
memberHasWallet := exists
|
||||||
|
|
||||||
// Check if user has privilege role without sharing the account to controlNode
|
// Check if user has privilege role without sharing the account to controlNode
|
||||||
// or user treated as a member without wallet in closed community
|
// or user treated as a member without wallet in closed community
|
||||||
|
@ -1046,9 +1054,13 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
accountsAndChainIDs := revealedAccountsToAccountsAndChainIDsCombination(revealedAccounts)
|
accountsAndChainIDs := revealedAccountsToAccountsAndChainIDsCombination(revealedAccount)
|
||||||
|
|
||||||
isNewRoleTokenMaster, err := m.ReevaluatePrivilegedMember(community, becomeTokenMasterPermissions, accountsAndChainIDs, memberPubKey,
|
isNewRoleTokenMaster, err := m.ReevaluatePrivilegedMember(
|
||||||
|
community,
|
||||||
|
communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER],
|
||||||
|
accountsAndChainIDs,
|
||||||
|
memberPubKey,
|
||||||
protobuf.CommunityMember_ROLE_TOKEN_MASTER, isCurrentRoleTokenMaster)
|
protobuf.CommunityMember_ROLE_TOKEN_MASTER, isCurrentRoleTokenMaster)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1064,7 +1076,11 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
isNewRoleAdmin, err := m.ReevaluatePrivilegedMember(community, becomeAdminPermissions, accountsAndChainIDs, memberPubKey,
|
isNewRoleAdmin, err := m.ReevaluatePrivilegedMember(
|
||||||
|
community,
|
||||||
|
communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_ADMIN],
|
||||||
|
accountsAndChainIDs,
|
||||||
|
memberPubKey,
|
||||||
protobuf.CommunityMember_ROLE_ADMIN, isCurrentRoleAdmin)
|
protobuf.CommunityMember_ROLE_ADMIN, isCurrentRoleAdmin)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1081,7 +1097,10 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasMemberPermissions {
|
if hasMemberPermissions {
|
||||||
permissionResponse, err := m.PermissionChecker.CheckPermissions(becomeMemberPermissions, accountsAndChainIDs, true)
|
permissionResponse, err := m.PermissionChecker.CheckPermissions(
|
||||||
|
communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_MEMBER],
|
||||||
|
accountsAndChainIDs,
|
||||||
|
true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1096,52 +1115,96 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate channel permissions
|
err = m.reevaluateMemberChannelsPermissions(community, memberPubKey, channelPermissionsPreParsedData, accountsAndChainIDs)
|
||||||
for channelID := range community.Chats() {
|
|
||||||
chatID := community.ChatID(channelID)
|
|
||||||
|
|
||||||
viewOnlyPermissions := community.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
|
|
||||||
viewAndPostPermissions := community.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
|
|
||||||
|
|
||||||
if len(viewOnlyPermissions) == 0 && len(viewAndPostPermissions) == 0 {
|
|
||||||
// ensure all members are added back if channel permissions were removed
|
|
||||||
_, err = community.PopulateChatWithAllMembers(channelID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountsAndChainIDs, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
isMemberAlreadyInChannel := community.IsMemberInChat(memberPubKey, channelID)
|
|
||||||
|
|
||||||
if response.ViewOnlyPermissions.Satisfied || response.ViewAndPostPermissions.Satisfied {
|
|
||||||
channelRole := protobuf.CommunityMember_CHANNEL_ROLE_VIEWER
|
|
||||||
if response.ViewAndPostPermissions.Satisfied {
|
|
||||||
channelRole = protobuf.CommunityMember_CHANNEL_ROLE_POSTER
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the member back to the chat member list in case the role changed (it replaces the previous values)
|
|
||||||
_, err := community.AddMemberToChat(channelID, memberPubKey, []protobuf.CommunityMember_Roles{}, channelRole)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
} else if isMemberAlreadyInChannel {
|
|
||||||
_, err := community.RemoveUserFromChat(memberPubKey, channelID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return community, newPrivilegedRoles, m.saveAndPublish(community)
|
return community, newPrivilegedRoles, m.saveAndPublish(community)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Manager) reevaluateMemberChannelsPermissions(community *Community, memberPubKey *ecdsa.PublicKey,
|
||||||
|
channelPermissionsPreParsedData map[string]*PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination) error {
|
||||||
|
|
||||||
|
if len(channelPermissionsPreParsedData) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check which permissions we satisfy and which not
|
||||||
|
channelPermissionsCheckResult, err := m.checkChannelsPermissions(channelPermissionsPreParsedData, accountsAndChainIDs, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for channelID := range community.Chats() {
|
||||||
|
chatID := community.ChatID(channelID)
|
||||||
|
isMemberAlreadyInChannel := community.IsMemberInChat(memberPubKey, channelID)
|
||||||
|
|
||||||
|
channelPermissionsCheckResult, exists := channelPermissionsCheckResult[chatID]
|
||||||
|
|
||||||
|
// if channel permissions were removed member must be added back
|
||||||
|
if !exists {
|
||||||
|
if !isMemberAlreadyInChannel {
|
||||||
|
_, err := community.AddMemberToChat(channelID, memberPubKey, []protobuf.CommunityMember_Roles{}, protobuf.CommunityMember_CHANNEL_ROLE_POSTER)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
viewAndPostSatisfied, viewAndPosPermissionExists := channelPermissionsCheckResult[protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL]
|
||||||
|
viewOnlySatisfied, viewOnlyPermissionExists := channelPermissionsCheckResult[protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL]
|
||||||
|
|
||||||
|
satisfied := false
|
||||||
|
channelRole := protobuf.CommunityMember_CHANNEL_ROLE_VIEWER
|
||||||
|
if viewAndPosPermissionExists && viewAndPostSatisfied {
|
||||||
|
satisfied = viewAndPostSatisfied
|
||||||
|
channelRole = protobuf.CommunityMember_CHANNEL_ROLE_POSTER
|
||||||
|
} else if !satisfied && viewOnlyPermissionExists {
|
||||||
|
satisfied = viewOnlySatisfied
|
||||||
|
}
|
||||||
|
|
||||||
|
if satisfied {
|
||||||
|
// Add the member back to the chat member list in case the role changed (it replaces the previous values)
|
||||||
|
_, err := community.AddMemberToChat(channelID, memberPubKey, []protobuf.CommunityMember_Roles{}, channelRole)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if !satisfied && isMemberAlreadyInChannel {
|
||||||
|
_, err := community.RemoveUserFromChat(memberPubKey, channelID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) checkChannelsPermissions(channelsPermissionsPreParsedData map[string]*PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (map[string]map[protobuf.CommunityTokenPermission_Type]bool, error) {
|
||||||
|
channelPermissionsCheckResult := make(map[string]map[protobuf.CommunityTokenPermission_Type]bool)
|
||||||
|
for _, channelsPermissionPreParsedData := range channelsPermissionsPreParsedData {
|
||||||
|
permissionResponse, err := m.PermissionChecker.CheckPermissions(channelsPermissionPreParsedData, accountsAndChainIDs, true)
|
||||||
|
if err != nil {
|
||||||
|
return channelPermissionsCheckResult, err
|
||||||
|
}
|
||||||
|
// Note: in `PreParsedCommunityPermissionsData` for channels there will be only one permission
|
||||||
|
// no need to iterate over `Permissions`
|
||||||
|
for _, chatId := range channelsPermissionPreParsedData.Permissions[0].ChatIds {
|
||||||
|
if _, exists := channelPermissionsCheckResult[chatId]; !exists {
|
||||||
|
channelPermissionsCheckResult[chatId] = make(map[protobuf.CommunityTokenPermission_Type]bool)
|
||||||
|
}
|
||||||
|
satisfied, exists := channelPermissionsCheckResult[chatId][channelsPermissionPreParsedData.Permissions[0].Type]
|
||||||
|
if exists && satisfied {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
channelPermissionsCheckResult[chatId][channelsPermissionPreParsedData.Permissions[0].Type] = permissionResponse.Satisfied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return channelPermissionsCheckResult, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) StartMembersReevaluationLoop(communityID types.HexBytes, reevaluateOnStart bool) {
|
func (m *Manager) StartMembersReevaluationLoop(communityID types.HexBytes, reevaluateOnStart bool) {
|
||||||
go m.reevaluateMembersLoop(communityID, reevaluateOnStart)
|
go m.reevaluateMembersLoop(communityID, reevaluateOnStart)
|
||||||
}
|
}
|
||||||
|
@ -2462,24 +2525,22 @@ func (m *Manager) CheckPermissionToJoin(id []byte, addresses []gethcommon.Addres
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.PermissionChecker.CheckPermissionToJoin(community, addresses)
|
return m.PermissionChecker.CheckPermissionToJoin(community, addresses)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) accountsSatisfyPermissionsToJoin(community *Community, accounts []*protobuf.RevealedAccount) (bool, protobuf.CommunityMember_Roles, error) {
|
func (m *Manager) accountsSatisfyPermissionsToJoin(
|
||||||
accountsAndChainIDs := revealedAccountsToAccountsAndChainIDsCombination(accounts)
|
communityPermissionsPreParsedData map[protobuf.CommunityTokenPermission_Type]*PreParsedCommunityPermissionsData,
|
||||||
becomeAdminPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_ADMIN)
|
accountsAndChainIDs []*AccountChainIDsCombination) (bool, protobuf.CommunityMember_Roles, error) {
|
||||||
becomeMemberPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_MEMBER)
|
|
||||||
becomeTokenMasterPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
|
|
||||||
|
|
||||||
if m.accountsHasPrivilegedPermission(becomeTokenMasterPermissions, accountsAndChainIDs) {
|
if m.accountsHasPrivilegedPermission(communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER], accountsAndChainIDs) {
|
||||||
return true, protobuf.CommunityMember_ROLE_TOKEN_MASTER, nil
|
return true, protobuf.CommunityMember_ROLE_TOKEN_MASTER, nil
|
||||||
}
|
}
|
||||||
if m.accountsHasPrivilegedPermission(becomeAdminPermissions, accountsAndChainIDs) {
|
if m.accountsHasPrivilegedPermission(communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_ADMIN], accountsAndChainIDs) {
|
||||||
return true, protobuf.CommunityMember_ROLE_ADMIN, nil
|
return true, protobuf.CommunityMember_ROLE_ADMIN, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(becomeMemberPermissions) > 0 {
|
preParsedBecomeMemberPermissions := communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_MEMBER]
|
||||||
permissionResponse, err := m.PermissionChecker.CheckPermissions(becomeMemberPermissions, accountsAndChainIDs, true)
|
if preParsedBecomeMemberPermissions != nil {
|
||||||
|
permissionResponse, err := m.PermissionChecker.CheckPermissions(preParsedBecomeMemberPermissions, accountsAndChainIDs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, protobuf.CommunityMember_ROLE_NONE, err
|
return false, protobuf.CommunityMember_ROLE_NONE, err
|
||||||
}
|
}
|
||||||
|
@ -2490,37 +2551,49 @@ func (m *Manager) accountsSatisfyPermissionsToJoin(community *Community, account
|
||||||
return true, protobuf.CommunityMember_ROLE_NONE, nil
|
return true, protobuf.CommunityMember_ROLE_NONE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) accountsSatisfyPermissionsToJoinChannels(community *Community, accounts []*protobuf.RevealedAccount) (map[string]*protobuf.CommunityChat, map[string]*protobuf.CommunityChat, error) {
|
func (m *Manager) accountsSatisfyPermissionsToJoinChannels(
|
||||||
|
community *Community,
|
||||||
|
channelPermissionsPreParsedData map[string]*PreParsedCommunityPermissionsData,
|
||||||
|
accountsAndChainIDs []*AccountChainIDsCombination) (map[string]*protobuf.CommunityChat, map[string]*protobuf.CommunityChat, error) {
|
||||||
|
|
||||||
viewChats := make(map[string]*protobuf.CommunityChat)
|
viewChats := make(map[string]*protobuf.CommunityChat)
|
||||||
viewAndPostChats := make(map[string]*protobuf.CommunityChat)
|
viewAndPostChats := make(map[string]*protobuf.CommunityChat)
|
||||||
|
|
||||||
accountsAndChainIDs := revealedAccountsToAccountsAndChainIDsCombination(accounts)
|
if len(channelPermissionsPreParsedData) == 0 {
|
||||||
|
for channelID, channel := range community.config.CommunityDescription.Chats {
|
||||||
|
viewAndPostChats[channelID] = channel
|
||||||
|
}
|
||||||
|
|
||||||
|
return viewChats, viewAndPostChats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check which permissions we satisfy and which not
|
||||||
|
channelPermissionsCheckResult, err := m.checkChannelsPermissions(channelPermissionsPreParsedData, accountsAndChainIDs, true)
|
||||||
|
if err != nil {
|
||||||
|
m.logger.Warn("check channel permission failed: %v", zap.Error(err))
|
||||||
|
return viewChats, viewAndPostChats, err
|
||||||
|
}
|
||||||
|
|
||||||
for channelID, channel := range community.config.CommunityDescription.Chats {
|
for channelID, channel := range community.config.CommunityDescription.Chats {
|
||||||
channelViewOnlyPermissions := community.ChannelTokenPermissionsByType(community.IDString()+channelID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
|
chatID := community.ChatID(channelID)
|
||||||
channelViewAndPostPermissions := community.ChannelTokenPermissionsByType(community.IDString()+channelID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
|
channelPermissionsCheckResult, exists := channelPermissionsCheckResult[chatID]
|
||||||
channelPermissions := append(channelViewOnlyPermissions, channelViewAndPostPermissions...)
|
|
||||||
|
|
||||||
if len(channelPermissions) == 0 {
|
if !exists {
|
||||||
viewAndPostChats[channelID] = channel
|
viewAndPostChats[channelID] = channel
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
permissionResponse, err := m.PermissionChecker.CheckPermissions(channelPermissions, accountsAndChainIDs, true)
|
viewAndPostSatisfied, exists := channelPermissionsCheckResult[protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL]
|
||||||
if err != nil {
|
if exists && viewAndPostSatisfied {
|
||||||
return nil, nil, err
|
delete(viewChats, channelID)
|
||||||
|
viewAndPostChats[channelID] = channel
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if permissionResponse.Satisfied {
|
viewOnlySatisfied, exists := channelPermissionsCheckResult[protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL]
|
||||||
highestRole := calculateRolesAndHighestRole(permissionResponse.Permissions).HighestRole
|
if exists && viewOnlySatisfied {
|
||||||
if highestRole == nil {
|
if _, exists := viewAndPostChats[channelID]; !exists {
|
||||||
return nil, nil, errors.New("failed to calculate highest role")
|
|
||||||
}
|
|
||||||
switch highestRole.Role {
|
|
||||||
case protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL:
|
|
||||||
viewChats[channelID] = channel
|
viewChats[channelID] = channel
|
||||||
case protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL:
|
|
||||||
viewAndPostChats[channelID] = channel
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2548,7 +2621,11 @@ func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, err
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
permissionsSatisfied, role, err := m.accountsSatisfyPermissionsToJoin(community, revealedAccounts)
|
accountsAndChainIDs := revealedAccountsToAccountsAndChainIDsCombination(revealedAccounts)
|
||||||
|
|
||||||
|
communityPermissionsPreParsedData, channelPermissionsPreParsedData := PreParsePermissionsData(community.tokenPermissions())
|
||||||
|
|
||||||
|
permissionsSatisfied, role, err := m.accountsSatisfyPermissionsToJoin(communityPermissionsPreParsedData, accountsAndChainIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -2567,7 +2644,7 @@ func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, err
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
viewChannels, postChannels, err := m.accountsSatisfyPermissionsToJoinChannels(community, revealedAccounts)
|
viewChannels, postChannels, err := m.accountsSatisfyPermissionsToJoinChannels(community, channelPermissionsPreParsedData, accountsAndChainIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -3001,6 +3078,8 @@ func (m *Manager) CheckChannelPermissions(communityID types.HexBytes, chatID str
|
||||||
|
|
||||||
viewOnlyPermissions := community.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
|
viewOnlyPermissions := community.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
|
||||||
viewAndPostPermissions := community.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
|
viewAndPostPermissions := community.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
|
||||||
|
viewOnlyPreParsedPermissions := preParsedCommunityPermissionsData(viewOnlyPermissions)
|
||||||
|
viewAndPostPreParsedPermissions := preParsedCommunityPermissionsData(viewAndPostPermissions)
|
||||||
|
|
||||||
allChainIDs, err := m.tokenManager.GetAllChainIDs()
|
allChainIDs, err := m.tokenManager.GetAllChainIDs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3008,7 +3087,7 @@ func (m *Manager) CheckChannelPermissions(communityID types.HexBytes, chatID str
|
||||||
}
|
}
|
||||||
accountsAndChainIDs := combineAddressesAndChainIDs(addresses, allChainIDs)
|
accountsAndChainIDs := combineAddressesAndChainIDs(addresses, allChainIDs)
|
||||||
|
|
||||||
response, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountsAndChainIDs, false)
|
response, err := m.checkChannelPermissions(viewOnlyPreParsedPermissions, viewAndPostPreParsedPermissions, accountsAndChainIDs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -3035,7 +3114,7 @@ type CheckChannelViewAndPostPermissionsResult struct {
|
||||||
Permissions map[string]*PermissionTokenCriteriaResult `json:"permissions"`
|
Permissions map[string]*PermissionTokenCriteriaResult `json:"permissions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) checkChannelPermissions(viewOnlyPermissions []*CommunityTokenPermission, viewAndPostPermissions []*CommunityTokenPermission, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckChannelPermissionsResponse, error) {
|
func (m *Manager) checkChannelPermissions(viewOnlyPreParsedPermissions *PreParsedCommunityPermissionsData, viewAndPostPreParsedPermissions *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckChannelPermissionsResponse, error) {
|
||||||
|
|
||||||
response := &CheckChannelPermissionsResponse{
|
response := &CheckChannelPermissionsResponse{
|
||||||
ViewOnlyPermissions: &CheckChannelViewOnlyPermissionsResult{
|
ViewOnlyPermissions: &CheckChannelViewOnlyPermissionsResult{
|
||||||
|
@ -3048,18 +3127,18 @@ func (m *Manager) checkChannelPermissions(viewOnlyPermissions []*CommunityTokenP
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
viewOnlyPermissionsResponse, err := m.PermissionChecker.CheckPermissions(viewOnlyPermissions, accountsAndChainIDs, shortcircuit)
|
viewOnlyPermissionsResponse, err := m.PermissionChecker.CheckPermissions(viewOnlyPreParsedPermissions, accountsAndChainIDs, shortcircuit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
viewAndPostPermissionsResponse, err := m.PermissionChecker.CheckPermissions(viewAndPostPermissions, accountsAndChainIDs, shortcircuit)
|
viewAndPostPermissionsResponse, err := m.PermissionChecker.CheckPermissions(viewAndPostPreParsedPermissions, accountsAndChainIDs, shortcircuit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hasViewOnlyPermissions := len(viewOnlyPermissions) > 0
|
hasViewOnlyPermissions := viewOnlyPreParsedPermissions != nil
|
||||||
hasViewAndPostPermissions := len(viewAndPostPermissions) > 0
|
hasViewAndPostPermissions := viewAndPostPreParsedPermissions != nil
|
||||||
|
|
||||||
if (hasViewAndPostPermissions && !hasViewOnlyPermissions) || (hasViewOnlyPermissions && hasViewAndPostPermissions && viewAndPostPermissionsResponse.Satisfied) {
|
if (hasViewAndPostPermissions && !hasViewOnlyPermissions) || (hasViewOnlyPermissions && hasViewAndPostPermissions && viewAndPostPermissionsResponse.Satisfied) {
|
||||||
response.ViewOnlyPermissions.Satisfied = viewAndPostPermissionsResponse.Satisfied
|
response.ViewOnlyPermissions.Satisfied = viewAndPostPermissionsResponse.Satisfied
|
||||||
|
@ -3096,11 +3175,13 @@ func (m *Manager) CheckAllChannelsPermissions(communityID types.HexBytes, addres
|
||||||
Channels: make(map[string]*CheckChannelPermissionsResponse),
|
Channels: make(map[string]*CheckChannelPermissionsResponse),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: optimize
|
||||||
for channelID := range channels {
|
for channelID := range channels {
|
||||||
viewOnlyPermissions := community.ChannelTokenPermissionsByType(community.IDString()+channelID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
|
viewOnlyPermissions := community.ChannelTokenPermissionsByType(community.IDString()+channelID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
|
||||||
viewAndPostPermissions := community.ChannelTokenPermissionsByType(community.IDString()+channelID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
|
viewAndPostPermissions := community.ChannelTokenPermissionsByType(community.IDString()+channelID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
|
||||||
|
viewOnlyPreParsedPermissions := preParsedCommunityPermissionsData(viewOnlyPermissions)
|
||||||
checkChannelPermissionsResponse, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountsAndChainIDs, false)
|
viewAndPostPreParsedPermissions := preParsedCommunityPermissionsData(viewAndPostPermissions)
|
||||||
|
checkChannelPermissionsResponse, err := m.checkChannelPermissions(viewOnlyPreParsedPermissions, viewAndPostPreParsedPermissions, accountsAndChainIDs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -4992,9 +5073,9 @@ func revealedAccountsToAccountsAndChainIDsCombination(revealedAccounts []*protob
|
||||||
return accountsAndChainIDs
|
return accountsAndChainIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) accountsHasPrivilegedPermission(privilegedPermissions []*CommunityTokenPermission, accounts []*AccountChainIDsCombination) bool {
|
func (m *Manager) accountsHasPrivilegedPermission(preParsedCommunityPermissionData *PreParsedCommunityPermissionsData, accounts []*AccountChainIDsCombination) bool {
|
||||||
if len(privilegedPermissions) > 0 {
|
if preParsedCommunityPermissionData != nil {
|
||||||
permissionResponse, err := m.PermissionChecker.CheckPermissions(privilegedPermissions, accounts, true)
|
permissionResponse, err := m.PermissionChecker.CheckPermissions(preParsedCommunityPermissionData, accounts, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Warn("check privileged permission failed: %v", zap.Error(err))
|
m.logger.Warn("check privileged permission failed: %v", zap.Error(err))
|
||||||
return false
|
return false
|
||||||
|
@ -5047,16 +5128,17 @@ func (m *Manager) GetRevealedAddresses(communityID types.HexBytes, memberPk stri
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) ReevaluatePrivilegedMember(community *Community, tokenPermissions []*CommunityTokenPermission,
|
func (m *Manager) ReevaluatePrivilegedMember(community *Community, permissionsData *PreParsedCommunityPermissionsData,
|
||||||
accountsAndChainIDs []*AccountChainIDsCombination, memberPubKey *ecdsa.PublicKey,
|
accountsAndChainIDs []*AccountChainIDsCombination, memberPubKey *ecdsa.PublicKey,
|
||||||
privilegedRole protobuf.CommunityMember_Roles, alreadyHasPrivilegedRole bool) (bool, error) {
|
privilegedRole protobuf.CommunityMember_Roles, alreadyHasPrivilegedRole bool) (bool, error) {
|
||||||
|
|
||||||
hasPrivilegedRolePermissions := len(tokenPermissions) > 0
|
hasPrivilegedRolePermissions := permissionsData != nil
|
||||||
removeCurrentRole := false
|
removeCurrentRole := false
|
||||||
|
|
||||||
if hasPrivilegedRolePermissions {
|
if hasPrivilegedRolePermissions {
|
||||||
permissionResponse, err := m.PermissionChecker.CheckPermissions(tokenPermissions, accountsAndChainIDs, true)
|
permissionResponse, err := m.PermissionChecker.CheckPermissions(permissionsData, accountsAndChainIDs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
m.logger.Warn("check privileged permission failed: %v", zap.Error(err))
|
||||||
return alreadyHasPrivilegedRole, err
|
return alreadyHasPrivilegedRole, err
|
||||||
} else if permissionResponse.Satisfied && !alreadyHasPrivilegedRole {
|
} else if permissionResponse.Satisfied && !alreadyHasPrivilegedRole {
|
||||||
_, err = community.AddRoleToMember(memberPubKey, privilegedRole)
|
_, err = community.AddRoleToMember(memberPubKey, privilegedRole)
|
||||||
|
|
|
@ -210,6 +210,8 @@ func (s *ManagerSuite) TestRetrieveTokens() {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preParsedPermissions := preParsedCommunityPermissionsData(permissions)
|
||||||
|
|
||||||
accountChainIDsCombination := []*AccountChainIDsCombination{
|
accountChainIDsCombination := []*AccountChainIDsCombination{
|
||||||
&AccountChainIDsCombination{
|
&AccountChainIDsCombination{
|
||||||
Address: gethcommon.HexToAddress("0xD6b912e09E797D291E8D0eA3D3D17F8000e01c32"),
|
Address: gethcommon.HexToAddress("0xD6b912e09E797D291E8D0eA3D3D17F8000e01c32"),
|
||||||
|
@ -218,14 +220,14 @@ func (s *ManagerSuite) TestRetrieveTokens() {
|
||||||
}
|
}
|
||||||
// Set response to exactly the right one
|
// Set response to exactly the right one
|
||||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), int64(1*math.Pow(10, float64(decimals))))
|
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), int64(1*math.Pow(10, float64(decimals))))
|
||||||
resp, err := m.PermissionChecker.CheckPermissions(permissions, accountChainIDsCombination, false)
|
resp, err := m.PermissionChecker.CheckPermissions(preParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
s.Require().True(resp.Satisfied)
|
s.Require().True(resp.Satisfied)
|
||||||
|
|
||||||
// Set response to 0
|
// Set response to 0
|
||||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
||||||
resp, err = m.PermissionChecker.CheckPermissions(permissions, accountChainIDsCombination, false)
|
resp, err = m.PermissionChecker.CheckPermissions(preParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
s.Require().False(resp.Satisfied)
|
s.Require().False(resp.Satisfied)
|
||||||
|
@ -259,6 +261,8 @@ func (s *ManagerSuite) TestRetrieveCollectibles() {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preParsedPermissions := preParsedCommunityPermissionsData(permissions)
|
||||||
|
|
||||||
accountChainIDsCombination := []*AccountChainIDsCombination{
|
accountChainIDsCombination := []*AccountChainIDsCombination{
|
||||||
&AccountChainIDsCombination{
|
&AccountChainIDsCombination{
|
||||||
Address: gethcommon.HexToAddress("0xD6b912e09E797D291E8D0eA3D3D17F8000e01c32"),
|
Address: gethcommon.HexToAddress("0xD6b912e09E797D291E8D0eA3D3D17F8000e01c32"),
|
||||||
|
@ -269,7 +273,7 @@ func (s *ManagerSuite) TestRetrieveCollectibles() {
|
||||||
// Set response to exactly the right one
|
// Set response to exactly the right one
|
||||||
tokenBalances = []thirdparty.TokenBalance{tokenBalance(tokenID, 1)}
|
tokenBalances = []thirdparty.TokenBalance{tokenBalance(tokenID, 1)}
|
||||||
cm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), tokenBalances)
|
cm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), tokenBalances)
|
||||||
resp, err := m.PermissionChecker.CheckPermissions(permissions, accountChainIDsCombination, false)
|
resp, err := m.PermissionChecker.CheckPermissions(preParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
s.Require().True(resp.Satisfied)
|
s.Require().True(resp.Satisfied)
|
||||||
|
@ -277,7 +281,7 @@ func (s *ManagerSuite) TestRetrieveCollectibles() {
|
||||||
// Set balances to 0
|
// Set balances to 0
|
||||||
tokenBalances = []thirdparty.TokenBalance{}
|
tokenBalances = []thirdparty.TokenBalance{}
|
||||||
cm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), tokenBalances)
|
cm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), tokenBalances)
|
||||||
resp, err = m.PermissionChecker.CheckPermissions(permissions, accountChainIDsCombination, false)
|
resp, err = m.PermissionChecker.CheckPermissions(preParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
s.Require().False(resp.Satisfied)
|
s.Require().False(resp.Satisfied)
|
||||||
|
@ -932,9 +936,11 @@ func (s *ManagerSuite) TestCheckChannelPermissions_NoPermissions() {
|
||||||
|
|
||||||
var viewOnlyPermissions = make([]*CommunityTokenPermission, 0)
|
var viewOnlyPermissions = make([]*CommunityTokenPermission, 0)
|
||||||
var viewAndPostPermissions = make([]*CommunityTokenPermission, 0)
|
var viewAndPostPermissions = make([]*CommunityTokenPermission, 0)
|
||||||
|
viewOnlyPreParsedPermissions := preParsedCommunityPermissionsData(viewOnlyPermissions)
|
||||||
|
viewAndPostPreParsedPermissions := preParsedCommunityPermissionsData(viewAndPostPermissions)
|
||||||
|
|
||||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
||||||
resp, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
resp, err := m.checkChannelPermissions(viewOnlyPreParsedPermissions, viewAndPostPreParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
|
|
||||||
|
@ -984,8 +990,11 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewOnlyPermissions() {
|
||||||
|
|
||||||
var viewAndPostPermissions = make([]*CommunityTokenPermission, 0)
|
var viewAndPostPermissions = make([]*CommunityTokenPermission, 0)
|
||||||
|
|
||||||
|
viewOnlyPreParsedPermissions := preParsedCommunityPermissionsData(viewOnlyPermissions)
|
||||||
|
viewAndPostPreParsedPermissions := preParsedCommunityPermissionsData(viewAndPostPermissions)
|
||||||
|
|
||||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
||||||
resp, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
resp, err := m.checkChannelPermissions(viewOnlyPreParsedPermissions, viewAndPostPreParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
|
|
||||||
|
@ -996,7 +1005,7 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewOnlyPermissions() {
|
||||||
|
|
||||||
// Set response to exactly the right one
|
// Set response to exactly the right one
|
||||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), int64(1*math.Pow(10, float64(decimals))))
|
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), int64(1*math.Pow(10, float64(decimals))))
|
||||||
resp, err = m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
resp, err = m.checkChannelPermissions(viewOnlyPreParsedPermissions, viewAndPostPreParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
|
|
||||||
|
@ -1044,8 +1053,11 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewAndPostPermissions() {
|
||||||
|
|
||||||
var viewOnlyPermissions = make([]*CommunityTokenPermission, 0)
|
var viewOnlyPermissions = make([]*CommunityTokenPermission, 0)
|
||||||
|
|
||||||
|
viewOnlyPreParsedPermissions := preParsedCommunityPermissionsData(viewOnlyPermissions)
|
||||||
|
viewAndPostPreParsedPermissions := preParsedCommunityPermissionsData(viewAndPostPermissions)
|
||||||
|
|
||||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
||||||
resp, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
resp, err := m.checkChannelPermissions(viewOnlyPreParsedPermissions, viewAndPostPreParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
|
|
||||||
|
@ -1056,7 +1068,7 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewAndPostPermissions() {
|
||||||
|
|
||||||
// Set response to exactly the right one
|
// Set response to exactly the right one
|
||||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), int64(1*math.Pow(10, float64(decimals))))
|
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), int64(1*math.Pow(10, float64(decimals))))
|
||||||
resp, err = m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
resp, err = m.checkChannelPermissions(viewOnlyPreParsedPermissions, viewAndPostPreParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
|
|
||||||
|
@ -1134,7 +1146,10 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewAndPostPermissionsCombina
|
||||||
// Set resopnse for viewAndPost permissions
|
// Set resopnse for viewAndPost permissions
|
||||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(testContractAddresses[chainID]), 0)
|
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(testContractAddresses[chainID]), 0)
|
||||||
|
|
||||||
resp, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
viewOnlyPreParsedPermissions := preParsedCommunityPermissionsData(viewOnlyPermissions)
|
||||||
|
viewAndPostPreParsedPermissions := preParsedCommunityPermissionsData(viewAndPostPermissions)
|
||||||
|
|
||||||
|
resp, err := m.checkChannelPermissions(viewOnlyPreParsedPermissions, viewAndPostPreParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
|
|
||||||
|
@ -1213,7 +1228,10 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewAndPostPermissionsCombina
|
||||||
// Set resopnse for viewAndPost permissions
|
// Set resopnse for viewAndPost permissions
|
||||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(testContractAddresses[chainID]), int64(1*math.Pow(10, float64(decimals))))
|
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(testContractAddresses[chainID]), int64(1*math.Pow(10, float64(decimals))))
|
||||||
|
|
||||||
resp, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
viewOnlyPreParsedPermissions := preParsedCommunityPermissionsData(viewOnlyPermissions)
|
||||||
|
viewAndPostPreParsedPermissions := preParsedCommunityPermissionsData(viewAndPostPermissions)
|
||||||
|
|
||||||
|
resp, err := m.checkChannelPermissions(viewOnlyPreParsedPermissions, viewAndPostPreParsedPermissions, accountChainIDsCombination, false)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(resp)
|
s.Require().NotNil(resp)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
type PermissionChecker interface {
|
type PermissionChecker interface {
|
||||||
CheckPermissionToJoin(*Community, []gethcommon.Address) (*CheckPermissionToJoinResponse, error)
|
CheckPermissionToJoin(*Community, []gethcommon.Address) (*CheckPermissionToJoinResponse, error)
|
||||||
CheckPermissions(permissions []*CommunityTokenPermission, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error)
|
CheckPermissions(permissionsParsedData *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultPermissionChecker struct {
|
type DefaultPermissionChecker struct {
|
||||||
|
@ -33,6 +33,18 @@ type DefaultPermissionChecker struct {
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PreParsedPermissionsData struct {
|
||||||
|
Erc721TokenRequirements map[uint64]map[string]*protobuf.TokenCriteria
|
||||||
|
Erc20TokenAddresses []gethcommon.Address
|
||||||
|
Erc20ChainIDsMap map[uint64]bool
|
||||||
|
Erc721ChainIDsMap map[uint64]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type PreParsedCommunityPermissionsData struct {
|
||||||
|
*PreParsedPermissionsData
|
||||||
|
Permissions []*CommunityTokenPermission
|
||||||
|
}
|
||||||
|
|
||||||
func (p *DefaultPermissionChecker) getOwnedENS(addresses []gethcommon.Address) ([]string, error) {
|
func (p *DefaultPermissionChecker) getOwnedENS(addresses []gethcommon.Address) ([]string, error) {
|
||||||
ownedENS := make([]string, 0)
|
ownedENS := make([]string, 0)
|
||||||
if p.ensVerifier == nil {
|
if p.ensVerifier == nil {
|
||||||
|
@ -159,8 +171,8 @@ func (p *DefaultPermissionChecker) CheckPermissionToJoin(community *Community, a
|
||||||
return becomeMemberPermissionsResponse, nil
|
return becomeMemberPermissionsResponse, nil
|
||||||
}
|
}
|
||||||
// If there are any admin or token master permissions, combine result.
|
// If there are any admin or token master permissions, combine result.
|
||||||
|
preParsedPermissions := preParsedCommunityPermissionsData(adminOrTokenMasterPermissionsToJoin)
|
||||||
adminOrTokenPermissionsResponse, err := p.CheckPermissions(adminOrTokenMasterPermissionsToJoin, accountsAndChainIDs, false)
|
adminOrTokenPermissionsResponse, err := p.CheckPermissions(preParsedPermissions, accountsAndChainIDs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -191,13 +203,15 @@ func (p *DefaultPermissionChecker) checkPermissionsOrDefault(permissions []*Comm
|
||||||
}
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
return p.CheckPermissions(permissions, accountsAndChainIDs, false)
|
|
||||||
|
preParsedPermissions := preParsedCommunityPermissionsData(permissions)
|
||||||
|
return p.CheckPermissions(preParsedPermissions, accountsAndChainIDs, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckPermissions will retrieve balances and check whether the user has
|
// CheckPermissions will retrieve balances and check whether the user has
|
||||||
// permission to join the community, if shortcircuit is true, it will stop as soon
|
// permission to join the community, if shortcircuit is true, it will stop as soon
|
||||||
// as we know the answer
|
// as we know the answer
|
||||||
func (p *DefaultPermissionChecker) CheckPermissions(permissions []*CommunityTokenPermission, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error) {
|
func (p *DefaultPermissionChecker) CheckPermissions(permissionsParsedData *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error) {
|
||||||
|
|
||||||
response := &CheckPermissionsResponse{
|
response := &CheckPermissionsResponse{
|
||||||
Satisfied: false,
|
Satisfied: false,
|
||||||
|
@ -205,30 +219,25 @@ func (p *DefaultPermissionChecker) CheckPermissions(permissions []*CommunityToke
|
||||||
ValidCombinations: make([]*AccountChainIDsCombination, 0),
|
ValidCombinations: make([]*AccountChainIDsCombination, 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
erc20TokenRequirements, erc721TokenRequirements, _ := ExtractTokenCriteria(permissions)
|
if permissionsParsedData == nil {
|
||||||
|
response.Satisfied = true
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
erc20ChainIDsMap := make(map[uint64]bool)
|
erc721TokenRequirements := permissionsParsedData.Erc721TokenRequirements
|
||||||
erc721ChainIDsMap := make(map[uint64]bool)
|
|
||||||
|
erc20ChainIDsMap := permissionsParsedData.Erc20ChainIDsMap
|
||||||
|
erc721ChainIDsMap := permissionsParsedData.Erc721ChainIDsMap
|
||||||
|
|
||||||
|
erc20TokenAddresses := permissionsParsedData.Erc20TokenAddresses
|
||||||
|
|
||||||
erc20TokenAddresses := make([]gethcommon.Address, 0)
|
|
||||||
accounts := make([]gethcommon.Address, 0)
|
accounts := make([]gethcommon.Address, 0)
|
||||||
|
|
||||||
|
// TODO: move outside in order not to convert it
|
||||||
for _, accountAndChainIDs := range accountsAndChainIDs {
|
for _, accountAndChainIDs := range accountsAndChainIDs {
|
||||||
accounts = append(accounts, accountAndChainIDs.Address)
|
accounts = append(accounts, accountAndChainIDs.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
// figure out chain IDs we're interested in
|
|
||||||
for chainID, tokens := range erc20TokenRequirements {
|
|
||||||
erc20ChainIDsMap[chainID] = true
|
|
||||||
for contractAddress := range tokens {
|
|
||||||
erc20TokenAddresses = append(erc20TokenAddresses, gethcommon.HexToAddress(contractAddress))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for chainID := range erc721TokenRequirements {
|
|
||||||
erc721ChainIDsMap[chainID] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
chainIDsForERC20 := calculateChainIDsSet(accountsAndChainIDs, erc20ChainIDsMap)
|
chainIDsForERC20 := calculateChainIDsSet(accountsAndChainIDs, erc20ChainIDsMap)
|
||||||
chainIDsForERC721 := calculateChainIDsSet(accountsAndChainIDs, erc721ChainIDsMap)
|
chainIDsForERC721 := calculateChainIDsSet(accountsAndChainIDs, erc721ChainIDsMap)
|
||||||
|
|
||||||
|
@ -260,7 +269,7 @@ func (p *DefaultPermissionChecker) CheckPermissions(permissions []*CommunityToke
|
||||||
|
|
||||||
accountsChainIDsCombinations := make(map[gethcommon.Address]map[uint64]bool)
|
accountsChainIDsCombinations := make(map[gethcommon.Address]map[uint64]bool)
|
||||||
|
|
||||||
for _, tokenPermission := range permissions {
|
for _, tokenPermission := range permissionsParsedData.Permissions {
|
||||||
|
|
||||||
permissionRequirementsMet := true
|
permissionRequirementsMet := true
|
||||||
response.Permissions[tokenPermission.Id] = &PermissionTokenCriteriaResult{Role: tokenPermission.Type}
|
response.Permissions[tokenPermission.Id] = &PermissionTokenCriteriaResult{Role: tokenPermission.Type}
|
||||||
|
@ -435,3 +444,64 @@ func (p *DefaultPermissionChecker) CheckPermissions(permissions []*CommunityToke
|
||||||
|
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func preParsedPermissionsData(permissions []*CommunityTokenPermission) *PreParsedPermissionsData {
|
||||||
|
erc20TokenRequirements, erc721TokenRequirements, _ := ExtractTokenCriteria(permissions)
|
||||||
|
|
||||||
|
erc20ChainIDsMap := make(map[uint64]bool)
|
||||||
|
erc721ChainIDsMap := make(map[uint64]bool)
|
||||||
|
|
||||||
|
erc20TokenAddresses := make([]gethcommon.Address, 0)
|
||||||
|
|
||||||
|
// figure out chain IDs we're interested in
|
||||||
|
for chainID, tokens := range erc20TokenRequirements {
|
||||||
|
erc20ChainIDsMap[chainID] = true
|
||||||
|
for contractAddress := range tokens {
|
||||||
|
erc20TokenAddresses = append(erc20TokenAddresses, gethcommon.HexToAddress(contractAddress))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for chainID := range erc721TokenRequirements {
|
||||||
|
erc721ChainIDsMap[chainID] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return &PreParsedPermissionsData{
|
||||||
|
Erc721TokenRequirements: erc721TokenRequirements,
|
||||||
|
Erc20TokenAddresses: erc20TokenAddresses,
|
||||||
|
Erc20ChainIDsMap: erc20ChainIDsMap,
|
||||||
|
Erc721ChainIDsMap: erc721ChainIDsMap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func preParsedCommunityPermissionsData(permissions []*CommunityTokenPermission) *PreParsedCommunityPermissionsData {
|
||||||
|
if len(permissions) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &PreParsedCommunityPermissionsData{
|
||||||
|
Permissions: permissions,
|
||||||
|
PreParsedPermissionsData: preParsedPermissionsData(permissions),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func PreParsePermissionsData(permissions map[string]*CommunityTokenPermission) (map[protobuf.CommunityTokenPermission_Type]*PreParsedCommunityPermissionsData, map[string]*PreParsedCommunityPermissionsData) {
|
||||||
|
becomeMemberPermissions := TokenPermissionsByType(permissions, protobuf.CommunityTokenPermission_BECOME_MEMBER)
|
||||||
|
becomeAdminPermissions := TokenPermissionsByType(permissions, protobuf.CommunityTokenPermission_BECOME_ADMIN)
|
||||||
|
becomeTokenMasterPermissions := TokenPermissionsByType(permissions, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
|
||||||
|
|
||||||
|
viewOnlyPermissions := TokenPermissionsByType(permissions, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
|
||||||
|
viewAndPostPermissions := TokenPermissionsByType(permissions, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
|
||||||
|
channelPermissions := append(viewAndPostPermissions, viewOnlyPermissions...)
|
||||||
|
|
||||||
|
communityPermissionsPreParsedData := make(map[protobuf.CommunityTokenPermission_Type]*PreParsedCommunityPermissionsData)
|
||||||
|
communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_MEMBER] = preParsedCommunityPermissionsData(becomeMemberPermissions)
|
||||||
|
communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_ADMIN] = preParsedCommunityPermissionsData(becomeAdminPermissions)
|
||||||
|
communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER] = preParsedCommunityPermissionsData(becomeTokenMasterPermissions)
|
||||||
|
|
||||||
|
channelPermissionsPreParsedData := make(map[string]*PreParsedCommunityPermissionsData)
|
||||||
|
for _, channelPermission := range channelPermissions {
|
||||||
|
channelPermissionsPreParsedData[channelPermission.Id] = preParsedCommunityPermissionsData([]*CommunityTokenPermission{channelPermission})
|
||||||
|
}
|
||||||
|
|
||||||
|
return communityPermissionsPreParsedData, channelPermissionsPreParsedData
|
||||||
|
}
|
||||||
|
|
|
@ -2055,3 +2055,59 @@ func (p *Persistence) getDecryptedCommunityDescriptionByID(tx *sql.Tx, community
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Persistence) GetCommunityRequestsToJoinRevealedAddresses(communityID []byte) (map[string][]*protobuf.RevealedAccount, error) {
|
||||||
|
accounts := make(map[string][]*protobuf.RevealedAccount)
|
||||||
|
|
||||||
|
rows, err := p.db.Query(`
|
||||||
|
SELECT r.public_key,
|
||||||
|
a.address, a.chain_ids, a.is_airdrop_address, a.signature
|
||||||
|
FROM communities_requests_to_join r
|
||||||
|
LEFT JOIN communities_requests_to_join_revealed_addresses a ON r.id = a.request_id
|
||||||
|
WHERE r.community_id = ? AND r.state = ?`, communityID, RequestToJoinStateAccepted)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return accounts, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var rawPublicKey sql.NullString
|
||||||
|
var address sql.NullString
|
||||||
|
var chainIDsStr sql.NullString
|
||||||
|
var isAirdropAddress sql.NullBool
|
||||||
|
var signature sql.RawBytes
|
||||||
|
|
||||||
|
err = rows.Scan(&rawPublicKey, &address, &chainIDsStr, &isAirdropAddress, &signature)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !rawPublicKey.Valid {
|
||||||
|
return nil, errors.New("GetCommunityRequestsToJoinRevealedAddresses: invalid public key")
|
||||||
|
}
|
||||||
|
|
||||||
|
publicKey := rawPublicKey.String
|
||||||
|
|
||||||
|
revealedAccount, err := toRevealedAccount(address, chainIDsStr, isAirdropAddress, signature)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if revealedAccount == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists := accounts[publicKey]; !exists {
|
||||||
|
accounts[publicKey] = []*protobuf.RevealedAccount{revealedAccount}
|
||||||
|
} else {
|
||||||
|
accounts[publicKey] = append(accounts[publicKey], revealedAccount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return accounts, nil
|
||||||
|
}
|
||||||
|
|
|
@ -1051,3 +1051,55 @@ func (s *PersistenceSuite) TestDecryptedCommunityCacheClock() {
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(count, 1)
|
s.Require().Equal(count, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PersistenceSuite) TestGetCommunityRequestsToJoinRevealedAddresses() {
|
||||||
|
clock := uint64(time.Now().Unix())
|
||||||
|
communityID := types.HexBytes{7, 7, 7, 7, 7, 7, 7, 7}
|
||||||
|
revealedAddress := "address1"
|
||||||
|
chainIds := []uint64{1, 2}
|
||||||
|
publicKey := common.PubkeyToHex(&s.identity.PublicKey)
|
||||||
|
signature := []byte("test")
|
||||||
|
|
||||||
|
// No data in database
|
||||||
|
accounts, err := s.db.GetCommunityRequestsToJoinRevealedAddresses(communityID)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
_, exists := accounts[publicKey]
|
||||||
|
s.Require().False(exists)
|
||||||
|
|
||||||
|
expectedRtj := &RequestToJoin{
|
||||||
|
ID: types.HexBytes{1, 2, 3, 4, 5, 6, 7, 8},
|
||||||
|
PublicKey: publicKey,
|
||||||
|
Clock: clock,
|
||||||
|
CommunityID: communityID,
|
||||||
|
State: RequestToJoinStateAccepted,
|
||||||
|
RevealedAccounts: []*protobuf.RevealedAccount{
|
||||||
|
{
|
||||||
|
Address: revealedAddress,
|
||||||
|
ChainIds: chainIds,
|
||||||
|
IsAirdropAddress: true,
|
||||||
|
Signature: signature,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request to join was stored without revealed account
|
||||||
|
err = s.db.SaveRequestToJoin(expectedRtj)
|
||||||
|
s.Require().NoError(err, "SaveRequestToJoin shouldn't give any error")
|
||||||
|
|
||||||
|
// revealed account is absent
|
||||||
|
accounts, err = s.db.GetCommunityRequestsToJoinRevealedAddresses(communityID)
|
||||||
|
s.Require().NoError(err, "RevealedAccounts empty, shouldn't give any error")
|
||||||
|
|
||||||
|
_, exists = accounts[publicKey]
|
||||||
|
s.Require().False(exists)
|
||||||
|
|
||||||
|
// save revealed accounts for the previous request to join
|
||||||
|
err = s.db.SaveRequestToJoinRevealedAddresses(expectedRtj.ID, expectedRtj.RevealedAccounts)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
accounts, err = s.db.GetCommunityRequestsToJoinRevealedAddresses(communityID)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
memberAccounts, exists := accounts[publicKey]
|
||||||
|
s.Require().True(exists)
|
||||||
|
s.Require().Len(memberAccounts, 1)
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func ExtractTokenCriteria(permissions []*CommunityTokenPermission) (erc20TokenCr
|
||||||
if isERC20 && !existsERC20 {
|
if isERC20 && !existsERC20 {
|
||||||
erc20TokenCriteria[chainID] = make(map[string]*protobuf.TokenCriteria)
|
erc20TokenCriteria[chainID] = make(map[string]*protobuf.TokenCriteria)
|
||||||
}
|
}
|
||||||
|
// TODO: check if we do not duplicate this due to ToLower case
|
||||||
_, existsERC721 = erc721TokenCriteria[chainID][contractAddress]
|
_, existsERC721 = erc721TokenCriteria[chainID][contractAddress]
|
||||||
if isERC721 && !existsERC721 {
|
if isERC721 && !existsERC721 {
|
||||||
erc721TokenCriteria[chainID][strings.ToLower(contractAddress)] = tokenRequirement
|
erc721TokenCriteria[chainID][strings.ToLower(contractAddress)] = tokenRequirement
|
||||||
|
|
|
@ -3619,7 +3619,8 @@ func (t *testPermissionChecker) CheckPermissionToJoin(*communities.Community, []
|
||||||
return &communities.CheckPermissionsResponse{Satisfied: true}, nil
|
return &communities.CheckPermissionsResponse{Satisfied: true}, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
func (t *testPermissionChecker) CheckPermissions(permissions []*communities.CommunityTokenPermission, accountsAndChainIDs []*communities.AccountChainIDsCombination, shortcircuit bool) (*communities.CheckPermissionsResponse, error) {
|
|
||||||
|
func (t *testPermissionChecker) CheckPermissions(permissionsParsedData *communities.PreParsedCommunityPermissionsData, accountsAndChainIDs []*communities.AccountChainIDsCombination, shortcircuit bool) (*communities.CheckPermissionsResponse, error) {
|
||||||
return &communities.CheckPermissionsResponse{Satisfied: true}, nil
|
return &communities.CheckPermissionsResponse{Satisfied: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,13 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
@ -2011,3 +2013,122 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestResendEncryptionKeyOnBac
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Len(response.Messages(), 1)
|
s.Require().Len(response.Messages(), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MessengerCommunitiesTokenPermissionsSuite) TestReevaluateMemberPermissionsPerformance() {
|
||||||
|
// This test is created for a performance degradation tracking for reevaluateMember permissions
|
||||||
|
// current scenario mostly track channels permissions reevaluating, but feel free to expand it to
|
||||||
|
// other scenarios or test you performance improvements
|
||||||
|
|
||||||
|
// in average, it took nearly 100-105 ms to check one permission for a current scenario:
|
||||||
|
// - 10 members
|
||||||
|
// - 10 channels
|
||||||
|
// - one permission (channel permission for all 10 channels is set up)
|
||||||
|
|
||||||
|
// currently, adding any new permission to test must twice the current test average time
|
||||||
|
|
||||||
|
community, chat := s.createCommunity()
|
||||||
|
|
||||||
|
community, err := s.owner.communitiesManager.GetByID(community.ID())
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(community.Chats(), 2)
|
||||||
|
|
||||||
|
requestToJoin := &communities.RequestToJoin{
|
||||||
|
Clock: uint64(time.Now().Unix()),
|
||||||
|
CommunityID: community.ID(),
|
||||||
|
State: communities.RequestToJoinStateAccepted,
|
||||||
|
RevealedAccounts: []*protobuf.RevealedAccount{
|
||||||
|
{
|
||||||
|
Address: bobAddress,
|
||||||
|
ChainIds: []uint64{testChainID1},
|
||||||
|
IsAirdropAddress: true,
|
||||||
|
Signature: []byte("test"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
communityRole := []protobuf.CommunityMember_Roles{}
|
||||||
|
|
||||||
|
keysCount := 10
|
||||||
|
|
||||||
|
for i := 0; i < keysCount; i++ {
|
||||||
|
privateKey, err := crypto.GenerateKey()
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
memberPubKeyStr := common.PubkeyToHex(&privateKey.PublicKey)
|
||||||
|
requestId := communities.CalculateRequestID(memberPubKeyStr, community.ID())
|
||||||
|
requestToJoin.ID = requestId
|
||||||
|
requestToJoin.PublicKey = memberPubKeyStr
|
||||||
|
|
||||||
|
err = s.owner.communitiesManager.SaveRequestToJoin(requestToJoin)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
err = s.owner.communitiesManager.SaveRequestToJoinRevealedAddresses(requestId, requestToJoin.RevealedAccounts)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
_, err = community.AddMember(&privateKey.PublicKey, communityRole)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
_, err = community.AddMemberToChat(chat.CommunityChatID(), &privateKey.PublicKey, communityRole, protobuf.CommunityMember_CHANNEL_ROLE_POSTER)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Require().Equal(community.MembersCount(), keysCount+1) // 1 is owner
|
||||||
|
|
||||||
|
chatsCount := 8 // in total will be 10, 2 channels were created during creating the community
|
||||||
|
|
||||||
|
for i := 0; i < chatsCount; i++ {
|
||||||
|
newChat := &protobuf.CommunityChat{
|
||||||
|
Permissions: &protobuf.CommunityPermissions{
|
||||||
|
Access: protobuf.CommunityPermissions_AUTO_ACCEPT,
|
||||||
|
},
|
||||||
|
Identity: &protobuf.ChatIdentity{
|
||||||
|
DisplayName: "name-" + strconv.Itoa(i),
|
||||||
|
Description: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
chatID := uuid.New().String()
|
||||||
|
_, err = community.CreateChat(chatID, newChat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Require().Len(community.Chats(), chatsCount+2) // 2 chats were created during community creation
|
||||||
|
|
||||||
|
err = s.owner.communitiesManager.SaveCommunity(community)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
// setup view channel permission
|
||||||
|
channelPermissionRequest := requests.CreateCommunityTokenPermission{
|
||||||
|
CommunityID: community.ID(),
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: []*protobuf.TokenCriteria{
|
||||||
|
&protobuf.TokenCriteria{
|
||||||
|
Type: protobuf.CommunityTokenType_ERC20,
|
||||||
|
ContractAddresses: map[uint64]string{testChainID1: "0x123"},
|
||||||
|
Symbol: "TEST",
|
||||||
|
AmountInWei: "100000000000000000000",
|
||||||
|
Decimals: uint64(18),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ChatIds: community.ChatIDs(),
|
||||||
|
}
|
||||||
|
|
||||||
|
s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, channelPermissionRequest.TokenCriteria[0])
|
||||||
|
defer s.resetMockedBalances() // reset mocked balances, this test in run with different test cases
|
||||||
|
|
||||||
|
// create permission using communitiesManager in order not to launch blocking reevaluation loop
|
||||||
|
community, _, err = s.owner.communitiesManager.CreateCommunityTokenPermission(&channelPermissionRequest)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(community.TokenPermissions(), 1)
|
||||||
|
|
||||||
|
for _, ids := range community.ChatIDs() {
|
||||||
|
s.Require().True(s.owner.communitiesManager.IsChannelEncrypted(community.IDString(), ids))
|
||||||
|
}
|
||||||
|
|
||||||
|
// force owner to reevaluate channel members
|
||||||
|
// in production it will happen automatically, by periodic check
|
||||||
|
start := time.Now()
|
||||||
|
_, _, err = s.owner.communitiesManager.ReevaluateMembers(community.ID())
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
elapsed := time.Since(start)
|
||||||
|
|
||||||
|
fmt.Println("ReevaluateMembers Time: ", elapsed)
|
||||||
|
s.Require().Less(elapsed.Seconds(), 2.0)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue