fix: fix permissions checker
Improve CheckPermissions function. Check separately member and admin+tokenmaster permissions.. Issue #12884
This commit is contained in:
parent
87199a8c99
commit
cc66f43713
|
@ -2636,6 +2636,7 @@ func (c *CheckPermissionsResponse) calculateSatisfied() {
|
||||||
}
|
}
|
||||||
if satisfied {
|
if satisfied {
|
||||||
c.Satisfied = true
|
c.Satisfied = true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,9 @@ import (
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
maps "golang.org/x/exp/maps"
|
||||||
|
slices "golang.org/x/exp/slices"
|
||||||
|
|
||||||
gethcommon "github.com/ethereum/go-ethereum/common"
|
gethcommon "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/status-im/status-go/protocol/ens"
|
"github.com/status-im/status-go/protocol/ens"
|
||||||
|
@ -91,13 +94,54 @@ func (p *DefaultPermissionChecker) GetOwnedERC721Tokens(walletAddresses []gethco
|
||||||
return ownedERC721Tokens, nil
|
return ownedERC721Tokens, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *DefaultPermissionChecker) accountChainsCombinationToMap(combinations []*AccountChainIDsCombination) map[gethcommon.Address][]uint64 {
|
||||||
|
result := make(map[gethcommon.Address][]uint64)
|
||||||
|
for _, combination := range combinations {
|
||||||
|
result[combination.Address] = combination.ChainIDs
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge valid combinations w/o duplicates
|
||||||
|
func (p *DefaultPermissionChecker) MergeValidCombinations(left, right []*AccountChainIDsCombination) []*AccountChainIDsCombination {
|
||||||
|
|
||||||
|
leftMap := p.accountChainsCombinationToMap(left)
|
||||||
|
rightMap := p.accountChainsCombinationToMap(right)
|
||||||
|
|
||||||
|
// merge maps, result in left map
|
||||||
|
for k, v := range rightMap {
|
||||||
|
if _, exists := leftMap[k]; !exists {
|
||||||
|
leftMap[k] = v
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
// append chains which are new
|
||||||
|
chains := leftMap[k]
|
||||||
|
for _, chainID := range v {
|
||||||
|
if !slices.Contains(chains, chainID) {
|
||||||
|
chains = append(chains, chainID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leftMap[k] = chains
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := []*AccountChainIDsCombination{}
|
||||||
|
for k, v := range leftMap {
|
||||||
|
result = append(result, &AccountChainIDsCombination{
|
||||||
|
Address: k,
|
||||||
|
ChainIDs: v,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func (p *DefaultPermissionChecker) CheckPermissionToJoin(community *Community, addresses []gethcommon.Address) (*CheckPermissionToJoinResponse, error) {
|
func (p *DefaultPermissionChecker) CheckPermissionToJoin(community *Community, addresses []gethcommon.Address) (*CheckPermissionToJoinResponse, error) {
|
||||||
becomeAdminPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_ADMIN)
|
becomeAdminPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_ADMIN)
|
||||||
becomeMemberPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_MEMBER)
|
becomeMemberPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_MEMBER)
|
||||||
becomeTokenMasterPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
|
becomeTokenMasterPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
|
||||||
|
|
||||||
permissionsToJoin := append(becomeAdminPermissions, becomeMemberPermissions...)
|
adminOrTokenMasterPermissionsToJoin := append(becomeAdminPermissions, becomeTokenMasterPermissions...)
|
||||||
permissionsToJoin = append(permissionsToJoin, becomeTokenMasterPermissions...)
|
|
||||||
|
|
||||||
allChainIDs, err := p.tokenManager.GetAllChainIDs()
|
allChainIDs, err := p.tokenManager.GetAllChainIDs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -106,7 +150,39 @@ func (p *DefaultPermissionChecker) CheckPermissionToJoin(community *Community, a
|
||||||
|
|
||||||
accountsAndChainIDs := combineAddressesAndChainIDs(addresses, allChainIDs)
|
accountsAndChainIDs := combineAddressesAndChainIDs(addresses, allChainIDs)
|
||||||
|
|
||||||
if len(becomeMemberPermissions) == 0 || len(permissionsToJoin) == 0 {
|
// Check becomeMember and (admin & token master) permissions separately.
|
||||||
|
becomeMemberPermissionsResponse, err := p.checkPermissionsOrDefault(becomeMemberPermissions, accountsAndChainIDs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(adminOrTokenMasterPermissionsToJoin) <= 0 {
|
||||||
|
return becomeMemberPermissionsResponse, nil
|
||||||
|
}
|
||||||
|
// If there are any admin or token master permissions, combine result.
|
||||||
|
|
||||||
|
adminOrTokenPermissionsResponse, err := p.CheckPermissions(adminOrTokenMasterPermissionsToJoin, accountsAndChainIDs, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mergedPermissions := make(map[string]*PermissionTokenCriteriaResult)
|
||||||
|
maps.Copy(mergedPermissions, becomeMemberPermissionsResponse.Permissions)
|
||||||
|
maps.Copy(mergedPermissions, adminOrTokenPermissionsResponse.Permissions)
|
||||||
|
|
||||||
|
mergedCombinations := p.MergeValidCombinations(becomeMemberPermissionsResponse.ValidCombinations, adminOrTokenPermissionsResponse.ValidCombinations)
|
||||||
|
|
||||||
|
combinedResponse := &CheckPermissionsResponse{
|
||||||
|
Satisfied: becomeMemberPermissionsResponse.Satisfied || adminOrTokenPermissionsResponse.Satisfied,
|
||||||
|
Permissions: mergedPermissions,
|
||||||
|
ValidCombinations: mergedCombinations,
|
||||||
|
}
|
||||||
|
|
||||||
|
return combinedResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DefaultPermissionChecker) checkPermissionsOrDefault(permissions []*CommunityTokenPermission, accountsAndChainIDs []*AccountChainIDsCombination) (*CheckPermissionsResponse, error) {
|
||||||
|
if len(permissions) == 0 {
|
||||||
// There are no permissions to join on this community at the moment,
|
// There are no permissions to join on this community at the moment,
|
||||||
// so we reveal all accounts + all chain IDs
|
// so we reveal all accounts + all chain IDs
|
||||||
response := &CheckPermissionsResponse{
|
response := &CheckPermissionsResponse{
|
||||||
|
@ -116,7 +192,7 @@ func (p *DefaultPermissionChecker) CheckPermissionToJoin(community *Community, a
|
||||||
}
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
return p.CheckPermissions(permissionsToJoin, accountsAndChainIDs, false)
|
return p.CheckPermissions(permissions, accountsAndChainIDs, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckPermissions will retrieve balances and check whether the user has
|
// CheckPermissions will retrieve balances and check whether the user has
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package communities
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
gethcommon "github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPermissionCheckerSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(PermissionCheckerSuite))
|
||||||
|
}
|
||||||
|
|
||||||
|
type PermissionCheckerSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PermissionCheckerSuite) TestMergeValidCombinations() {
|
||||||
|
|
||||||
|
permissionChecker := DefaultPermissionChecker{}
|
||||||
|
|
||||||
|
combination1 := &AccountChainIDsCombination{
|
||||||
|
Address: gethcommon.HexToAddress("0xA"),
|
||||||
|
ChainIDs: []uint64{1},
|
||||||
|
}
|
||||||
|
|
||||||
|
combination2 := &AccountChainIDsCombination{
|
||||||
|
Address: gethcommon.HexToAddress("0xB"),
|
||||||
|
ChainIDs: []uint64{5},
|
||||||
|
}
|
||||||
|
|
||||||
|
combination3 := &AccountChainIDsCombination{
|
||||||
|
Address: gethcommon.HexToAddress("0xA"),
|
||||||
|
ChainIDs: []uint64{5},
|
||||||
|
}
|
||||||
|
|
||||||
|
combination4 := &AccountChainIDsCombination{
|
||||||
|
Address: gethcommon.HexToAddress("0xB"),
|
||||||
|
ChainIDs: []uint64{5},
|
||||||
|
}
|
||||||
|
|
||||||
|
mergedCombination := permissionChecker.MergeValidCombinations([]*AccountChainIDsCombination{combination1, combination2},
|
||||||
|
[]*AccountChainIDsCombination{combination3, combination4})
|
||||||
|
|
||||||
|
s.Require().Len(mergedCombination, 2)
|
||||||
|
chains1 := mergedCombination[0].ChainIDs
|
||||||
|
chains2 := mergedCombination[1].ChainIDs
|
||||||
|
|
||||||
|
if len(chains1) == 2 {
|
||||||
|
s.Equal([]uint64{1, 5}, chains1)
|
||||||
|
s.Equal([]uint64{5}, chains2)
|
||||||
|
} else {
|
||||||
|
s.Equal([]uint64{1, 5}, chains2)
|
||||||
|
s.Equal([]uint64{5}, chains1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue