993 lines
35 KiB
Go
993 lines
35 KiB
Go
package communities
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"github.com/status-im/status-go/eth-node/crypto"
|
|
"github.com/status-im/status-go/eth-node/types"
|
|
"github.com/status-im/status-go/protocol/common"
|
|
"github.com/status-im/status-go/protocol/protobuf"
|
|
)
|
|
|
|
func createTestCommunity(identity *ecdsa.PrivateKey) (*Community, error) {
|
|
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{},
|
|
TokenPermissions: map[string]*protobuf.CommunityTokenPermission{},
|
|
CommunityTokensMetadata: []*protobuf.CommunityTokenMetadata{},
|
|
},
|
|
ID: &identity.PublicKey,
|
|
ControlNode: &identity.PublicKey,
|
|
ControlDevice: true,
|
|
Joined: true,
|
|
MemberIdentity: identity,
|
|
}
|
|
|
|
return New(config, &TimeSourceStub{}, &DescriptionEncryptorMock{})
|
|
}
|
|
|
|
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, err := createTestCommunity(s.identity)
|
|
s.Require().NoError(err)
|
|
|
|
// 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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
ChatIds: []string{"some-chat-id"},
|
|
},
|
|
},
|
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
|
&protobuf.CommunityTokenPermission{
|
|
Id: "some-id-1",
|
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
|
TokenCriteria: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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, err := createTestCommunity(s.identity)
|
|
s.Require().NoError(err)
|
|
modified := origin.CreateDeepCopy()
|
|
|
|
for _, permission := range tc.originPermissions {
|
|
_, err := origin.UpsertTokenPermission(permission)
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
for _, permission := range tc.modifiedPermissions {
|
|
_, err := modified.UpsertTokenPermission(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, err := createTestCommunity(s.identity)
|
|
s.Require().NoError(err)
|
|
|
|
for _, permission := range tc.permissions {
|
|
_, err := origin.UpsertTokenPermission(permission)
|
|
s.Require().NoError(err)
|
|
}
|
|
modified := origin.CreateDeepCopy()
|
|
|
|
for _, member := range tc.originMembers {
|
|
_, err := origin.AddMember(member, []protobuf.CommunityMember_Roles{}, origin.Clock())
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
for _, member := range tc.modifiedMembers {
|
|
_, err := modified.AddMember(member, []protobuf.CommunityMember_Roles{}, origin.Clock())
|
|
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, err := createTestCommunity(s.identity)
|
|
s.Require().NoError(err)
|
|
modified := origin.CreateDeepCopy()
|
|
|
|
for _, permission := range tc.originPermissions {
|
|
_, err := origin.UpsertTokenPermission(permission)
|
|
s.Require().NoError(err)
|
|
}
|
|
for _, member := range tc.originMembers {
|
|
_, err := origin.AddMember(member, []protobuf.CommunityMember_Roles{}, origin.Clock())
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
for _, permission := range tc.modifiedPermissions {
|
|
_, err := modified.UpsertTokenPermission(permission)
|
|
s.Require().NoError(err)
|
|
}
|
|
for _, member := range tc.modifiedMembers {
|
|
_, err := modified.AddMember(member, []protobuf.CommunityMember_Roles{}, origin.Clock())
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
actions := EvaluateCommunityEncryptionKeyActions(origin, modified)
|
|
s.Require().Equal(tc.expectedActionType, actions.CommunityKeyAction.ActionType)
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *CommunityEncryptionKeyActionSuite) TestChannelLevelKeyActions() {
|
|
channelID := "1234"
|
|
chatID := types.EncodeHex(crypto.CompressPubkey(&s.identity.PublicKey)) + channelID
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
ChatIds: []string{chatID},
|
|
},
|
|
},
|
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
|
&protobuf.CommunityTokenPermission{
|
|
Id: "some-id",
|
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
|
TokenCriteria: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
ChatIds: []string{chatID},
|
|
},
|
|
},
|
|
modifiedPermissions: []*protobuf.CommunityTokenPermission{
|
|
&protobuf.CommunityTokenPermission{
|
|
Id: "some-id",
|
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
|
TokenCriteria: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
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, err := createTestCommunity(s.identity)
|
|
s.Require().NoError(err)
|
|
|
|
_, err = origin.CreateChat(channelID, &protobuf.CommunityChat{
|
|
Members: map[string]*protobuf.CommunityMember{},
|
|
Permissions: &protobuf.CommunityPermissions{Access: protobuf.CommunityPermissions_AUTO_ACCEPT},
|
|
Identity: &protobuf.ChatIdentity{},
|
|
})
|
|
s.Require().NoError(err)
|
|
|
|
modified := origin.CreateDeepCopy()
|
|
|
|
for _, permission := range tc.originPermissions {
|
|
_, err := origin.UpsertTokenPermission(permission)
|
|
s.Require().NoError(err)
|
|
}
|
|
for _, member := range tc.originMembers {
|
|
_, err := origin.AddMember(member, []protobuf.CommunityMember_Roles{}, origin.Clock())
|
|
s.Require().NoError(err)
|
|
_, err = origin.AddMemberToChat(channelID, member, []protobuf.CommunityMember_Roles{}, protobuf.CommunityMember_CHANNEL_ROLE_POSTER)
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
for _, permission := range tc.modifiedPermissions {
|
|
_, err := modified.UpsertTokenPermission(permission)
|
|
s.Require().NoError(err)
|
|
}
|
|
for _, member := range tc.modifiedMembers {
|
|
_, err := modified.AddMember(member, []protobuf.CommunityMember_Roles{}, origin.Clock())
|
|
s.Require().NoError(err)
|
|
_, err = modified.AddMemberToChat(channelID, member, []protobuf.CommunityMember_Roles{}, protobuf.CommunityMember_CHANNEL_ROLE_POSTER)
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
actions := EvaluateCommunityEncryptionKeyActions(origin, modified)
|
|
channelAction, ok := actions.ChannelKeysActions[channelID]
|
|
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)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *CommunityEncryptionKeyActionSuite) TestNilOrigin() {
|
|
newCommunity, err := createTestCommunity(s.identity)
|
|
s.Require().NoError(err)
|
|
|
|
channelID := "0x1234"
|
|
chatID := types.EncodeHex(crypto.CompressPubkey(&s.identity.PublicKey)) + channelID
|
|
|
|
_, err = newCommunity.CreateChat(channelID, &protobuf.CommunityChat{
|
|
Members: map[string]*protobuf.CommunityMember{},
|
|
Permissions: &protobuf.CommunityPermissions{Access: protobuf.CommunityPermissions_AUTO_ACCEPT},
|
|
Identity: &protobuf.ChatIdentity{},
|
|
})
|
|
s.Require().NoError(err)
|
|
|
|
newCommunityPermissions := []*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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
ChatIds: []string{chatID},
|
|
},
|
|
}
|
|
for _, permission := range newCommunityPermissions {
|
|
_, err := newCommunity.UpsertTokenPermission(permission)
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
actions := EvaluateCommunityEncryptionKeyActions(nil, newCommunity)
|
|
s.Require().Equal(actions.CommunityKeyAction.ActionType, EncryptionKeyAdd)
|
|
s.Require().Len(actions.ChannelKeysActions, 1)
|
|
s.Require().NotNil(actions.ChannelKeysActions[channelID])
|
|
s.Require().Equal(actions.ChannelKeysActions[channelID].ActionType, EncryptionKeyAdd)
|
|
}
|
|
|
|
func (s *CommunityEncryptionKeyActionSuite) TestControlNodeChange() {
|
|
channelID := "1234"
|
|
chatID := types.EncodeHex(crypto.CompressPubkey(&s.identity.PublicKey)) + channelID
|
|
clock := uint64(time.Now().Unix())
|
|
testCases := []struct {
|
|
name string
|
|
permissions []*protobuf.CommunityTokenPermission
|
|
members []*ecdsa.PublicKey
|
|
channelMembers []*ecdsa.PublicKey
|
|
expectedActions EncryptionKeyActions
|
|
}{
|
|
{
|
|
name: "change control node in open community",
|
|
permissions: []*protobuf.CommunityTokenPermission{},
|
|
members: []*ecdsa.PublicKey{&s.member1.PublicKey, &s.member2.PublicKey},
|
|
channelMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
|
expectedActions: EncryptionKeyActions{
|
|
CommunityKeyAction: EncryptionKeyAction{
|
|
ActionType: EncryptionKeyNone,
|
|
Members: map[string]*protobuf.CommunityMember{},
|
|
},
|
|
ChannelKeysActions: map[string]EncryptionKeyAction{
|
|
channelID: EncryptionKeyAction{
|
|
ActionType: EncryptionKeyNone,
|
|
Members: map[string]*protobuf.CommunityMember{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "change control node in token-gated community",
|
|
permissions: []*protobuf.CommunityTokenPermission{
|
|
&protobuf.CommunityTokenPermission{
|
|
Id: "some-id",
|
|
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
|
|
TokenCriteria: make([]*protobuf.TokenCriteria, 0),
|
|
ChatIds: []string{},
|
|
},
|
|
},
|
|
members: []*ecdsa.PublicKey{&s.member1.PublicKey, &s.member2.PublicKey},
|
|
channelMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
|
expectedActions: EncryptionKeyActions{
|
|
CommunityKeyAction: EncryptionKeyAction{
|
|
ActionType: EncryptionKeyRekey,
|
|
Members: map[string]*protobuf.CommunityMember{
|
|
s.member1Key: &protobuf.CommunityMember{LastUpdateClock: clock},
|
|
s.member2Key: &protobuf.CommunityMember{LastUpdateClock: clock},
|
|
},
|
|
},
|
|
ChannelKeysActions: map[string]EncryptionKeyAction{
|
|
channelID: EncryptionKeyAction{
|
|
ActionType: EncryptionKeyNone,
|
|
Members: map[string]*protobuf.CommunityMember{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "change control node in open community with token-gated channel",
|
|
permissions: []*protobuf.CommunityTokenPermission{
|
|
&protobuf.CommunityTokenPermission{
|
|
Id: "some-id",
|
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
|
TokenCriteria: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
ChatIds: []string{chatID},
|
|
},
|
|
},
|
|
members: []*ecdsa.PublicKey{&s.member1.PublicKey, &s.member2.PublicKey},
|
|
channelMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
|
expectedActions: EncryptionKeyActions{
|
|
CommunityKeyAction: EncryptionKeyAction{
|
|
ActionType: EncryptionKeyNone,
|
|
Members: map[string]*protobuf.CommunityMember{},
|
|
},
|
|
ChannelKeysActions: map[string]EncryptionKeyAction{
|
|
channelID: EncryptionKeyAction{
|
|
ActionType: EncryptionKeyRekey,
|
|
Members: map[string]*protobuf.CommunityMember{
|
|
s.member1Key: &protobuf.CommunityMember{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "change control node in token-gated community with token-gated channel",
|
|
permissions: []*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: []*protobuf.TokenCriteria{&protobuf.TokenCriteria{}},
|
|
ChatIds: []string{chatID},
|
|
},
|
|
},
|
|
members: []*ecdsa.PublicKey{&s.member1.PublicKey, &s.member2.PublicKey},
|
|
channelMembers: []*ecdsa.PublicKey{&s.member1.PublicKey},
|
|
expectedActions: EncryptionKeyActions{
|
|
CommunityKeyAction: EncryptionKeyAction{
|
|
ActionType: EncryptionKeyRekey,
|
|
Members: map[string]*protobuf.CommunityMember{
|
|
s.member1Key: &protobuf.CommunityMember{
|
|
LastUpdateClock: clock,
|
|
},
|
|
s.member2Key: &protobuf.CommunityMember{
|
|
LastUpdateClock: clock,
|
|
},
|
|
},
|
|
},
|
|
ChannelKeysActions: map[string]EncryptionKeyAction{
|
|
channelID: EncryptionKeyAction{
|
|
ActionType: EncryptionKeyRekey,
|
|
Members: map[string]*protobuf.CommunityMember{
|
|
s.member1Key: &protobuf.CommunityMember{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
s.Run(tc.name, func() {
|
|
origin, err := createTestCommunity(s.identity)
|
|
s.Require().NoError(err)
|
|
|
|
_, err = origin.CreateChat(channelID, &protobuf.CommunityChat{
|
|
Members: map[string]*protobuf.CommunityMember{},
|
|
Permissions: &protobuf.CommunityPermissions{Access: protobuf.CommunityPermissions_AUTO_ACCEPT},
|
|
Identity: &protobuf.ChatIdentity{},
|
|
})
|
|
s.Require().NoError(err)
|
|
|
|
for _, permission := range tc.permissions {
|
|
_, err := origin.UpsertTokenPermission(permission)
|
|
s.Require().NoError(err)
|
|
}
|
|
for _, member := range tc.members {
|
|
_, err := origin.AddMember(member, []protobuf.CommunityMember_Roles{}, clock)
|
|
s.Require().NoError(err)
|
|
}
|
|
for _, member := range tc.channelMembers {
|
|
_, err = origin.AddMemberToChat(channelID, member, []protobuf.CommunityMember_Roles{}, protobuf.CommunityMember_CHANNEL_ROLE_POSTER)
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
// change control node to arbitrary member
|
|
modified := origin.CreateDeepCopy()
|
|
modified.setControlNode(&s.member1.PublicKey)
|
|
|
|
actions := EvaluateCommunityEncryptionKeyActions(origin, modified)
|
|
s.Require().True(reflect.DeepEqual(tc.expectedActions, *actions))
|
|
})
|
|
}
|
|
}
|