feat: add pending state for token permissions
iterates: status-im/status-desktop#11852
This commit is contained in:
parent
a31dea7988
commit
a12e87dac6
|
@ -104,26 +104,26 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
|||
return nil, errors.New("member identity not set")
|
||||
}
|
||||
communityItem := struct {
|
||||
ID types.HexBytes `json:"id"`
|
||||
Verified bool `json:"verified"`
|
||||
Chats map[string]CommunityChat `json:"chats"`
|
||||
Categories map[string]CommunityCategory `json:"categories"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
IntroMessage string `json:"introMessage"`
|
||||
OutroMessage string `json:"outroMessage"`
|
||||
Tags []CommunityTag `json:"tags"`
|
||||
Images map[string]images.IdentityImage `json:"images"`
|
||||
Color string `json:"color"`
|
||||
MembersCount int `json:"membersCount"`
|
||||
EnsName string `json:"ensName"`
|
||||
Link string `json:"link"`
|
||||
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
BanList []string `json:"banList"`
|
||||
TokenPermissions map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissions"`
|
||||
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
||||
ActiveMembersCount uint64 `json:"activeMembersCount"`
|
||||
ID types.HexBytes `json:"id"`
|
||||
Verified bool `json:"verified"`
|
||||
Chats map[string]CommunityChat `json:"chats"`
|
||||
Categories map[string]CommunityCategory `json:"categories"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
IntroMessage string `json:"introMessage"`
|
||||
OutroMessage string `json:"outroMessage"`
|
||||
Tags []CommunityTag `json:"tags"`
|
||||
Images map[string]images.IdentityImage `json:"images"`
|
||||
Color string `json:"color"`
|
||||
MembersCount int `json:"membersCount"`
|
||||
EnsName string `json:"ensName"`
|
||||
Link string `json:"link"`
|
||||
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
BanList []string `json:"banList"`
|
||||
TokenPermissions map[string]*CommunityTokenPermission `json:"tokenPermissions"`
|
||||
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
||||
ActiveMembersCount uint64 `json:"activeMembersCount"`
|
||||
}{
|
||||
ID: o.ID(),
|
||||
Verified: o.config.Verified,
|
||||
|
@ -161,7 +161,7 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
|||
communityItem.Chats[id] = chat
|
||||
}
|
||||
|
||||
communityItem.TokenPermissions = o.config.CommunityDescription.TokenPermissions
|
||||
communityItem.TokenPermissions = o.tokenPermissions()
|
||||
communityItem.MembersCount = len(o.config.CommunityDescription.Members)
|
||||
communityItem.Link = fmt.Sprintf("https://join.status.im/c/0x%x", o.ID())
|
||||
communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage
|
||||
|
@ -199,38 +199,38 @@ func (o *Community) MarshalJSON() ([]byte, error) {
|
|||
return nil, errors.New("member identity not set")
|
||||
}
|
||||
communityItem := struct {
|
||||
ID types.HexBytes `json:"id"`
|
||||
MemberRole protobuf.CommunityMember_Roles `json:"memberRole"`
|
||||
IsControlNode bool `json:"isControlNode"`
|
||||
Verified bool `json:"verified"`
|
||||
Joined bool `json:"joined"`
|
||||
Spectated bool `json:"spectated"`
|
||||
RequestedAccessAt int `json:"requestedAccessAt"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
IntroMessage string `json:"introMessage"`
|
||||
OutroMessage string `json:"outroMessage"`
|
||||
Tags []CommunityTag `json:"tags"`
|
||||
Chats map[string]CommunityChat `json:"chats"`
|
||||
Categories map[string]CommunityCategory `json:"categories"`
|
||||
Images map[string]images.IdentityImage `json:"images"`
|
||||
Permissions *protobuf.CommunityPermissions `json:"permissions"`
|
||||
Members map[string]*protobuf.CommunityMember `json:"members"`
|
||||
CanRequestAccess bool `json:"canRequestAccess"`
|
||||
CanManageUsers bool `json:"canManageUsers"` //TODO: we can remove this
|
||||
CanDeleteMessageForEveryone bool `json:"canDeleteMessageForEveryone"` //TODO: we can remove this
|
||||
CanJoin bool `json:"canJoin"`
|
||||
Color string `json:"color"`
|
||||
RequestedToJoinAt uint64 `json:"requestedToJoinAt,omitempty"`
|
||||
IsMember bool `json:"isMember"`
|
||||
Muted bool `json:"muted"`
|
||||
MuteTill time.Time `json:"muteTill,omitempty"`
|
||||
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
BanList []string `json:"banList"`
|
||||
TokenPermissions map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissions"`
|
||||
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
||||
ActiveMembersCount uint64 `json:"activeMembersCount"`
|
||||
ID types.HexBytes `json:"id"`
|
||||
MemberRole protobuf.CommunityMember_Roles `json:"memberRole"`
|
||||
IsControlNode bool `json:"isControlNode"`
|
||||
Verified bool `json:"verified"`
|
||||
Joined bool `json:"joined"`
|
||||
Spectated bool `json:"spectated"`
|
||||
RequestedAccessAt int `json:"requestedAccessAt"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
IntroMessage string `json:"introMessage"`
|
||||
OutroMessage string `json:"outroMessage"`
|
||||
Tags []CommunityTag `json:"tags"`
|
||||
Chats map[string]CommunityChat `json:"chats"`
|
||||
Categories map[string]CommunityCategory `json:"categories"`
|
||||
Images map[string]images.IdentityImage `json:"images"`
|
||||
Permissions *protobuf.CommunityPermissions `json:"permissions"`
|
||||
Members map[string]*protobuf.CommunityMember `json:"members"`
|
||||
CanRequestAccess bool `json:"canRequestAccess"`
|
||||
CanManageUsers bool `json:"canManageUsers"` //TODO: we can remove this
|
||||
CanDeleteMessageForEveryone bool `json:"canDeleteMessageForEveryone"` //TODO: we can remove this
|
||||
CanJoin bool `json:"canJoin"`
|
||||
Color string `json:"color"`
|
||||
RequestedToJoinAt uint64 `json:"requestedToJoinAt,omitempty"`
|
||||
IsMember bool `json:"isMember"`
|
||||
Muted bool `json:"muted"`
|
||||
MuteTill time.Time `json:"muteTill,omitempty"`
|
||||
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
BanList []string `json:"banList"`
|
||||
TokenPermissions map[string]*CommunityTokenPermission `json:"tokenPermissions"`
|
||||
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
||||
ActiveMembersCount uint64 `json:"activeMembersCount"`
|
||||
}{
|
||||
ID: o.ID(),
|
||||
MemberRole: o.MemberRole(o.MemberIdentity()),
|
||||
|
@ -280,7 +280,7 @@ func (o *Community) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
communityItem.Chats[id] = chat
|
||||
}
|
||||
communityItem.TokenPermissions = o.config.CommunityDescription.TokenPermissions
|
||||
communityItem.TokenPermissions = o.tokenPermissions()
|
||||
communityItem.Members = o.config.CommunityDescription.Members
|
||||
communityItem.Permissions = o.config.CommunityDescription.Permissions
|
||||
communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage
|
||||
|
@ -949,15 +949,16 @@ func (o *Community) UpdateCommunityDescription(description *protobuf.CommunityDe
|
|||
return response, nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
response = EvaluateCommunityChanges(o.config.CommunityDescription, description)
|
||||
response.Community = o
|
||||
}
|
||||
originCommunity := o.CreateDeepCopy()
|
||||
|
||||
o.config.CommunityDescription = description
|
||||
o.config.CommunityDescriptionProtocolMessage = rawMessage
|
||||
|
||||
// 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 {
|
||||
response = EvaluateCommunityChanges(originCommunity, o)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
@ -1315,20 +1316,64 @@ func (o *Community) Categories() map[string]*protobuf.CommunityCategory {
|
|||
return response
|
||||
}
|
||||
|
||||
func (o *Community) TokenPermissions() map[string]*protobuf.CommunityTokenPermission {
|
||||
return o.config.CommunityDescription.TokenPermissions
|
||||
func (o *Community) tokenPermissions() map[string]*CommunityTokenPermission {
|
||||
result := make(map[string]*CommunityTokenPermission, len(o.config.CommunityDescription.TokenPermissions))
|
||||
for _, tokenPermission := range o.config.CommunityDescription.TokenPermissions {
|
||||
result[tokenPermission.Id] = NewCommunityTokenPermission(tokenPermission)
|
||||
}
|
||||
|
||||
// Non-privileged members should not see pending permissions
|
||||
if o.config.EventsData == nil || !o.IsPrivilegedMember(o.MemberIdentity()) {
|
||||
return result
|
||||
}
|
||||
|
||||
processedPermissions := make(map[string]*struct{})
|
||||
for _, event := range o.config.EventsData.Events {
|
||||
if event.TokenPermission == nil || processedPermissions[event.TokenPermission.Id] != nil {
|
||||
continue
|
||||
}
|
||||
processedPermissions[event.TokenPermission.Id] = &struct{}{} // first permission event wins
|
||||
|
||||
switch event.Type {
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE:
|
||||
tokenPermission := result[event.TokenPermission.Id]
|
||||
if tokenPermission != nil {
|
||||
tokenPermission.State = TokenPermissionUpdatePending
|
||||
} else {
|
||||
tokenPermission := NewCommunityTokenPermission(event.TokenPermission)
|
||||
tokenPermission.State = TokenPermissionAdditionPending
|
||||
result[event.TokenPermission.Id] = tokenPermission
|
||||
}
|
||||
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE:
|
||||
tokenPermission := result[event.TokenPermission.Id]
|
||||
if tokenPermission != nil {
|
||||
tokenPermission.State = TokenPermissionRemovalPending
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (o *Community) TokenPermissions() map[string]*CommunityTokenPermission {
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
return o.tokenPermissions()
|
||||
}
|
||||
|
||||
func (o *Community) HasTokenPermissions() bool {
|
||||
return o.config.CommunityDescription.TokenPermissions != nil && len(o.config.CommunityDescription.TokenPermissions) > 0
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
return len(o.tokenPermissions()) > 0
|
||||
}
|
||||
|
||||
func (o *Community) ChannelHasTokenPermissions(chatID string) bool {
|
||||
if !o.HasTokenPermissions() {
|
||||
return false
|
||||
}
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
|
||||
for _, tokenPermission := range o.TokenPermissions() {
|
||||
for _, tokenPermission := range o.tokenPermissions() {
|
||||
if includes(tokenPermission.ChatIds, chatID) {
|
||||
return true
|
||||
}
|
||||
|
@ -1337,8 +1382,8 @@ func (o *Community) ChannelHasTokenPermissions(chatID string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func TokenPermissionsByType(permissions map[string]*protobuf.CommunityTokenPermission, permissionType protobuf.CommunityTokenPermission_Type) []*protobuf.CommunityTokenPermission {
|
||||
result := make([]*protobuf.CommunityTokenPermission, 0)
|
||||
func TokenPermissionsByType(permissions map[string]*CommunityTokenPermission, permissionType protobuf.CommunityTokenPermission_Type) []*CommunityTokenPermission {
|
||||
result := make([]*CommunityTokenPermission, 0)
|
||||
for _, tokenPermission := range permissions {
|
||||
if tokenPermission.Type == permissionType {
|
||||
result = append(result, tokenPermission)
|
||||
|
@ -1347,22 +1392,24 @@ func TokenPermissionsByType(permissions map[string]*protobuf.CommunityTokenPermi
|
|||
return result
|
||||
}
|
||||
|
||||
func (o *Community) tokenPermissionByID(ID string) *protobuf.CommunityTokenPermission {
|
||||
permissions := o.config.CommunityDescription.TokenPermissions
|
||||
if permissions == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return permissions[ID]
|
||||
func (o *Community) tokenPermissionByID(ID string) *CommunityTokenPermission {
|
||||
return o.tokenPermissions()[ID]
|
||||
}
|
||||
|
||||
func (o *Community) TokenPermissionsByType(permissionType protobuf.CommunityTokenPermission_Type) []*protobuf.CommunityTokenPermission {
|
||||
return TokenPermissionsByType(o.TokenPermissions(), permissionType)
|
||||
func (o *Community) TokenPermissionByID(ID string) *CommunityTokenPermission {
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
|
||||
return o.tokenPermissionByID(ID)
|
||||
}
|
||||
|
||||
func (o *Community) ChannelTokenPermissionsByType(channelID string, permissionType protobuf.CommunityTokenPermission_Type) []*protobuf.CommunityTokenPermission {
|
||||
permissions := make([]*protobuf.CommunityTokenPermission, 0)
|
||||
for _, tokenPermission := range o.TokenPermissions() {
|
||||
func (o *Community) TokenPermissionsByType(permissionType protobuf.CommunityTokenPermission_Type) []*CommunityTokenPermission {
|
||||
return TokenPermissionsByType(o.tokenPermissions(), permissionType)
|
||||
}
|
||||
|
||||
func (o *Community) ChannelTokenPermissionsByType(channelID string, permissionType protobuf.CommunityTokenPermission_Type) []*CommunityTokenPermission {
|
||||
permissions := make([]*CommunityTokenPermission, 0)
|
||||
for _, tokenPermission := range o.tokenPermissions() {
|
||||
if tokenPermission.Type == permissionType && includes(tokenPermission.ChatIds, channelID) {
|
||||
permissions = append(permissions, tokenPermission)
|
||||
}
|
||||
|
@ -1387,57 +1434,80 @@ func (o *Community) UpsertTokenPermission(tokenPermission *protobuf.CommunityTok
|
|||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
|
||||
if !(o.IsControlNode() || o.hasPermissionToSendTokenPermissionCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE, tokenPermission.Type)) {
|
||||
return nil, ErrNotAuthorized
|
||||
}
|
||||
|
||||
changes, err := o.upsertTokenPermission(tokenPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if o.IsControlNode() {
|
||||
changes, err := o.upsertTokenPermission(tokenPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
o.updateEncrypted()
|
||||
o.increaseClock()
|
||||
} else {
|
||||
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
if o.hasPermissionToSendTokenPermissionCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE, tokenPermission.Type) {
|
||||
existed := o.tokenPermissionByID(tokenPermission.Id) != nil
|
||||
|
||||
err := o.addNewCommunityEvent(o.ToCommunityTokenPermissionChangeCommunityEvent(tokenPermission))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
permission := NewCommunityTokenPermission(tokenPermission)
|
||||
|
||||
changes := o.emptyCommunityChanges()
|
||||
if existed {
|
||||
permission.State = TokenPermissionUpdatePending
|
||||
changes.TokenPermissionsModified[tokenPermission.Id] = permission
|
||||
} else {
|
||||
permission.State = TokenPermissionAdditionPending
|
||||
changes.TokenPermissionsAdded[tokenPermission.Id] = permission
|
||||
}
|
||||
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
return changes, nil
|
||||
return nil, ErrNotAuthorized
|
||||
}
|
||||
|
||||
func (o *Community) DeleteTokenPermission(permissionID string) (*CommunityChanges, error) {
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
|
||||
permission, exists := o.config.CommunityDescription.TokenPermissions[permissionID]
|
||||
tokenPermission, exists := o.config.CommunityDescription.TokenPermissions[permissionID]
|
||||
if !exists {
|
||||
return nil, ErrTokenPermissionNotFound
|
||||
}
|
||||
|
||||
if !(o.IsControlNode() || o.hasPermissionToSendTokenPermissionCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE, permission.Type)) {
|
||||
return nil, ErrNotAuthorized
|
||||
}
|
||||
|
||||
changes, err := o.deleteTokenPermission(permissionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if o.IsControlNode() {
|
||||
o.updateEncrypted()
|
||||
o.increaseClock()
|
||||
} else {
|
||||
err := o.addNewCommunityEvent(o.ToCommunityTokenPermissionDeleteCommunityEvent(permission))
|
||||
changes, err := o.deleteTokenPermission(permissionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
o.updateEncrypted()
|
||||
o.increaseClock()
|
||||
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
return changes, nil
|
||||
if o.hasPermissionToSendTokenPermissionCommunityEvent(protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE, tokenPermission.Type) {
|
||||
err := o.addNewCommunityEvent(o.ToCommunityTokenPermissionDeleteCommunityEvent(tokenPermission))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
permission := NewCommunityTokenPermission(tokenPermission)
|
||||
permission.State = TokenPermissionRemovalPending
|
||||
|
||||
changes := o.emptyCommunityChanges()
|
||||
changes.TokenPermissionsModified[permission.Id] = permission
|
||||
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
return nil, ErrNotAuthorized
|
||||
}
|
||||
|
||||
func (o *Community) VerifyGrantSignature(data []byte) (*protobuf.Grant, error) {
|
||||
|
@ -1989,9 +2059,9 @@ func (o *Community) upsertTokenPermission(permission *protobuf.CommunityTokenPer
|
|||
|
||||
changes := o.emptyCommunityChanges()
|
||||
if existed {
|
||||
changes.TokenPermissionsModified[permission.Id] = permission
|
||||
changes.TokenPermissionsModified[permission.Id] = NewCommunityTokenPermission(permission)
|
||||
} else {
|
||||
changes.TokenPermissionsAdded[permission.Id] = permission
|
||||
changes.TokenPermissionsAdded[permission.Id] = NewCommunityTokenPermission(permission)
|
||||
}
|
||||
|
||||
return changes, nil
|
||||
|
@ -2007,7 +2077,7 @@ func (o *Community) deleteTokenPermission(permissionID string) (*CommunityChange
|
|||
|
||||
changes := o.emptyCommunityChanges()
|
||||
|
||||
changes.TokenPermissionsRemoved[permissionID] = permission
|
||||
changes.TokenPermissionsRemoved[permissionID] = NewCommunityTokenPermission(permission)
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ type CommunityChanges struct {
|
|||
MembersAdded map[string]*protobuf.CommunityMember `json:"membersAdded"`
|
||||
MembersRemoved map[string]*protobuf.CommunityMember `json:"membersRemoved"`
|
||||
|
||||
TokenPermissionsAdded map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissionsAdded"`
|
||||
TokenPermissionsModified map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissionsModified"`
|
||||
TokenPermissionsRemoved map[string]*protobuf.CommunityTokenPermission `json:"tokenPermissionsRemoved"`
|
||||
TokenPermissionsAdded map[string]*CommunityTokenPermission `json:"tokenPermissionsAdded"`
|
||||
TokenPermissionsModified map[string]*CommunityTokenPermission `json:"tokenPermissionsModified"`
|
||||
TokenPermissionsRemoved map[string]*CommunityTokenPermission `json:"tokenPermissionsRemoved"`
|
||||
|
||||
ChatsRemoved map[string]*protobuf.CommunityChat `json:"chatsRemoved"`
|
||||
ChatsAdded map[string]*protobuf.CommunityChat `json:"chatsAdded"`
|
||||
|
@ -46,9 +46,9 @@ func EmptyCommunityChanges() *CommunityChanges {
|
|||
MembersAdded: 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),
|
||||
TokenPermissionsAdded: make(map[string]*CommunityTokenPermission),
|
||||
TokenPermissionsModified: make(map[string]*CommunityTokenPermission),
|
||||
TokenPermissionsRemoved: make(map[string]*CommunityTokenPermission),
|
||||
|
||||
ChatsRemoved: make(map[string]*protobuf.CommunityChat),
|
||||
ChatsAdded: make(map[string]*protobuf.CommunityChat),
|
||||
|
@ -79,7 +79,35 @@ func (c *CommunityChanges) HasMemberLeft(identity string) bool {
|
|||
return ok
|
||||
}
|
||||
|
||||
func EvaluateCommunityChanges(origin, modified *protobuf.CommunityDescription) *CommunityChanges {
|
||||
func EvaluateCommunityChanges(origin, modified *Community) *CommunityChanges {
|
||||
changes := evaluateCommunityChangesByDescription(origin.Description(), modified.Description())
|
||||
|
||||
originTokenPermissions := origin.tokenPermissions()
|
||||
modifiedTokenPermissions := modified.tokenPermissions()
|
||||
|
||||
// Check for modified or removed token permissions
|
||||
for id, originPermission := range originTokenPermissions {
|
||||
if modifiedPermission := modifiedTokenPermissions[id]; modifiedPermission != nil {
|
||||
if !modifiedPermission.Equals(originPermission) {
|
||||
changes.TokenPermissionsModified[id] = modifiedPermission
|
||||
}
|
||||
} else {
|
||||
changes.TokenPermissionsRemoved[id] = originPermission
|
||||
}
|
||||
}
|
||||
|
||||
// Check for added token permissions
|
||||
for id, permission := range modifiedTokenPermissions {
|
||||
if _, ok := originTokenPermissions[id]; !ok {
|
||||
changes.TokenPermissionsAdded[id] = permission
|
||||
}
|
||||
}
|
||||
|
||||
changes.Community = modified
|
||||
return changes
|
||||
}
|
||||
|
||||
func evaluateCommunityChangesByDescription(origin, modified *protobuf.CommunityDescription) *CommunityChanges {
|
||||
changes := EmptyCommunityChanges()
|
||||
|
||||
// Check for new members at the org level
|
||||
|
@ -229,19 +257,5 @@ func EvaluateCommunityChanges(origin, modified *protobuf.CommunityDescription) *
|
|||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func EvaluateCommunityEncryptionKeyActions(origin, modified *Community) *Encrypt
|
|||
}
|
||||
}
|
||||
|
||||
changes := EvaluateCommunityChanges(origin.Description(), modified.Description())
|
||||
changes := EvaluateCommunityChanges(origin, modified)
|
||||
|
||||
result := &EncryptionKeyActions{
|
||||
CommunityKeyAction: *evaluateCommunityLevelEncryptionKeyAction(origin, modified, changes),
|
||||
|
@ -89,7 +89,7 @@ func evaluateChannelLevelEncryptionKeyActions(origin, modified *Community, chang
|
|||
return &result
|
||||
}
|
||||
|
||||
func evaluateEncryptionKeyAction(originPermissions, modifiedPermissions []*protobuf.CommunityTokenPermission, allMembers, membersAdded, membersRemoved map[string]*protobuf.CommunityMember) *EncryptionKeyAction {
|
||||
func evaluateEncryptionKeyAction(originPermissions, modifiedPermissions []*CommunityTokenPermission, allMembers, membersAdded, membersRemoved map[string]*protobuf.CommunityMember) *EncryptionKeyAction {
|
||||
result := &EncryptionKeyAction{
|
||||
ActionType: EncryptionKeyNone,
|
||||
Members: map[string]*protobuf.CommunityMember{},
|
||||
|
|
|
@ -181,43 +181,34 @@ func (o *Community) ToAddTokenMetadataCommunityEvent(tokenMetadata *protobuf.Com
|
|||
}
|
||||
}
|
||||
|
||||
func (o *Community) UpdateCommunityByEvents(communityEventMessage *CommunityEventsMessage) (*CommunityChanges, error) {
|
||||
func (o *Community) UpdateCommunityByEvents(communityEventMessage *CommunityEventsMessage) error {
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
|
||||
// Validate that EventsBaseCommunityDescription was signed by the control node
|
||||
description, err := validateAndGetEventsMessageCommunityDescription(communityEventMessage.EventsBaseCommunityDescription, o.config.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if description.Clock != o.config.CommunityDescription.Clock {
|
||||
return nil, ErrInvalidCommunityEventClock
|
||||
return ErrInvalidCommunityEventClock
|
||||
}
|
||||
|
||||
// Create a deep copy of current community so we can update CommunityDescription by new admin events
|
||||
copy := o.CreateDeepCopy()
|
||||
|
||||
// Merge community admin events to existing community. Admin events must be stored to the db
|
||||
// Merge community events to existing community. Community events must be stored to the db
|
||||
// during saving the community
|
||||
o.mergeCommunityEvents(communityEventMessage)
|
||||
|
||||
copy.config.CommunityDescription = description
|
||||
copy.config.CommunityDescriptionProtocolMessage = communityEventMessage.EventsBaseCommunityDescription
|
||||
copy.config.EventsData = o.config.EventsData
|
||||
o.config.CommunityDescription = description
|
||||
o.config.CommunityDescriptionProtocolMessage = communityEventMessage.EventsBaseCommunityDescription
|
||||
|
||||
// Update the copy of the CommunityDescription by community events
|
||||
err = copy.updateCommunityDescriptionByEvents()
|
||||
err = o.updateCommunityDescriptionByEvents()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Evaluate `CommunityChanges` data by searching a difference between `CommunityDescription`
|
||||
// from the DB and `CommunityDescription` patched by community events
|
||||
changes := EvaluateCommunityChanges(o.config.CommunityDescription, copy.config.CommunityDescription)
|
||||
changes.Community = copy
|
||||
|
||||
return changes, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Community) updateCommunityDescriptionByEvents() error {
|
||||
|
@ -246,15 +237,19 @@ func (o *Community) updateCommunityDescriptionByCommunityEvent(communityEvent Co
|
|||
o.config.CommunityDescription.Tags = communityEvent.CommunityConfig.Tags
|
||||
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE:
|
||||
_, err := o.upsertTokenPermission(communityEvent.TokenPermission)
|
||||
if err != nil {
|
||||
return err
|
||||
if o.IsControlNode() {
|
||||
_, err := o.upsertTokenPermission(communityEvent.TokenPermission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE:
|
||||
_, err := o.deleteTokenPermission(communityEvent.TokenPermission.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
if o.IsControlNode() {
|
||||
_, err := o.deleteTokenPermission(communityEvent.TokenPermission.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case protobuf.CommunityEvent_COMMUNITY_CATEGORY_CREATE:
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package communities
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
)
|
||||
|
||||
type TokenPermissionState uint8
|
||||
|
||||
const (
|
||||
TokenPermissionApproved TokenPermissionState = iota
|
||||
TokenPermissionAdditionPending
|
||||
TokenPermissionUpdatePending
|
||||
TokenPermissionRemovalPending
|
||||
)
|
||||
|
||||
type CommunityTokenPermission struct {
|
||||
*protobuf.CommunityTokenPermission
|
||||
State TokenPermissionState `json:"state,omitempty"`
|
||||
}
|
||||
|
||||
func NewCommunityTokenPermission(base *protobuf.CommunityTokenPermission) *CommunityTokenPermission {
|
||||
return &CommunityTokenPermission{
|
||||
CommunityTokenPermission: base,
|
||||
State: TokenPermissionApproved,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *CommunityTokenPermission) Equals(other *CommunityTokenPermission) bool {
|
||||
if p.Id != other.Id ||
|
||||
p.Type != other.Type ||
|
||||
len(p.TokenCriteria) != len(other.TokenCriteria) ||
|
||||
len(p.ChatIds) != len(other.ChatIds) ||
|
||||
p.IsPrivate != other.IsPrivate ||
|
||||
p.State != other.State {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range p.TokenCriteria {
|
||||
if !compareTokenCriteria(p.TokenCriteria[i], other.TokenCriteria[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return reflect.DeepEqual(p.ChatIds, other.ChatIds)
|
||||
}
|
||||
|
||||
func compareTokenCriteria(a, b *protobuf.TokenCriteria) bool {
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return a.Type == b.Type &&
|
||||
a.Symbol == b.Symbol &&
|
||||
a.Name == b.Name &&
|
||||
a.Amount == b.Amount &&
|
||||
a.EnsPattern == b.EnsPattern &&
|
||||
a.Decimals == b.Decimals &&
|
||||
reflect.DeepEqual(a.ContractAddresses, b.ContractAddresses) &&
|
||||
reflect.DeepEqual(a.TokenIds, b.TokenIds)
|
||||
}
|
|
@ -1350,6 +1350,7 @@ func (m *Manager) handleCommunityDescriptionMessageCommon(community *Community,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
community.config.EventsData = nil
|
||||
|
||||
err = m.persistence.SaveCommunity(community)
|
||||
if err != nil {
|
||||
|
@ -1433,9 +1434,11 @@ func (m *Manager) HandleCommunityEventsMessage(signer *ecdsa.PublicKey, message
|
|||
return nil, errors.New("user has not permissions to send events")
|
||||
}
|
||||
|
||||
originCommunity := community.CreateDeepCopy()
|
||||
|
||||
eventsMessage.Events = m.validateAndFilterEvents(community, eventsMessage.Events)
|
||||
|
||||
changes, err := community.UpdateCommunityByEvents(eventsMessage)
|
||||
err = community.UpdateCommunityByEvents(eventsMessage)
|
||||
if err != nil {
|
||||
if err == ErrInvalidCommunityEventClock && community.IsControlNode() {
|
||||
m.publish(&Subscription{
|
||||
|
@ -1447,7 +1450,7 @@ func (m *Manager) HandleCommunityEventsMessage(signer *ecdsa.PublicKey, message
|
|||
return nil, err
|
||||
}
|
||||
|
||||
additionalCommunityResponse, err := m.handleAdditionalAdminChanges(changes.Community)
|
||||
additionalCommunityResponse, err := m.handleAdditionalAdminChanges(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1456,30 +1459,30 @@ func (m *Manager) HandleCommunityEventsMessage(signer *ecdsa.PublicKey, message
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Control node cerifies community events and publish changes
|
||||
// all other nodes only apply changes to the community
|
||||
if changes.Community.IsControlNode() {
|
||||
changes.Community.increaseClock()
|
||||
err = m.persistence.SaveCommunity(changes.Community)
|
||||
// Control node applies events and publish updated CommunityDescription
|
||||
if community.IsControlNode() {
|
||||
community.config.EventsData = nil // clear events, they are already applied
|
||||
community.increaseClock()
|
||||
err = m.persistence.SaveCommunity(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.publish(&Subscription{Community: changes.Community})
|
||||
m.publish(&Subscription{Community: community})
|
||||
} else {
|
||||
err = m.persistence.SaveCommunity(changes.Community)
|
||||
err = m.persistence.SaveCommunity(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err := m.persistence.SaveCommunityEvents(changes.Community)
|
||||
err := m.persistence.SaveCommunityEvents(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &CommunityResponse{
|
||||
Community: changes.Community,
|
||||
Changes: changes,
|
||||
Community: community,
|
||||
Changes: EvaluateCommunityChanges(originCommunity, community),
|
||||
RequestsToJoin: additionalCommunityResponse.RequestsToJoin,
|
||||
}, nil
|
||||
}
|
||||
|
@ -2320,7 +2323,7 @@ func calculateChainIDsSet(accountsAndChainIDs []*AccountChainIDsCombination, req
|
|||
// checkPermissions will retrieve balances and check whether the user has
|
||||
// permission to join the community, if shortcircuit is true, it will stop as soon
|
||||
// as we know the answer
|
||||
func (m *Manager) checkPermissions(permissions []*protobuf.CommunityTokenPermission, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error) {
|
||||
func (m *Manager) checkPermissions(permissions []*CommunityTokenPermission, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error) {
|
||||
|
||||
response := &CheckPermissionsResponse{
|
||||
Satisfied: false,
|
||||
|
@ -2661,7 +2664,7 @@ type CheckChannelViewAndPostPermissionsResult struct {
|
|||
Permissions map[string]*PermissionTokenCriteriaResult `json:"permissions"`
|
||||
}
|
||||
|
||||
func (m *Manager) checkChannelPermissions(viewOnlyPermissions []*protobuf.CommunityTokenPermission, viewAndPostPermissions []*protobuf.CommunityTokenPermission, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckChannelPermissionsResponse, error) {
|
||||
func (m *Manager) checkChannelPermissions(viewOnlyPermissions []*CommunityTokenPermission, viewAndPostPermissions []*CommunityTokenPermission, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckChannelPermissionsResponse, error) {
|
||||
|
||||
response := &CheckChannelPermissionsResponse{
|
||||
ViewOnlyPermissions: &CheckChannelViewOnlyPermissionsResult{
|
||||
|
@ -4477,7 +4480,7 @@ func revealedAccountsToAccountsAndChainIDsCombination(revealedAccounts []*protob
|
|||
return accountsAndChainIDs
|
||||
}
|
||||
|
||||
func (m *Manager) accountsHasPrivilegedPermission(privilegedPermissions []*protobuf.CommunityTokenPermission, accounts []*AccountChainIDsCombination) bool {
|
||||
func (m *Manager) accountsHasPrivilegedPermission(privilegedPermissions []*CommunityTokenPermission, accounts []*AccountChainIDsCombination) bool {
|
||||
if len(privilegedPermissions) > 0 {
|
||||
permissionResponse, err := m.checkPermissions(privilegedPermissions, accounts, true)
|
||||
if err != nil {
|
||||
|
@ -4551,7 +4554,7 @@ func (m *Manager) GetRevealedAddresses(communityID types.HexBytes, memberPk stri
|
|||
return m.persistence.GetRequestToJoinRevealedAddresses(requestID)
|
||||
}
|
||||
|
||||
func (m *Manager) ReevaluatePrivelegedMember(community *Community, tokenPermissions []*protobuf.CommunityTokenPermission,
|
||||
func (m *Manager) ReevaluatePrivelegedMember(community *Community, tokenPermissions []*CommunityTokenPermission,
|
||||
accountsAndChainIDs []*AccountChainIDsCombination, memberPubKey *ecdsa.PublicKey,
|
||||
privilegedRole protobuf.CommunityMember_Roles, alreadyHasPrivilegedRole bool) (bool, error) {
|
||||
|
||||
|
@ -4672,7 +4675,7 @@ func (m *Manager) HandleCommunityTokensMetadata(community *Community) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func getPrivilegesLevel(chainID uint64, tokenAddress string, tokenPermissions map[string]*protobuf.CommunityTokenPermission) community_token.PrivilegesLevel {
|
||||
func getPrivilegesLevel(chainID uint64, tokenAddress string, tokenPermissions map[string]*CommunityTokenPermission) community_token.PrivilegesLevel {
|
||||
for _, permission := range tokenPermissions {
|
||||
if permission.Type == protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER || permission.Type == protobuf.CommunityTokenPermission_BECOME_TOKEN_OWNER {
|
||||
for _, tokenCriteria := range permission.TokenCriteria {
|
||||
|
|
|
@ -187,11 +187,13 @@ func (s *ManagerSuite) TestRetrieveTokens() {
|
|||
},
|
||||
}
|
||||
|
||||
var permissions = []*protobuf.CommunityTokenPermission{
|
||||
&protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||
TokenCriteria: tokenCriteria,
|
||||
var permissions = []*CommunityTokenPermission{
|
||||
&CommunityTokenPermission{
|
||||
CommunityTokenPermission: &protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||
TokenCriteria: tokenCriteria,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -234,11 +236,13 @@ func (s *ManagerSuite) TestRetrieveCollectibles() {
|
|||
},
|
||||
}
|
||||
|
||||
var permissions = []*protobuf.CommunityTokenPermission{
|
||||
&protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||
TokenCriteria: tokenCriteria,
|
||||
var permissions = []*CommunityTokenPermission{
|
||||
&CommunityTokenPermission{
|
||||
CommunityTokenPermission: &protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
||||
TokenCriteria: tokenCriteria,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -905,8 +909,8 @@ func (s *ManagerSuite) TestCheckChannelPermissions_NoPermissions() {
|
|||
},
|
||||
}
|
||||
|
||||
var viewOnlyPermissions = make([]*protobuf.CommunityTokenPermission, 0)
|
||||
var viewAndPostPermissions = make([]*protobuf.CommunityTokenPermission, 0)
|
||||
var viewOnlyPermissions = make([]*CommunityTokenPermission, 0)
|
||||
var viewAndPostPermissions = make([]*CommunityTokenPermission, 0)
|
||||
|
||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
||||
resp, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
||||
|
@ -946,16 +950,18 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewOnlyPermissions() {
|
|||
},
|
||||
}
|
||||
|
||||
var viewOnlyPermissions = []*protobuf.CommunityTokenPermission{
|
||||
&protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||
TokenCriteria: tokenCriteria,
|
||||
ChatIds: []string{"test-channel-id", "test-channel-id-2"},
|
||||
var viewOnlyPermissions = []*CommunityTokenPermission{
|
||||
&CommunityTokenPermission{
|
||||
CommunityTokenPermission: &protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||
TokenCriteria: tokenCriteria,
|
||||
ChatIds: []string{"test-channel-id", "test-channel-id-2"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var viewAndPostPermissions = make([]*protobuf.CommunityTokenPermission, 0)
|
||||
var viewAndPostPermissions = make([]*CommunityTokenPermission, 0)
|
||||
|
||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
||||
resp, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
||||
|
@ -1004,16 +1010,18 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewAndPostPermissions() {
|
|||
},
|
||||
}
|
||||
|
||||
var viewAndPostPermissions = []*protobuf.CommunityTokenPermission{
|
||||
&protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||
TokenCriteria: tokenCriteria,
|
||||
ChatIds: []string{"test-channel-id", "test-channel-id-2"},
|
||||
var viewAndPostPermissions = []*CommunityTokenPermission{
|
||||
&CommunityTokenPermission{
|
||||
CommunityTokenPermission: &protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||
TokenCriteria: tokenCriteria,
|
||||
ChatIds: []string{"test-channel-id", "test-channel-id-2"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var viewOnlyPermissions = make([]*protobuf.CommunityTokenPermission, 0)
|
||||
var viewOnlyPermissions = make([]*CommunityTokenPermission, 0)
|
||||
|
||||
tm.setResponse(chainID, accountChainIDsCombination[0].Address, gethcommon.HexToAddress(contractAddresses[chainID]), 0)
|
||||
resp, err := m.checkChannelPermissions(viewOnlyPermissions, viewAndPostPermissions, accountChainIDsCombination, false)
|
||||
|
@ -1063,12 +1071,14 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewAndPostPermissionsCombina
|
|||
},
|
||||
}
|
||||
|
||||
var viewOnlyPermissions = []*protobuf.CommunityTokenPermission{
|
||||
&protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||
TokenCriteria: viewOnlyTokenCriteria,
|
||||
ChatIds: []string{"test-channel-id", "test-channel-id-2"},
|
||||
var viewOnlyPermissions = []*CommunityTokenPermission{
|
||||
&CommunityTokenPermission{
|
||||
CommunityTokenPermission: &protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||
TokenCriteria: viewOnlyTokenCriteria,
|
||||
ChatIds: []string{"test-channel-id", "test-channel-id-2"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -1087,12 +1097,14 @@ func (s *ManagerSuite) TestCheckChannelPermissions_ViewAndPostPermissionsCombina
|
|||
},
|
||||
}
|
||||
|
||||
var viewAndPostPermissions = []*protobuf.CommunityTokenPermission{
|
||||
&protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||
TokenCriteria: viewAndPostTokenCriteria,
|
||||
ChatIds: []string{"test-channel-id", "test-channel-id-2"},
|
||||
var viewAndPostPermissions = []*CommunityTokenPermission{
|
||||
&CommunityTokenPermission{
|
||||
CommunityTokenPermission: &protobuf.CommunityTokenPermission{
|
||||
Id: "some-id",
|
||||
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||
TokenCriteria: viewAndPostTokenCriteria,
|
||||
ChatIds: []string{"test-channel-id", "test-channel-id-2"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ func CalculateRequestID(publicKey string, communityID types.HexBytes) types.HexB
|
|||
return crypto.Keccak256([]byte(idString))
|
||||
}
|
||||
|
||||
func ExtractTokenCriteria(permissions []*protobuf.CommunityTokenPermission) (erc20TokenCriteria map[uint64]map[string]*protobuf.TokenCriteria, erc721TokenCriteria map[uint64]map[string]*protobuf.TokenCriteria, ensTokenCriteria []string) {
|
||||
func ExtractTokenCriteria(permissions []*CommunityTokenPermission) (erc20TokenCriteria map[uint64]map[string]*protobuf.TokenCriteria, erc721TokenCriteria map[uint64]map[string]*protobuf.TokenCriteria, ensTokenCriteria []string) {
|
||||
erc20TokenCriteria = make(map[uint64]map[string]*protobuf.TokenCriteria)
|
||||
erc721TokenCriteria = make(map[uint64]map[string]*protobuf.TokenCriteria)
|
||||
ensTokenCriteria = make([]string, 0)
|
||||
|
|
|
@ -277,34 +277,44 @@ func createTestPermissionRequest(community *communities.Community, pType protobu
|
|||
}
|
||||
|
||||
func createTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, request *requests.CreateCommunityTokenPermission) (string, *requests.CreateCommunityTokenPermission) {
|
||||
checkTokenPermissionCreation := func(response *MessengerResponse) error {
|
||||
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(modifiedCommmunity.TokenPermissionsByType(request.Type)) == 0 {
|
||||
return errors.New("new token permission was not found")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
response, err := base.GetEventSender().CreateCommunityTokenPermission(request)
|
||||
s := base.GetSuite()
|
||||
s.Require().NoError(err)
|
||||
s.Require().Nil(checkTokenPermissionCreation(response))
|
||||
s.Require().Len(response.CommunityChanges, 1)
|
||||
s.Require().Len(response.CommunityChanges[0].TokenPermissionsAdded, 1)
|
||||
|
||||
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkTokenPermissionCreation)
|
||||
addedPermission := func() *communities.CommunityTokenPermission {
|
||||
for _, permission := range response.CommunityChanges[0].TokenPermissionsAdded {
|
||||
return permission
|
||||
}
|
||||
return nil
|
||||
}()
|
||||
s.Require().NotNil(addedPermission)
|
||||
// Permission added by event must be in pending state
|
||||
s.Require().Equal(communities.TokenPermissionAdditionPending, addedPermission.State)
|
||||
|
||||
var tokenPermissionID string
|
||||
for tokenPermissionID = range response.CommunityChanges[0].TokenPermissionsAdded {
|
||||
break
|
||||
responseHasApprovedTokenPermission := func(r *MessengerResponse) bool {
|
||||
if len(r.Communities()) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
receivedPermission := r.Communities()[0].TokenPermissionByID(addedPermission.Id)
|
||||
return receivedPermission != nil && receivedPermission.State == communities.TokenPermissionApproved
|
||||
}
|
||||
|
||||
s.Require().NotEqual(tokenPermissionID, "")
|
||||
// Control node receives community event & approves it
|
||||
_, err = WaitOnMessengerResponse(base.GetControlNode(), responseHasApprovedTokenPermission, "community with approved permission not found")
|
||||
s.Require().NoError(err)
|
||||
|
||||
return tokenPermissionID, request
|
||||
// Member receives updated community description
|
||||
_, err = WaitOnMessengerResponse(base.GetMember(), responseHasApprovedTokenPermission, "community with approved permission not found")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// EventSender receives updated community description
|
||||
_, err = WaitOnMessengerResponse(base.GetEventSender(), responseHasApprovedTokenPermission, "community with approved permission not found")
|
||||
s.Require().NoError(err)
|
||||
|
||||
return addedPermission.Id, request
|
||||
}
|
||||
|
||||
func createTestTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) (string, *requests.CreateCommunityTokenPermission) {
|
||||
|
@ -314,54 +324,79 @@ func createTestTokenPermission(base CommunityEventsTestsInterface, community *co
|
|||
|
||||
func editTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, request *requests.EditCommunityTokenPermission) {
|
||||
s := base.GetSuite()
|
||||
checkTokenPermissionEdit := func(response *MessengerResponse) error {
|
||||
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
assertCheckTokenPermissionEdited(s, modifiedCommmunity, request.CreateCommunityTokenPermission.Type)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
response, err := base.GetEventSender().EditCommunityTokenPermission(request)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Nil(checkTokenPermissionEdit(response))
|
||||
s.Require().Len(response.CommunityChanges, 1)
|
||||
s.Require().Len(response.CommunityChanges[0].TokenPermissionsModified, 1)
|
||||
|
||||
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkTokenPermissionEdit)
|
||||
}
|
||||
editedPermission := response.CommunityChanges[0].TokenPermissionsModified[request.PermissionID]
|
||||
s.Require().NotNil(editedPermission)
|
||||
// Permission edited by event must be in pending state
|
||||
s.Require().Equal(communities.TokenPermissionUpdatePending, editedPermission.State)
|
||||
|
||||
func assertCheckTokenPermissionEdited(s *suite.Suite, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
|
||||
permissions := community.TokenPermissionsByType(pType)
|
||||
s.Require().Len(permissions, 1)
|
||||
s.Require().Len(permissions[0].TokenCriteria, 1)
|
||||
s.Require().Equal(permissions[0].TokenCriteria[0].Type, protobuf.CommunityTokenType_ERC20)
|
||||
s.Require().Equal(permissions[0].TokenCriteria[0].Symbol, "UPDATED")
|
||||
s.Require().Equal(permissions[0].TokenCriteria[0].Amount, "200")
|
||||
s.Require().Equal(permissions[0].TokenCriteria[0].Decimals, uint64(18))
|
||||
permissionSatisfyRequest := func(p *communities.CommunityTokenPermission) bool {
|
||||
return request.Type == p.Type &&
|
||||
request.TokenCriteria[0].Symbol == p.TokenCriteria[0].Symbol &&
|
||||
request.TokenCriteria[0].Amount == p.TokenCriteria[0].Amount &&
|
||||
request.TokenCriteria[0].Decimals == p.TokenCriteria[0].Decimals
|
||||
}
|
||||
s.Require().True(permissionSatisfyRequest(editedPermission))
|
||||
|
||||
responseHasApprovedEditedTokenPermission := func(r *MessengerResponse) bool {
|
||||
if len(r.Communities()) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
receivedPermission := r.Communities()[0].TokenPermissionByID(editedPermission.Id)
|
||||
return receivedPermission != nil && receivedPermission.State == communities.TokenPermissionApproved &&
|
||||
permissionSatisfyRequest(receivedPermission)
|
||||
}
|
||||
|
||||
// Control node receives community event & approves it
|
||||
_, err = WaitOnMessengerResponse(base.GetControlNode(), responseHasApprovedEditedTokenPermission, "community with approved permission not found")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Member receives updated community description
|
||||
_, err = WaitOnMessengerResponse(base.GetMember(), responseHasApprovedEditedTokenPermission, "community with approved permission not found")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// EventSender receives updated community description
|
||||
_, err = WaitOnMessengerResponse(base.GetEventSender(), responseHasApprovedEditedTokenPermission, "community with approved permission not found")
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func deleteTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, request *requests.DeleteCommunityTokenPermission) {
|
||||
checkTokenPermissionDeleted := func(response *MessengerResponse) error {
|
||||
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if modifiedCommmunity.HasTokenPermissions() {
|
||||
return errors.New("token permission was not deleted")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
response, err := base.GetEventSender().DeleteCommunityTokenPermission(request)
|
||||
s := base.GetSuite()
|
||||
s.Require().NoError(err)
|
||||
s.Require().Nil(checkTokenPermissionDeleted(response))
|
||||
s.Require().Len(response.CommunityChanges, 1)
|
||||
s.Require().Len(response.CommunityChanges[0].TokenPermissionsModified, 1)
|
||||
|
||||
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkTokenPermissionDeleted)
|
||||
removedPermission := response.CommunityChanges[0].TokenPermissionsModified[request.PermissionID]
|
||||
s.Require().NotNil(removedPermission)
|
||||
// Permission removed by event must be in pending state
|
||||
s.Require().Equal(communities.TokenPermissionRemovalPending, removedPermission.State)
|
||||
|
||||
responseHasNoTokenPermission := func(r *MessengerResponse) bool {
|
||||
if len(r.Communities()) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return r.Communities()[0].TokenPermissionByID(removedPermission.Id) == nil
|
||||
}
|
||||
|
||||
// Control node receives community event & approves it
|
||||
_, err = WaitOnMessengerResponse(base.GetControlNode(), responseHasNoTokenPermission, "community with approved permission not found")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Member receives updated community description
|
||||
_, err = WaitOnMessengerResponse(base.GetMember(), responseHasNoTokenPermission, "community with approved permission not found")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// EventSender receives updated community description
|
||||
_, err = WaitOnMessengerResponse(base.GetEventSender(), responseHasNoTokenPermission, "community with approved permission not found")
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func assertCheckTokenPermissionCreated(s *suite.Suite, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
|
||||
|
|
|
@ -1001,7 +1001,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) testReevaluateMemberPrivileg
|
|||
|
||||
s.advertiseCommunityTo(community, s.alice)
|
||||
|
||||
var tokenPermission *protobuf.CommunityTokenPermission
|
||||
var tokenPermission *communities.CommunityTokenPermission
|
||||
for _, tokenPermission = range community.TokenPermissions() {
|
||||
break
|
||||
}
|
||||
|
@ -1110,8 +1110,8 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) testReevaluateMemberPrivileg
|
|||
|
||||
s.advertiseCommunityTo(community, s.alice)
|
||||
|
||||
var tokenPermission *protobuf.CommunityTokenPermission
|
||||
var tokenMemberPermission *protobuf.CommunityTokenPermission
|
||||
var tokenPermission *communities.CommunityTokenPermission
|
||||
var tokenMemberPermission *communities.CommunityTokenPermission
|
||||
for _, permission := range community.TokenPermissions() {
|
||||
if permission.Type == protobuf.CommunityTokenPermission_BECOME_MEMBER {
|
||||
tokenMemberPermission = permission
|
||||
|
|
Loading…
Reference in New Issue