feat: add CommunityEncryptionKeyActions and its evaluation logic
Added utility that evaluates necessary encryption key actions based on community changes. part of: status-im/status-desktop#10998
This commit is contained in:
parent
84bfdf4aab
commit
d9df8b6150
|
@ -1018,6 +1018,14 @@ func (o *Community) UpdateCommunityDescription(description *protobuf.CommunityDe
|
||||||
o.mutex.Lock()
|
o.mutex.Lock()
|
||||||
defer o.mutex.Unlock()
|
defer o.mutex.Unlock()
|
||||||
|
|
||||||
|
// This is done in case tags are updated and a client sends unknown tags
|
||||||
|
description.Tags = requests.RemoveUnknownAndDeduplicateTags(description.Tags)
|
||||||
|
|
||||||
|
err := ValidateCommunityDescription(description)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
response := o.emptyCommunityChanges()
|
response := o.emptyCommunityChanges()
|
||||||
|
|
||||||
// allowEqualClock == true only if this was a description from the handling request to join sent by an admin
|
// allowEqualClock == true only if this was a description from the handling request to join sent by an admin
|
||||||
|
@ -1029,9 +1037,10 @@ func (o *Community) UpdateCommunityDescription(description *protobuf.CommunityDe
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := o.collectCommunityChanges(description)
|
// We only calculate changes if we joined/spectated the community or we requested access, otherwise not interested
|
||||||
if err != nil {
|
if o.config.Joined || o.config.Spectated || o.config.RequestedToJoinAt > 0 {
|
||||||
return nil, err
|
response = EvaluateCommunityChanges(o.config.CommunityDescription, description)
|
||||||
|
response.Community = o
|
||||||
}
|
}
|
||||||
|
|
||||||
o.config.CommunityDescription = description
|
o.config.CommunityDescription = description
|
||||||
|
@ -1384,14 +1393,18 @@ func (o *Community) HasTokenPermissions() bool {
|
||||||
return len(o.config.CommunityDescription.TokenPermissions) > 0
|
return len(o.config.CommunityDescription.TokenPermissions) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Community) TokenPermissionsByType(permissionType protobuf.CommunityTokenPermission_Type) []*protobuf.CommunityTokenPermission {
|
func TokenPermissionsByType(permissions map[string]*protobuf.CommunityTokenPermission, permissionType protobuf.CommunityTokenPermission_Type) []*protobuf.CommunityTokenPermission {
|
||||||
permissions := make([]*protobuf.CommunityTokenPermission, 0)
|
result := make([]*protobuf.CommunityTokenPermission, 0)
|
||||||
for _, tokenPermission := range o.TokenPermissions() {
|
for _, tokenPermission := range permissions {
|
||||||
if tokenPermission.Type == permissionType {
|
if tokenPermission.Type == permissionType {
|
||||||
permissions = append(permissions, tokenPermission)
|
result = append(result, tokenPermission)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return permissions
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Community) TokenPermissionsByType(permissionType protobuf.CommunityTokenPermission_Type) []*protobuf.CommunityTokenPermission {
|
||||||
|
return TokenPermissionsByType(o.TokenPermissions(), permissionType)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Community) ChannelTokenPermissionsByType(channelID string, permissionType protobuf.CommunityTokenPermission_Type) []*protobuf.CommunityTokenPermission {
|
func (o *Community) ChannelTokenPermissionsByType(channelID string, permissionType protobuf.CommunityTokenPermission_Type) []*protobuf.CommunityTokenPermission {
|
||||||
|
@ -1809,6 +1822,38 @@ func (o *Community) AddMember(publicKey *ecdsa.PublicKey, roles []protobuf.Commu
|
||||||
return changes, nil
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Community) AddMemberToChat(chatID string, publicKey *ecdsa.PublicKey, roles []protobuf.CommunityMember_Roles) (*CommunityChanges, error) {
|
||||||
|
o.mutex.Lock()
|
||||||
|
defer o.mutex.Unlock()
|
||||||
|
|
||||||
|
if !o.IsOwnerOrAdmin() {
|
||||||
|
return nil, ErrNotAuthorized
|
||||||
|
}
|
||||||
|
|
||||||
|
memberKey := common.PubkeyToHex(publicKey)
|
||||||
|
changes := o.emptyCommunityChanges()
|
||||||
|
|
||||||
|
chat, ok := o.config.CommunityDescription.Chats[chatID]
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrChatNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if chat.Members == nil {
|
||||||
|
chat.Members = make(map[string]*protobuf.CommunityMember)
|
||||||
|
}
|
||||||
|
chat.Members[memberKey] = &protobuf.CommunityMember{
|
||||||
|
Roles: roles,
|
||||||
|
}
|
||||||
|
changes.ChatsModified[chatID] = &CommunityChatChanges{
|
||||||
|
ChatModified: chat,
|
||||||
|
MembersAdded: map[string]*protobuf.CommunityMember{
|
||||||
|
memberKey: chat.Members[memberKey],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Community) ChatIDs() (chatIDs []string) {
|
func (o *Community) ChatIDs() (chatIDs []string) {
|
||||||
for id := range o.config.CommunityDescription.Chats {
|
for id := range o.config.CommunityDescription.Chats {
|
||||||
chatIDs = append(chatIDs, o.IDString()+id)
|
chatIDs = append(chatIDs, o.IDString()+id)
|
||||||
|
@ -2044,189 +2089,6 @@ func (o *Community) addCommunityMember(pk *ecdsa.PublicKey, member *protobuf.Com
|
||||||
o.config.CommunityDescription.Members[memberKey] = member
|
o.config.CommunityDescription.Members[memberKey] = member
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Community) collectCommunityChanges(description *protobuf.CommunityDescription) (*CommunityChanges, error) {
|
|
||||||
// This is done in case tags are updated and a client sends unknown tags
|
|
||||||
description.Tags = requests.RemoveUnknownAndDeduplicateTags(description.Tags)
|
|
||||||
|
|
||||||
err := ValidateCommunityDescription(description)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
response := o.emptyCommunityChanges()
|
|
||||||
|
|
||||||
// We only calculate changes if we joined/spectated the community or we requested access, otherwise not interested
|
|
||||||
if o.config.Joined || o.config.Spectated || o.config.RequestedToJoinAt > 0 {
|
|
||||||
// Check for new members at the org level
|
|
||||||
for pk, member := range description.Members {
|
|
||||||
if _, ok := o.config.CommunityDescription.Members[pk]; !ok {
|
|
||||||
if response.MembersAdded == nil {
|
|
||||||
response.MembersAdded = make(map[string]*protobuf.CommunityMember)
|
|
||||||
}
|
|
||||||
response.MembersAdded[pk] = member
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for removed members at the org level
|
|
||||||
for pk, member := range o.config.CommunityDescription.Members {
|
|
||||||
if _, ok := description.Members[pk]; !ok {
|
|
||||||
if response.MembersRemoved == nil {
|
|
||||||
response.MembersRemoved = make(map[string]*protobuf.CommunityMember)
|
|
||||||
}
|
|
||||||
response.MembersRemoved[pk] = member
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for removed chats
|
|
||||||
for chatID, chat := range o.config.CommunityDescription.Chats {
|
|
||||||
if description.Chats == nil {
|
|
||||||
description.Chats = make(map[string]*protobuf.CommunityChat)
|
|
||||||
}
|
|
||||||
if _, ok := description.Chats[chatID]; !ok {
|
|
||||||
if response.ChatsRemoved == nil {
|
|
||||||
response.ChatsRemoved = make(map[string]*protobuf.CommunityChat)
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ChatsRemoved[chatID] = chat
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for chatID, chat := range description.Chats {
|
|
||||||
if o.config.CommunityDescription.Chats == nil {
|
|
||||||
o.config.CommunityDescription.Chats = make(map[string]*protobuf.CommunityChat)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := o.config.CommunityDescription.Chats[chatID]; !ok {
|
|
||||||
if response.ChatsAdded == nil {
|
|
||||||
response.ChatsAdded = make(map[string]*protobuf.CommunityChat)
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ChatsAdded[chatID] = chat
|
|
||||||
} else {
|
|
||||||
// Check for members added
|
|
||||||
for pk, member := range description.Chats[chatID].Members {
|
|
||||||
if _, ok := o.config.CommunityDescription.Chats[chatID].Members[pk]; !ok {
|
|
||||||
if response.ChatsModified[chatID] == nil {
|
|
||||||
response.ChatsModified[chatID] = &CommunityChatChanges{
|
|
||||||
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
|
||||||
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ChatsModified[chatID].MembersAdded[pk] = member
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for members removed
|
|
||||||
for pk, member := range o.config.CommunityDescription.Chats[chatID].Members {
|
|
||||||
if _, ok := description.Chats[chatID].Members[pk]; !ok {
|
|
||||||
if response.ChatsModified[chatID] == nil {
|
|
||||||
response.ChatsModified[chatID] = &CommunityChatChanges{
|
|
||||||
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
|
||||||
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ChatsModified[chatID].MembersRemoved[pk] = member
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if first message timestamp was modified
|
|
||||||
if o.config.CommunityDescription.Chats[chatID].Identity.FirstMessageTimestamp !=
|
|
||||||
description.Chats[chatID].Identity.FirstMessageTimestamp {
|
|
||||||
if response.ChatsModified[chatID] == nil {
|
|
||||||
response.ChatsModified[chatID] = &CommunityChatChanges{
|
|
||||||
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
|
||||||
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response.ChatsModified[chatID].FirstMessageTimestampModified = description.Chats[chatID].Identity.FirstMessageTimestamp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for categories that were removed
|
|
||||||
for categoryID := range o.config.CommunityDescription.Categories {
|
|
||||||
if description.Categories == nil {
|
|
||||||
description.Categories = make(map[string]*protobuf.CommunityCategory)
|
|
||||||
}
|
|
||||||
|
|
||||||
if description.Chats == nil {
|
|
||||||
description.Chats = make(map[string]*protobuf.CommunityChat)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := description.Categories[categoryID]; !ok {
|
|
||||||
response.CategoriesRemoved = append(response.CategoriesRemoved, categoryID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.config.CommunityDescription.Chats == nil {
|
|
||||||
o.config.CommunityDescription.Chats = make(map[string]*protobuf.CommunityChat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for categories that were added
|
|
||||||
for categoryID, category := range description.Categories {
|
|
||||||
if o.config.CommunityDescription.Categories == nil {
|
|
||||||
o.config.CommunityDescription.Categories = make(map[string]*protobuf.CommunityCategory)
|
|
||||||
}
|
|
||||||
if _, ok := o.config.CommunityDescription.Categories[categoryID]; !ok {
|
|
||||||
if response.CategoriesAdded == nil {
|
|
||||||
response.CategoriesAdded = make(map[string]*protobuf.CommunityCategory)
|
|
||||||
}
|
|
||||||
|
|
||||||
response.CategoriesAdded[categoryID] = category
|
|
||||||
} else {
|
|
||||||
if o.config.CommunityDescription.Categories[categoryID].Name != category.Name || o.config.CommunityDescription.Categories[categoryID].Position != category.Position {
|
|
||||||
response.CategoriesModified[categoryID] = category
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for chat categories that were modified
|
|
||||||
for chatID, chat := range description.Chats {
|
|
||||||
if o.config.CommunityDescription.Chats == nil {
|
|
||||||
o.config.CommunityDescription.Chats = make(map[string]*protobuf.CommunityChat)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := o.config.CommunityDescription.Chats[chatID]; !ok {
|
|
||||||
continue // It's a new chat
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.config.CommunityDescription.Chats[chatID].CategoryId != chat.CategoryId {
|
|
||||||
if response.ChatsModified[chatID] == nil {
|
|
||||||
response.ChatsModified[chatID] = &CommunityChatChanges{
|
|
||||||
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
|
||||||
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ChatsModified[chatID].CategoryModified = chat.CategoryId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for removed token permissions
|
|
||||||
for id := range o.config.CommunityDescription.TokenPermissions {
|
|
||||||
if _, ok := description.TokenPermissions[id]; !ok {
|
|
||||||
if response.TokenPermissionsRemoved == nil {
|
|
||||||
response.TokenPermissionsRemoved = make([]string, 0)
|
|
||||||
}
|
|
||||||
response.TokenPermissionsRemoved = append(response.TokenPermissionsRemoved, id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for id, permission := range description.TokenPermissions {
|
|
||||||
if _, ok := o.config.CommunityDescription.TokenPermissions[id]; !ok {
|
|
||||||
if response.TokenPermissionsAdded == nil {
|
|
||||||
response.TokenPermissionsAdded = make(map[string]*protobuf.CommunityTokenPermission)
|
|
||||||
}
|
|
||||||
response.TokenPermissionsAdded[id] = permission
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Community) addTokenPermission(permission *protobuf.CommunityTokenPermission) (*CommunityChanges, error) {
|
func (o *Community) addTokenPermission(permission *protobuf.CommunityTokenPermission) (*CommunityChanges, error) {
|
||||||
if o.config.CommunityDescription.TokenPermissions == nil {
|
if o.config.CommunityDescription.TokenPermissions == nil {
|
||||||
o.config.CommunityDescription.TokenPermissions = make(map[string]*protobuf.CommunityTokenPermission)
|
o.config.CommunityDescription.TokenPermissions = make(map[string]*protobuf.CommunityTokenPermission)
|
||||||
|
@ -2268,10 +2130,15 @@ func (o *Community) updateTokenPermission(permission *protobuf.CommunityTokenPer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Community) deleteTokenPermission(permissionID string) (*CommunityChanges, error) {
|
func (o *Community) deleteTokenPermission(permissionID string) (*CommunityChanges, error) {
|
||||||
|
permission, exists := o.config.CommunityDescription.TokenPermissions[permissionID]
|
||||||
|
if !exists {
|
||||||
|
return nil, ErrTokenPermissionNotFound
|
||||||
|
}
|
||||||
|
|
||||||
delete(o.config.CommunityDescription.TokenPermissions, permissionID)
|
delete(o.config.CommunityDescription.TokenPermissions, permissionID)
|
||||||
|
|
||||||
changes := o.emptyCommunityChanges()
|
changes := o.emptyCommunityChanges()
|
||||||
changes.TokenPermissionsRemoved = append(changes.TokenPermissionsRemoved, permissionID)
|
changes.TokenPermissionsRemoved[permissionID] = permission
|
||||||
return changes, nil
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,13 @@ type CommunityChatChanges struct {
|
||||||
|
|
||||||
type CommunityChanges struct {
|
type CommunityChanges struct {
|
||||||
Community *Community `json:"community"`
|
Community *Community `json:"community"`
|
||||||
|
|
||||||
MembersAdded map[string]*protobuf.CommunityMember `json:"membersAdded"`
|
MembersAdded map[string]*protobuf.CommunityMember `json:"membersAdded"`
|
||||||
MembersRemoved map[string]*protobuf.CommunityMember `json:"membersRemoved"`
|
MembersRemoved map[string]*protobuf.CommunityMember `json:"membersRemoved"`
|
||||||
|
|
||||||
TokenPermissionsAdded map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissionsAdded"`
|
TokenPermissionsAdded map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissionsAdded"`
|
||||||
TokenPermissionsModified map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissionsModified"`
|
TokenPermissionsModified map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissionsModified"`
|
||||||
TokenPermissionsRemoved []string `json:"tokenPermissionsRemoved"`
|
TokenPermissionsRemoved map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissionsRemoved"`
|
||||||
|
|
||||||
ChatsRemoved map[string]*protobuf.CommunityChat `json:"chatsRemoved"`
|
ChatsRemoved map[string]*protobuf.CommunityChat `json:"chatsRemoved"`
|
||||||
ChatsAdded map[string]*protobuf.CommunityChat `json:"chatsAdded"`
|
ChatsAdded map[string]*protobuf.CommunityChat `json:"chatsAdded"`
|
||||||
|
@ -45,6 +46,10 @@ func EmptyCommunityChanges() *CommunityChanges {
|
||||||
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
||||||
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
||||||
|
|
||||||
|
TokenPermissionsAdded: make(map[string]*protobuf.CommunityTokenPermission),
|
||||||
|
TokenPermissionsModified: make(map[string]*protobuf.CommunityTokenPermission),
|
||||||
|
TokenPermissionsRemoved: make(map[string]*protobuf.CommunityTokenPermission),
|
||||||
|
|
||||||
ChatsRemoved: make(map[string]*protobuf.CommunityChat),
|
ChatsRemoved: make(map[string]*protobuf.CommunityChat),
|
||||||
ChatsAdded: make(map[string]*protobuf.CommunityChat),
|
ChatsAdded: make(map[string]*protobuf.CommunityChat),
|
||||||
ChatsModified: make(map[string]*CommunityChatChanges),
|
ChatsModified: make(map[string]*CommunityChatChanges),
|
||||||
|
@ -73,3 +78,170 @@ func (c *CommunityChanges) HasMemberLeft(identity string) bool {
|
||||||
_, ok := c.MembersRemoved[identity]
|
_, ok := c.MembersRemoved[identity]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func EvaluateCommunityChanges(origin, modified *protobuf.CommunityDescription) *CommunityChanges {
|
||||||
|
changes := EmptyCommunityChanges()
|
||||||
|
|
||||||
|
// Check for new members at the org level
|
||||||
|
for pk, member := range modified.Members {
|
||||||
|
if _, ok := origin.Members[pk]; !ok {
|
||||||
|
if changes.MembersAdded == nil {
|
||||||
|
changes.MembersAdded = make(map[string]*protobuf.CommunityMember)
|
||||||
|
}
|
||||||
|
changes.MembersAdded[pk] = member
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for removed members at the org level
|
||||||
|
for pk, member := range origin.Members {
|
||||||
|
if _, ok := modified.Members[pk]; !ok {
|
||||||
|
if changes.MembersRemoved == nil {
|
||||||
|
changes.MembersRemoved = make(map[string]*protobuf.CommunityMember)
|
||||||
|
}
|
||||||
|
changes.MembersRemoved[pk] = member
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for removed chats
|
||||||
|
for chatID, chat := range origin.Chats {
|
||||||
|
if modified.Chats == nil {
|
||||||
|
modified.Chats = make(map[string]*protobuf.CommunityChat)
|
||||||
|
}
|
||||||
|
if _, ok := modified.Chats[chatID]; !ok {
|
||||||
|
if changes.ChatsRemoved == nil {
|
||||||
|
changes.ChatsRemoved = make(map[string]*protobuf.CommunityChat)
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.ChatsRemoved[chatID] = chat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for chatID, chat := range modified.Chats {
|
||||||
|
if origin.Chats == nil {
|
||||||
|
origin.Chats = make(map[string]*protobuf.CommunityChat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := origin.Chats[chatID]; !ok {
|
||||||
|
if changes.ChatsAdded == nil {
|
||||||
|
changes.ChatsAdded = make(map[string]*protobuf.CommunityChat)
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.ChatsAdded[chatID] = chat
|
||||||
|
} else {
|
||||||
|
// Check for members added
|
||||||
|
for pk, member := range modified.Chats[chatID].Members {
|
||||||
|
if _, ok := origin.Chats[chatID].Members[pk]; !ok {
|
||||||
|
if changes.ChatsModified[chatID] == nil {
|
||||||
|
changes.ChatsModified[chatID] = &CommunityChatChanges{
|
||||||
|
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
||||||
|
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.ChatsModified[chatID].MembersAdded[pk] = member
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for members removed
|
||||||
|
for pk, member := range origin.Chats[chatID].Members {
|
||||||
|
if _, ok := modified.Chats[chatID].Members[pk]; !ok {
|
||||||
|
if changes.ChatsModified[chatID] == nil {
|
||||||
|
changes.ChatsModified[chatID] = &CommunityChatChanges{
|
||||||
|
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
||||||
|
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.ChatsModified[chatID].MembersRemoved[pk] = member
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if first message timestamp was modified
|
||||||
|
if origin.Chats[chatID].Identity.FirstMessageTimestamp !=
|
||||||
|
modified.Chats[chatID].Identity.FirstMessageTimestamp {
|
||||||
|
if changes.ChatsModified[chatID] == nil {
|
||||||
|
changes.ChatsModified[chatID] = &CommunityChatChanges{
|
||||||
|
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
||||||
|
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changes.ChatsModified[chatID].FirstMessageTimestampModified = modified.Chats[chatID].Identity.FirstMessageTimestamp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for categories that were removed
|
||||||
|
for categoryID := range origin.Categories {
|
||||||
|
if modified.Categories == nil {
|
||||||
|
modified.Categories = make(map[string]*protobuf.CommunityCategory)
|
||||||
|
}
|
||||||
|
|
||||||
|
if modified.Chats == nil {
|
||||||
|
modified.Chats = make(map[string]*protobuf.CommunityChat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := modified.Categories[categoryID]; !ok {
|
||||||
|
changes.CategoriesRemoved = append(changes.CategoriesRemoved, categoryID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if origin.Chats == nil {
|
||||||
|
origin.Chats = make(map[string]*protobuf.CommunityChat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for categories that were added
|
||||||
|
for categoryID, category := range modified.Categories {
|
||||||
|
if origin.Categories == nil {
|
||||||
|
origin.Categories = make(map[string]*protobuf.CommunityCategory)
|
||||||
|
}
|
||||||
|
if _, ok := origin.Categories[categoryID]; !ok {
|
||||||
|
if changes.CategoriesAdded == nil {
|
||||||
|
changes.CategoriesAdded = make(map[string]*protobuf.CommunityCategory)
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.CategoriesAdded[categoryID] = category
|
||||||
|
} else {
|
||||||
|
if origin.Categories[categoryID].Name != category.Name || origin.Categories[categoryID].Position != category.Position {
|
||||||
|
changes.CategoriesModified[categoryID] = category
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for chat categories that were modified
|
||||||
|
for chatID, chat := range modified.Chats {
|
||||||
|
if origin.Chats == nil {
|
||||||
|
origin.Chats = make(map[string]*protobuf.CommunityChat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := origin.Chats[chatID]; !ok {
|
||||||
|
continue // It's a new chat
|
||||||
|
}
|
||||||
|
|
||||||
|
if origin.Chats[chatID].CategoryId != chat.CategoryId {
|
||||||
|
if changes.ChatsModified[chatID] == nil {
|
||||||
|
changes.ChatsModified[chatID] = &CommunityChatChanges{
|
||||||
|
MembersAdded: make(map[string]*protobuf.CommunityMember),
|
||||||
|
MembersRemoved: make(map[string]*protobuf.CommunityMember),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.ChatsModified[chatID].CategoryModified = chat.CategoryId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for removed token permissions
|
||||||
|
for id, permission := range origin.TokenPermissions {
|
||||||
|
if _, ok := modified.TokenPermissions[id]; !ok {
|
||||||
|
changes.TokenPermissionsRemoved[id] = permission
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for added token permissions
|
||||||
|
for id, permission := range modified.TokenPermissions {
|
||||||
|
if _, ok := origin.TokenPermissions[id]; !ok {
|
||||||
|
changes.TokenPermissionsAdded[id] = permission
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
package communities
|
||||||
|
|
||||||
|
import "github.com/status-im/status-go/protocol/protobuf"
|
||||||
|
|
||||||
|
type EncryptionKeyActionType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
EncryptionKeyNone EncryptionKeyActionType = iota
|
||||||
|
EncryptionKeyAdd
|
||||||
|
EncryptionKeyRemove
|
||||||
|
EncryptionKeyRekey
|
||||||
|
EncryptionKeySendToMembers
|
||||||
|
)
|
||||||
|
|
||||||
|
type EncryptionKeyAction struct {
|
||||||
|
ActionType EncryptionKeyActionType
|
||||||
|
Members map[string]*protobuf.CommunityMember
|
||||||
|
}
|
||||||
|
|
||||||
|
type EncryptionKeyActions struct {
|
||||||
|
// community-level encryption key action
|
||||||
|
CommunityKeyAction EncryptionKeyAction
|
||||||
|
|
||||||
|
// channel-level encryption key actions
|
||||||
|
ChannelKeysActions map[string]EncryptionKeyAction // key is: chatID
|
||||||
|
}
|
||||||
|
|
||||||
|
func EvaluateCommunityEncryptionKeyActions(origin, modified *Community) *EncryptionKeyActions {
|
||||||
|
changes := EvaluateCommunityChanges(origin.Description(), modified.Description())
|
||||||
|
|
||||||
|
result := &EncryptionKeyActions{
|
||||||
|
CommunityKeyAction: *evaluateCommunityLevelEncryptionKeyAction(origin, modified, changes),
|
||||||
|
ChannelKeysActions: *evaluateChannelLevelEncryptionKeyActions(origin, modified, changes),
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func evaluateCommunityLevelEncryptionKeyAction(origin, modified *Community, changes *CommunityChanges) *EncryptionKeyAction {
|
||||||
|
originBecomeMemberPermissions := origin.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_MEMBER)
|
||||||
|
modifiedBecomeMemberPermissions := modified.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_MEMBER)
|
||||||
|
|
||||||
|
return evaluateEncryptionKeyAction(originBecomeMemberPermissions, modifiedBecomeMemberPermissions, modified.config.CommunityDescription.Members, changes.MembersAdded, changes.MembersRemoved)
|
||||||
|
}
|
||||||
|
|
||||||
|
func evaluateChannelLevelEncryptionKeyActions(origin, modified *Community, changes *CommunityChanges) *map[string]EncryptionKeyAction {
|
||||||
|
result := make(map[string]EncryptionKeyAction)
|
||||||
|
|
||||||
|
for chatID := range modified.config.CommunityDescription.Chats {
|
||||||
|
originChannelViewOnlyPermissions := origin.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
|
||||||
|
originChannelViewAndPostPermissions := origin.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
|
||||||
|
originChannelPermissions := append(originChannelViewOnlyPermissions, originChannelViewAndPostPermissions...)
|
||||||
|
|
||||||
|
modifiedChannelViewOnlyPermissions := modified.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
|
||||||
|
modifiedChannelViewAndPostPermissions := modified.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
|
||||||
|
modifiedChannelPermissions := append(modifiedChannelViewOnlyPermissions, modifiedChannelViewAndPostPermissions...)
|
||||||
|
|
||||||
|
membersAdded := make(map[string]*protobuf.CommunityMember)
|
||||||
|
membersRemoved := make(map[string]*protobuf.CommunityMember)
|
||||||
|
|
||||||
|
chatChanges, ok := changes.ChatsModified[chatID]
|
||||||
|
if ok {
|
||||||
|
membersAdded = chatChanges.MembersAdded
|
||||||
|
membersRemoved = chatChanges.MembersRemoved
|
||||||
|
}
|
||||||
|
|
||||||
|
result[chatID] = *evaluateEncryptionKeyAction(originChannelPermissions, modifiedChannelPermissions, modified.config.CommunityDescription.Members, membersAdded, membersRemoved)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
|
||||||
|
func evaluateEncryptionKeyAction(originPermissions, modifiedPermissions []*protobuf.CommunityTokenPermission, allMembers, membersAdded, membersRemoved map[string]*protobuf.CommunityMember) *EncryptionKeyAction {
|
||||||
|
result := &EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeyNone,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{},
|
||||||
|
}
|
||||||
|
|
||||||
|
copyMap := func(source map[string]*protobuf.CommunityMember) map[string]*protobuf.CommunityMember {
|
||||||
|
to := make(map[string]*protobuf.CommunityMember)
|
||||||
|
for pubKey, member := range source {
|
||||||
|
to[pubKey] = member
|
||||||
|
}
|
||||||
|
return to
|
||||||
|
}
|
||||||
|
|
||||||
|
// permission was just added
|
||||||
|
if len(modifiedPermissions) > 0 && len(originPermissions) == 0 {
|
||||||
|
result.ActionType = EncryptionKeyAdd
|
||||||
|
result.Members = copyMap(allMembers)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// permission was just removed
|
||||||
|
if len(modifiedPermissions) == 0 && len(originPermissions) > 0 {
|
||||||
|
result.ActionType = EncryptionKeyRemove
|
||||||
|
result.Members = copyMap(allMembers)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// open community/channel does not require any actions
|
||||||
|
if len(modifiedPermissions) == 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(membersRemoved) > 0 {
|
||||||
|
result.ActionType = EncryptionKeyRekey
|
||||||
|
result.Members = copyMap(allMembers)
|
||||||
|
} else if len(membersAdded) > 0 {
|
||||||
|
result.ActionType = EncryptionKeySendToMembers
|
||||||
|
result.Members = copyMap(membersAdded)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,781 @@
|
||||||
|
package communities
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createTestCommunity(identity *ecdsa.PrivateKey) *Community {
|
||||||
|
return &Community{
|
||||||
|
config: &Config{
|
||||||
|
PrivateKey: identity,
|
||||||
|
CommunityDescription: &protobuf.CommunityDescription{
|
||||||
|
Members: map[string]*protobuf.CommunityMember{},
|
||||||
|
Permissions: &protobuf.CommunityPermissions{},
|
||||||
|
Identity: &protobuf.ChatIdentity{},
|
||||||
|
Chats: map[string]*protobuf.CommunityChat{},
|
||||||
|
BanList: []string{},
|
||||||
|
Categories: map[string]*protobuf.CommunityCategory{},
|
||||||
|
Encrypted: false,
|
||||||
|
TokenPermissions: map[string]*protobuf.CommunityTokenPermission{},
|
||||||
|
CommunityTokensMetadata: []*protobuf.CommunityTokenMetadata{},
|
||||||
|
},
|
||||||
|
ID: &identity.PublicKey,
|
||||||
|
Joined: true,
|
||||||
|
MemberIdentity: &identity.PublicKey,
|
||||||
|
},
|
||||||
|
mutex: sync.Mutex{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCommunityEncryptionKeyActionSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(CommunityEncryptionKeyActionSuite))
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommunityEncryptionKeyActionSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
|
||||||
|
identity *ecdsa.PrivateKey
|
||||||
|
communityID []byte
|
||||||
|
|
||||||
|
member1 *ecdsa.PrivateKey
|
||||||
|
member2 *ecdsa.PrivateKey
|
||||||
|
member3 *ecdsa.PrivateKey
|
||||||
|
|
||||||
|
member1Key string
|
||||||
|
member2Key string
|
||||||
|
member3Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommunityEncryptionKeyActionSuite) SetupTest() {
|
||||||
|
identity, err := crypto.GenerateKey()
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.identity = identity
|
||||||
|
s.communityID = crypto.CompressPubkey(&identity.PublicKey)
|
||||||
|
|
||||||
|
member1, err := crypto.GenerateKey()
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.member1 = member1
|
||||||
|
|
||||||
|
member2, err := crypto.GenerateKey()
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.member2 = member2
|
||||||
|
|
||||||
|
member3, err := crypto.GenerateKey()
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.member3 = member3
|
||||||
|
|
||||||
|
s.member1Key = common.PubkeyToHex(&s.member1.PublicKey)
|
||||||
|
s.member2Key = common.PubkeyToHex(&s.member2.PublicKey)
|
||||||
|
s.member3Key = common.PubkeyToHex(&s.member3.PublicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommunityEncryptionKeyActionSuite) TestEncryptionKeyNone() {
|
||||||
|
origin := createTestCommunity(s.identity)
|
||||||
|
|
||||||
|
// if there are no changes there should be no actions
|
||||||
|
actions := EvaluateCommunityEncryptionKeyActions(origin, origin)
|
||||||
|
s.Require().Equal(actions.CommunityKeyAction.ActionType, EncryptionKeyNone)
|
||||||
|
s.Require().Len(actions.ChannelKeysActions, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommunityEncryptionKeyActionSuite) TestCommunityLevelKeyActions_PermissionsCombinations() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
originPermissions []*protobuf.CommunityTokenPermission
|
||||||
|
modifiedPermissions []*protobuf.CommunityTokenPermission
|
||||||
|
expectedActionType EncryptionKeyActionType
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "add member permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyAdd,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add member permissions",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-2",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyAdd,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add another member permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-2",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyNone,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add another member permission and remove previous one",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-2",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyNone,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove member permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
expectedActionType: EncryptionKeyRemove,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove one of member permissions",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-2",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyNone,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add channel permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{"some-chat-id"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyNone,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove channel permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{"some-chat-id"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
expectedActionType: EncryptionKeyNone,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add member permission on top of channel permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{"some-chat-id"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{"some-chat-id"},
|
||||||
|
},
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-2",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyAdd,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add channel permission on top of member permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-2",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{"some-chat-id"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyNone,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "change member permission to channel permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyRemove,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "change channel permission to member permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyAdd,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "change channel permission to member permission on top of member permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-2",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-1",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id-2",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedActionType: EncryptionKeyNone,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
origin := createTestCommunity(s.identity)
|
||||||
|
modified := origin.createDeepCopy()
|
||||||
|
|
||||||
|
for _, permission := range tc.originPermissions {
|
||||||
|
_, err := origin.AddTokenPermission(permission)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, permission := range tc.modifiedPermissions {
|
||||||
|
_, err := modified.AddTokenPermission(permission)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actions := EvaluateCommunityEncryptionKeyActions(origin, modified)
|
||||||
|
s.Require().Equal(tc.expectedActionType, actions.CommunityKeyAction.ActionType)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommunityEncryptionKeyActionSuite) TestCommunityLevelKeyActions_MembersCombinations() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
permissions []*protobuf.CommunityTokenPermission
|
||||||
|
originMembers []*ecdsa.PublicKey
|
||||||
|
modifiedMembers []*ecdsa.PublicKey
|
||||||
|
expectedAction EncryptionKeyAction
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "add member to open community",
|
||||||
|
permissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
originMembers: []*ecdsa.PublicKey{},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeyNone,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove member from open community",
|
||||||
|
permissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
originMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeyNone,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add member to token-gated community",
|
||||||
|
permissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originMembers: []*ecdsa.PublicKey{},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeySendToMembers,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{
|
||||||
|
s.member1Key: &protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add multiple members to token-gated community",
|
||||||
|
permissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originMembers: []*ecdsa.PublicKey{},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{&s.member1.PublicKey, &s.member2.PublicKey},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeySendToMembers,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{
|
||||||
|
s.member1Key: &protobuf.CommunityMember{},
|
||||||
|
s.member2Key: &protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove member from token-gated community",
|
||||||
|
permissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originMembers: []*ecdsa.PublicKey{&s.member1.PublicKey, &s.member2.PublicKey},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeyRekey,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{
|
||||||
|
s.member1Key: &protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add and remove members from token-gated community",
|
||||||
|
permissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{&s.member2.PublicKey, &s.member3.PublicKey},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeyRekey,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{
|
||||||
|
s.member2Key: &protobuf.CommunityMember{},
|
||||||
|
s.member3Key: &protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
origin := createTestCommunity(s.identity)
|
||||||
|
for _, permission := range tc.permissions {
|
||||||
|
_, err := origin.AddTokenPermission(permission)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
modified := origin.createDeepCopy()
|
||||||
|
|
||||||
|
for _, member := range tc.originMembers {
|
||||||
|
_, err := origin.AddMember(member, []protobuf.CommunityMember_Roles{})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, member := range tc.modifiedMembers {
|
||||||
|
_, err := modified.AddMember(member, []protobuf.CommunityMember_Roles{})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actions := EvaluateCommunityEncryptionKeyActions(origin, modified)
|
||||||
|
s.Require().Equal(tc.expectedAction.ActionType, actions.CommunityKeyAction.ActionType)
|
||||||
|
s.Require().Len(tc.expectedAction.Members, len(actions.CommunityKeyAction.Members))
|
||||||
|
for memberKey := range tc.expectedAction.Members {
|
||||||
|
_, exists := actions.CommunityKeyAction.Members[memberKey]
|
||||||
|
s.Require().True(exists)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommunityEncryptionKeyActionSuite) TestCommunityLevelKeyActions_PermissionsMembersCombinations() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
originPermissions []*protobuf.CommunityTokenPermission
|
||||||
|
modifiedPermissions []*protobuf.CommunityTokenPermission
|
||||||
|
originMembers []*ecdsa.PublicKey
|
||||||
|
modifiedMembers []*ecdsa.PublicKey
|
||||||
|
expectedActionType EncryptionKeyActionType
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "add member permission, add members",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originMembers: []*ecdsa.PublicKey{},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
||||||
|
expectedActionType: EncryptionKeyAdd,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add member permission, remove members",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{},
|
||||||
|
expectedActionType: EncryptionKeyAdd,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove member permission, add members",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
originMembers: []*ecdsa.PublicKey{},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
||||||
|
expectedActionType: EncryptionKeyRemove,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove member permission, remove members",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
originMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{},
|
||||||
|
expectedActionType: EncryptionKeyRemove,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
origin := createTestCommunity(s.identity)
|
||||||
|
modified := origin.createDeepCopy()
|
||||||
|
|
||||||
|
for _, permission := range tc.originPermissions {
|
||||||
|
_, err := origin.AddTokenPermission(permission)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
for _, member := range tc.originMembers {
|
||||||
|
_, err := origin.AddMember(member, []protobuf.CommunityMember_Roles{})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, permission := range tc.modifiedPermissions {
|
||||||
|
_, err := modified.AddTokenPermission(permission)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
for _, member := range tc.modifiedMembers {
|
||||||
|
_, err := modified.AddMember(member, []protobuf.CommunityMember_Roles{})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actions := EvaluateCommunityEncryptionKeyActions(origin, modified)
|
||||||
|
s.Require().Equal(tc.expectedActionType, actions.CommunityKeyAction.ActionType)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommunityEncryptionKeyActionSuite) TestChannelLevelKeyActions() {
|
||||||
|
chatID := "0x1234"
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
originPermissions []*protobuf.CommunityTokenPermission
|
||||||
|
modifiedPermissions []*protobuf.CommunityTokenPermission
|
||||||
|
originMembers []*ecdsa.PublicKey
|
||||||
|
modifiedMembers []*ecdsa.PublicKey
|
||||||
|
expectedAction EncryptionKeyAction
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "add channel permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{chatID},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originMembers: []*ecdsa.PublicKey{},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeyAdd,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove channel permission",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{chatID},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
originMembers: []*ecdsa.PublicKey{},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeyRemove,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add members to token-gated channel",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{chatID},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{chatID},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originMembers: []*ecdsa.PublicKey{},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{&s.member1.PublicKey, &s.member2.PublicKey},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeySendToMembers,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{
|
||||||
|
s.member1Key: &protobuf.CommunityMember{},
|
||||||
|
s.member2Key: &protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remove members from token-gated channel",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{chatID},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
||||||
|
&protobuf.CommunityTokenPermission{
|
||||||
|
Id: "some-id",
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
||||||
|
ChatIds: []string{chatID},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originMembers: []*ecdsa.PublicKey{&s.member1.PublicKey, &s.member2.PublicKey},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeyRekey,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add members to open channel",
|
||||||
|
originPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{},
|
||||||
|
originMembers: []*ecdsa.PublicKey{},
|
||||||
|
modifiedMembers: []*ecdsa.PublicKey{&s.member1.PublicKey, &s.member2.PublicKey},
|
||||||
|
expectedAction: EncryptionKeyAction{
|
||||||
|
ActionType: EncryptionKeyNone,
|
||||||
|
Members: map[string]*protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
origin := createTestCommunity(s.identity)
|
||||||
|
_, err := origin.CreateChat(chatID, &protobuf.CommunityChat{
|
||||||
|
Members: map[string]*protobuf.CommunityMember{},
|
||||||
|
Permissions: &protobuf.CommunityPermissions{Access: protobuf.CommunityPermissions_NO_MEMBERSHIP},
|
||||||
|
Identity: &protobuf.ChatIdentity{},
|
||||||
|
})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
modified := origin.createDeepCopy()
|
||||||
|
|
||||||
|
for _, permission := range tc.originPermissions {
|
||||||
|
_, err := origin.AddTokenPermission(permission)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
for _, member := range tc.originMembers {
|
||||||
|
_, err := origin.AddMember(member, []protobuf.CommunityMember_Roles{})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
_, err = origin.AddMemberToChat(chatID, member, []protobuf.CommunityMember_Roles{})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, permission := range tc.modifiedPermissions {
|
||||||
|
_, err := modified.AddTokenPermission(permission)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
for _, member := range tc.modifiedMembers {
|
||||||
|
_, err := modified.AddMember(member, []protobuf.CommunityMember_Roles{})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
_, err = modified.AddMemberToChat(chatID, member, []protobuf.CommunityMember_Roles{})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actions := EvaluateCommunityEncryptionKeyActions(origin, modified)
|
||||||
|
channelAction, ok := actions.ChannelKeysActions[chatID]
|
||||||
|
s.Require().True(ok)
|
||||||
|
s.Require().Equal(tc.expectedAction.ActionType, channelAction.ActionType)
|
||||||
|
s.Require().Len(tc.expectedAction.Members, len(channelAction.Members))
|
||||||
|
for memberKey := range tc.expectedAction.Members {
|
||||||
|
_, exists := channelAction.Members[memberKey]
|
||||||
|
s.Require().True(exists)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -199,12 +199,9 @@ func (o *Community) UpdateCommunityByEvents(communityEventMessage *CommunityEven
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect `CommunityChanges` data by searching a difference between `CommunityDescrption`
|
// Evaluate `CommunityChanges` data by searching a difference between `CommunityDescription`
|
||||||
// from the DB and `CommunityDescrption` patched by community events
|
// from the DB and `CommunityDescription` patched by community events
|
||||||
changes, err := o.collectCommunityChanges(copy.config.CommunityDescription)
|
changes := EvaluateCommunityChanges(o.config.CommunityDescription, copy.config.CommunityDescription)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: need to figure out is it ok to save marshaledCommunityDescription without the signature
|
// TODO: need to figure out is it ok to save marshaledCommunityDescription without the signature
|
||||||
marshaledCommDescr, err := proto.Marshal(copy.config.CommunityDescription)
|
marshaledCommDescr, err := proto.Marshal(copy.config.CommunityDescription)
|
||||||
|
|
Loading…
Reference in New Issue