feat(communities): enable selecting addresses to pass when joining (#3656)

Improve `RequestToJoinCommunity`  to accept `Addresses` in the request. If `Addresses` is not empty, we then only pass to the owner the selected addresses. The others are ignored.
Does not validate that the addresses in the slice are part of the user's wallet. Those not part of the wallet are just ignored.
This commit is contained in:
Jonathan Rainville 2023-06-22 14:59:07 -04:00 committed by GitHub
parent 3e7d1a5f34
commit 9c596343be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 22 deletions

View File

@ -48,7 +48,8 @@ const alicePassword = "qwerty"
const bobPassword = "bob123" const bobPassword = "bob123"
const adminAddress = "0x0100000000000000000000000000000000000000" const adminAddress = "0x0100000000000000000000000000000000000000"
const aliceAddress = "0x0200000000000000000000000000000000000000" const aliceAddress1 = "0x0200000000000000000000000000000000000000"
const aliceAddress2 = "0x0210000000000000000000000000000000000000"
const bobAddress = "0x0300000000000000000000000000000000000000" const bobAddress = "0x0300000000000000000000000000000000000000"
type AccountManagerMock struct { type AccountManagerMock struct {
@ -110,9 +111,9 @@ func (s *MessengerCommunitiesSuite) SetupTest() {
s.shh = gethbridge.NewGethWakuWrapper(shh) s.shh = gethbridge.NewGethWakuWrapper(shh)
s.Require().NoError(shh.Start()) s.Require().NoError(shh.Start())
s.admin = s.newMessengerWithWallet(adminPassword, adminAddress) s.admin = s.newMessengerWithWallet(adminPassword, []string{adminAddress})
s.bob = s.newMessengerWithWallet(bobPassword, bobAddress) s.bob = s.newMessengerWithWallet(bobPassword, []string{bobAddress})
s.alice = s.newMessengerWithWallet(alicePassword, aliceAddress) s.alice = s.newMessengerWithWallet(alicePassword, []string{aliceAddress1, aliceAddress2})
_, err := s.admin.Start() _, err := s.admin.Start()
s.Require().NoError(err) s.Require().NoError(err)
_, err = s.bob.Start() _, err = s.bob.Start()
@ -204,29 +205,35 @@ func (s *MessengerCommunitiesSuite) newMessenger(accountsManager account.Manager
return s.newMessengerWithKey(s.shh, privateKey, accountsManager) return s.newMessengerWithKey(s.shh, privateKey, accountsManager)
} }
func (s *MessengerCommunitiesSuite) newMessengerWithWallet(password string, walletAddress string) *Messenger { func (s *MessengerCommunitiesSuite) newMessengerWithWallet(password string, walletAddresses []string) *Messenger {
accountsManager := &AccountManagerMock{} accountsManager := &AccountManagerMock{}
accountsManager.AccountsMap = make(map[string]string) accountsManager.AccountsMap = make(map[string]string)
accountsManager.AccountsMap[walletAddress] = types.EncodeHex(crypto.Keccak256([]byte(password))) for _, walletAddress := range walletAddresses {
accountsManager.AccountsMap[walletAddress] = types.EncodeHex(crypto.Keccak256([]byte(password)))
}
messenger := s.newMessenger(accountsManager) messenger := s.newMessenger(accountsManager)
// add wallet account with keypair // add wallet account with keypair
kp := accounts.GetProfileKeypairForTest(false, true, false) for _, walletAddress := range walletAddresses {
kp.Accounts[0].Address = types.HexToAddress(walletAddress) kp := accounts.GetProfileKeypairForTest(false, true, false)
err := messenger.settings.SaveOrUpdateKeypair(kp) kp.Accounts[0].Address = types.HexToAddress(walletAddress)
s.Require().NoError(err) err := messenger.settings.SaveOrUpdateKeypair(kp)
s.Require().NoError(err)
}
walletAccounts, err := messenger.settings.GetAccounts() walletAccounts, err := messenger.settings.GetAccounts()
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Len(walletAccounts, 1) s.Require().Len(walletAccounts, len(walletAddresses))
s.Require().Equal(walletAccounts[0].Type, accounts.AccountTypeGenerated) for i := range walletAddresses {
s.Require().Equal(walletAccounts[i].Type, accounts.AccountTypeGenerated)
}
return messenger return messenger
} }
func (s *MessengerCommunitiesSuite) requestToJoinCommunity(user *Messenger, communityID types.HexBytes, password string) (*MessengerResponse, error) { func (s *MessengerCommunitiesSuite) requestToJoinCommunity(user *Messenger, communityID types.HexBytes, password string, addresses []string) (*MessengerResponse, error) {
passwdHash := types.EncodeHex(crypto.Keccak256([]byte(password))) passwdHash := types.EncodeHex(crypto.Keccak256([]byte(password)))
request := &requests.RequestToJoinCommunity{CommunityID: communityID, Password: passwdHash} request := &requests.RequestToJoinCommunity{CommunityID: communityID, Password: passwdHash, AddressesToReveal: addresses}
return user.RequestToJoinCommunity(request) return user.RequestToJoinCommunity(request)
} }
@ -262,7 +269,7 @@ func (s *MessengerCommunitiesSuite) TestCreateCommunity_WithoutDefaultChannel()
} }
func (s *MessengerCommunitiesSuite) TestRetrieveCommunity() { func (s *MessengerCommunitiesSuite) TestRetrieveCommunity() {
alice := s.newMessengerWithWallet(alicePassword, aliceAddress) alice := s.newMessengerWithWallet(alicePassword, []string{aliceAddress1})
description := &requests.CreateCommunity{ description := &requests.CreateCommunity{
Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP,
@ -577,9 +584,9 @@ func (s *MessengerCommunitiesSuite) advertiseCommunityTo(community *communities.
s.Require().NoError(err) s.Require().NoError(err)
} }
func (s *MessengerCommunitiesSuite) joinCommunity(community *communities.Community, user *Messenger, password string) { func (s *MessengerCommunitiesSuite) joinCommunityWithAddresses(community *communities.Community, user *Messenger, password string, addresses []string) {
// Request to join the community // Request to join the community
response, err := s.requestToJoinCommunity(user, community.ID(), password) response, err := s.requestToJoinCommunity(user, community.ID(), password, addresses)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().NotNil(response) s.Require().NotNil(response)
@ -625,6 +632,10 @@ func (s *MessengerCommunitiesSuite) joinCommunity(community *communities.Communi
s.Require().NoError(err) s.Require().NoError(err)
} }
func (s *MessengerCommunitiesSuite) joinCommunity(community *communities.Community, user *Messenger, password string) {
s.joinCommunityWithAddresses(community, user, password, []string{})
}
func (s *MessengerCommunitiesSuite) TestCommunityContactCodeAdvertisement() { func (s *MessengerCommunitiesSuite) TestCommunityContactCodeAdvertisement() {
// add bob's profile keypair // add bob's profile keypair
bobProfileKp := accounts.GetProfileKeypairForTest(true, false, false) bobProfileKp := accounts.GetProfileKeypairForTest(true, false, false)
@ -3709,12 +3720,14 @@ func (s *MessengerCommunitiesSuite) TestJoinedCommunityMembersSharedAddress() {
for pubKey, member := range community.Members() { for pubKey, member := range community.Members() {
if pubKey != common.PubkeyToHex(&s.admin.identity.PublicKey) { if pubKey != common.PubkeyToHex(&s.admin.identity.PublicKey) {
s.Require().Len(member.RevealedAccounts, 1)
switch pubKey { switch pubKey {
case common.PubkeyToHex(&s.alice.identity.PublicKey): case common.PubkeyToHex(&s.alice.identity.PublicKey):
s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress) s.Require().Len(member.RevealedAccounts, 2)
s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress1)
s.Require().Equal(member.RevealedAccounts[1].Address, aliceAddress2)
case common.PubkeyToHex(&s.bob.identity.PublicKey): case common.PubkeyToHex(&s.bob.identity.PublicKey):
s.Require().Len(member.RevealedAccounts, 1)
s.Require().Equal(member.RevealedAccounts[0].Address, bobAddress) s.Require().Equal(member.RevealedAccounts[0].Address, bobAddress)
default: default:
s.Require().Fail("pubKey does not match expected keys") s.Require().Fail("pubKey does not match expected keys")
@ -3722,3 +3735,28 @@ func (s *MessengerCommunitiesSuite) TestJoinedCommunityMembersSharedAddress() {
} }
} }
} }
func (s *MessengerCommunitiesSuite) TestJoinedCommunityMembersSelectedSharedAddress() {
community := s.createCommunity()
s.advertiseCommunityTo(community, s.alice)
s.joinCommunityWithAddresses(community, s.alice, alicePassword, []string{aliceAddress2})
community, err := s.admin.GetCommunityByID(community.ID())
s.Require().NoError(err)
s.Require().Equal(2, community.MembersCount())
for pubKey, member := range community.Members() {
if pubKey != common.PubkeyToHex(&s.admin.identity.PublicKey) {
s.Require().Len(member.RevealedAccounts, 1)
switch pubKey {
case common.PubkeyToHex(&s.alice.identity.PublicKey):
s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress2)
default:
s.Require().Fail("pubKey does not match expected keys")
}
}
}
}

View File

@ -704,8 +704,22 @@ func (m *Messenger) RequestToJoinCommunity(request *requests.RequestToJoinCommun
revealedAccounts := make(map[gethcommon.Address]*protobuf.RevealedAccount) revealedAccounts := make(map[gethcommon.Address]*protobuf.RevealedAccount)
revealedAddresses := make([]gethcommon.Address, 0) revealedAddresses := make([]gethcommon.Address, 0)
containsAddress := func(addresses []string, targetAddress string) bool {
for _, address := range addresses {
if address == targetAddress {
return true
}
}
return false
}
for _, walletAccount := range walletAccounts { for _, walletAccount := range walletAccounts {
if !walletAccount.Chat && walletAccount.Type != accounts.AccountTypeWatch { if !walletAccount.Chat && walletAccount.Type != accounts.AccountTypeWatch {
if len(request.AddressesToReveal) > 0 && !containsAddress(request.AddressesToReveal, walletAccount.Address.Hex()) {
continue
}
verifiedAccount, err := m.accountsManager.GetVerifiedWalletAccount(m.settings, walletAccount.Address.Hex(), request.Password) verifiedAccount, err := m.accountsManager.GetVerifiedWalletAccount(m.settings, walletAccount.Address.Hex(), request.Password)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -7,17 +7,22 @@ import (
) )
var ErrRequestToJoinCommunityInvalidCommunityID = errors.New("request-to-join-community: invalid community id") var ErrRequestToJoinCommunityInvalidCommunityID = errors.New("request-to-join-community: invalid community id")
var ErrRequestToJoinCommunityMissingPassword = errors.New("request-to-join-community: password is necessary when sending a list of addresses")
type RequestToJoinCommunity struct { type RequestToJoinCommunity struct {
CommunityID types.HexBytes `json:"communityId"` CommunityID types.HexBytes `json:"communityId"`
ENSName string `json:"ensName"` ENSName string `json:"ensName"`
Password string `json:"password"` Password string `json:"password"`
AddressesToReveal []string `json:"addressesToReveal"`
} }
func (j *RequestToJoinCommunity) Validate() error { func (j *RequestToJoinCommunity) Validate() error {
if len(j.CommunityID) == 0 { if len(j.CommunityID) == 0 {
return ErrRequestToJoinCommunityInvalidCommunityID return ErrRequestToJoinCommunityInvalidCommunityID
} }
if len(j.AddressesToReveal) > 0 && j.Password == "" {
return ErrRequestToJoinCommunityMissingPassword
}
return nil return nil
} }