Community encryption should automatically be enabled/disabled depending on community permissions (closed/open)
This commit is contained in:
parent
44ded4dd64
commit
57b2432290
|
@ -969,8 +969,8 @@ func (o *Community) Encrypted() bool {
|
|||
return o.config.CommunityDescription.Encrypted
|
||||
}
|
||||
|
||||
func (o *Community) Encrypt() {
|
||||
o.config.CommunityDescription.Encrypted = true
|
||||
func (o *Community) SetEncrypted(encrypted bool) {
|
||||
o.config.CommunityDescription.Encrypted = encrypted
|
||||
}
|
||||
|
||||
func (o *Community) Joined() bool {
|
||||
|
@ -1468,6 +1468,7 @@ func (o *Community) AddTokenPermission(permission *protobuf.CommunityTokenPermis
|
|||
}
|
||||
|
||||
o.config.CommunityDescription.TokenPermissions[permission.Id] = permission
|
||||
|
||||
o.increaseClock()
|
||||
changes := o.emptyCommunityChanges()
|
||||
|
||||
|
|
|
@ -3334,3 +3334,17 @@ func (m *Manager) SetCommunityActiveMembersCount(communityID string, activeMembe
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateCommunity takes a Community persists it and republishes it.
|
||||
// The clock is incremented meaning even a no change update will be republished by the admin, and parsed by the member.
|
||||
func (m *Manager) UpdateCommunity(c *Community) error {
|
||||
c.increaseClock()
|
||||
|
||||
err := m.persistence.SaveCommunity(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.publish(&Subscription{Community: c})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"go.uber.org/zap"
|
||||
|
@ -28,7 +27,6 @@ import (
|
|||
"github.com/status-im/status-go/protocol/common"
|
||||
"github.com/status-im/status-go/protocol/communities"
|
||||
"github.com/status-im/status-go/protocol/discord"
|
||||
"github.com/status-im/status-go/protocol/encryption"
|
||||
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/requests"
|
||||
|
@ -640,7 +638,6 @@ func (s *MessengerCommunitiesSuite) TestPostToCommunityChat() {
|
|||
Name: "status",
|
||||
Color: "#ffffff",
|
||||
Description: "status community description",
|
||||
Encrypted: true,
|
||||
}
|
||||
|
||||
// Create an community chat
|
||||
|
@ -2578,7 +2575,6 @@ func (s *MessengerCommunitiesSuite) TestSyncCommunity() {
|
|||
createCommunityReq := &requests.CreateCommunity{
|
||||
Membership: protobuf.CommunityPermissions_ON_REQUEST,
|
||||
Name: "new community",
|
||||
Encrypted: true,
|
||||
Color: "#000000",
|
||||
Description: "new community description",
|
||||
}
|
||||
|
@ -2593,15 +2589,6 @@ func (s *MessengerCommunitiesSuite) TestSyncCommunity() {
|
|||
}
|
||||
s.Require().NotNil(newCommunity)
|
||||
|
||||
// Check HR keys are created
|
||||
encodedKeys, err := s.alice.encryptor.GetAllHREncodedKeys(newCommunity.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(encodedKeys)
|
||||
|
||||
keys := &encryption.HRKeys{}
|
||||
s.Require().NoError(proto.Unmarshal(encodedKeys, keys))
|
||||
s.Require().Len(keys.Keys, 1)
|
||||
|
||||
// Check that Alice has 2 communities
|
||||
cs, err := s.alice.communitiesManager.All()
|
||||
s.Require().NoError(err, "communitiesManager.All")
|
||||
|
@ -2629,15 +2616,6 @@ func (s *MessengerCommunitiesSuite) TestSyncCommunity() {
|
|||
s.Require().NoError(err)
|
||||
s.Len(tcs, 2, "There must be 2 communities")
|
||||
|
||||
// Check HR keys are synced
|
||||
encodedKeys, err = alicesOtherDevice.encryptor.GetAllHREncodedKeys(newCommunity.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(encodedKeys)
|
||||
|
||||
keys = &encryption.HRKeys{}
|
||||
s.Require().NoError(proto.Unmarshal(encodedKeys, keys))
|
||||
s.Require().Len(keys.Keys, 1)
|
||||
|
||||
s.logger.Debug("", zap.Any("tcs", tcs))
|
||||
|
||||
// Get the new community from their db
|
||||
|
|
|
@ -623,7 +623,7 @@ func (s *encryptor) getNextHashRatchetKeyID(groupID []byte) (uint32, error) {
|
|||
return latestKeyID + 1, nil
|
||||
}
|
||||
|
||||
// Generates and stores a hash ratchet key given a group ID
|
||||
// GenerateHashRatchetKey Generates and stores a hash ratchet key given a group ID
|
||||
func (s *encryptor) GenerateHashRatchetKey(groupID []byte) (uint32, error) {
|
||||
|
||||
// Randomly generate a hash ratchet key
|
||||
|
|
|
@ -790,7 +790,7 @@ func (s *sqlitePersistence) GetHashRatchetKeyByID(groupID []byte, keyID uint32,
|
|||
}
|
||||
}
|
||||
|
||||
// GetCurrentKeyIDForGroup retrieves a key ID for given group ID
|
||||
// GetCurrentKeyForGroup retrieves a key ID for given group ID
|
||||
// (with an assumption that key ids are shared in the group, and
|
||||
// at any given time there is a single key used)
|
||||
func (s *sqlitePersistence) GetCurrentKeyForGroup(groupID []byte) (uint32, error) {
|
||||
|
@ -845,7 +845,7 @@ func (s *sqlitePersistence) GetKeyIDsForGroup(groupID []byte) ([]uint32, error)
|
|||
return keyIDs, nil
|
||||
}
|
||||
|
||||
// SaveHashRachetKeyHash saves a hash ratchet key cache data
|
||||
// SaveHashRatchetKeyHash saves a hash ratchet key cache data
|
||||
func (s *sqlitePersistence) SaveHashRatchetKeyHash(
|
||||
groupID []byte,
|
||||
keyID uint32,
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"crypto/ecdsa"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
_errors "errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
@ -1238,15 +1239,6 @@ func (m *Messenger) CreateCommunity(request *requests.CreateCommunity, createDef
|
|||
response.AddChat(chatResponse.Chats()[0])
|
||||
}
|
||||
|
||||
if request.Encrypted {
|
||||
// Init hash ratchet for community
|
||||
_, err = m.encryptor.GenerateHashRatchetKey(community.ID())
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
response.AddCommunity(community)
|
||||
response.AddCommunitySettings(&communitySettings)
|
||||
err = m.syncCommunity(context.Background(), community, m.dispatchMessage)
|
||||
|
@ -1271,8 +1263,16 @@ func (m *Messenger) CreateCommunityTokenPermission(request *requests.CreateCommu
|
|||
return nil, err
|
||||
}
|
||||
|
||||
response := &MessengerResponse{}
|
||||
response.AddCommunity(community)
|
||||
response, err := m.UpdateCommunityEncryption(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if response == nil {
|
||||
response = &MessengerResponse{}
|
||||
response.AddCommunity(community)
|
||||
}
|
||||
|
||||
response.CommunityChanges = []*communities.CommunityChanges{changes}
|
||||
|
||||
return response, nil
|
||||
|
@ -1288,8 +1288,16 @@ func (m *Messenger) EditCommunityTokenPermission(request *requests.EditCommunity
|
|||
return nil, err
|
||||
}
|
||||
|
||||
response := &MessengerResponse{}
|
||||
response.AddCommunity(community)
|
||||
response, err := m.UpdateCommunityEncryption(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if response == nil {
|
||||
response = &MessengerResponse{}
|
||||
response.AddCommunity(community)
|
||||
}
|
||||
|
||||
response.CommunityChanges = []*communities.CommunityChanges{changes}
|
||||
|
||||
return response, nil
|
||||
|
@ -1305,8 +1313,16 @@ func (m *Messenger) DeleteCommunityTokenPermission(request *requests.DeleteCommu
|
|||
return nil, err
|
||||
}
|
||||
|
||||
response := &MessengerResponse{}
|
||||
response.AddCommunity(community)
|
||||
response, err := m.UpdateCommunityEncryption(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if response == nil {
|
||||
response = &MessengerResponse{}
|
||||
response.AddCommunity(community)
|
||||
}
|
||||
|
||||
response.CommunityChanges = []*communities.CommunityChanges{changes}
|
||||
return response, nil
|
||||
}
|
||||
|
@ -2624,19 +2640,6 @@ func (m *Messenger) RequestImportDiscordCommunity(request *requests.ImportDiscor
|
|||
return
|
||||
}
|
||||
|
||||
if createCommunityRequest.Encrypted {
|
||||
// Init hash ratchet for community
|
||||
_, err = m.encryptor.GenerateHashRatchetKey(discordCommunity.ID())
|
||||
|
||||
if err != nil {
|
||||
m.cleanUpImport(discordCommunity.IDString())
|
||||
importProgress.AddTaskError(discord.CommunityCreationTask, discord.Error(err.Error()))
|
||||
importProgress.StopTask(discord.CommunityCreationTask)
|
||||
progressUpdates <- importProgress
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
communityID := discordCommunity.IDString()
|
||||
|
||||
// marking import as not cancelled
|
||||
|
@ -3536,3 +3539,52 @@ func (m *Messenger) AddCommunityToken(token *communities.CommunityToken) (*commu
|
|||
func (m *Messenger) UpdateCommunityTokenState(contractAddress string, deployState communities.DeployState) error {
|
||||
return m.communitiesManager.UpdateCommunityTokenState(contractAddress, deployState)
|
||||
}
|
||||
|
||||
// UpdateCommunityEncryption takes a community and encrypts / decrypts the community
|
||||
// based on TokenPermission. Community is republished along with any keys if needed.
|
||||
//
|
||||
// Note: This function cannot decrypt previously encrypted messages, and it cannot encrypt previous unencrypted messages.
|
||||
// This functionality introduces some race conditions:
|
||||
// - community description is processed by members before the receiving the key exchange messages
|
||||
// - members maybe sending encrypted messages after the community description is updated and a new member joins
|
||||
func (m *Messenger) UpdateCommunityEncryption(community *communities.Community) (*MessengerResponse, error) {
|
||||
if community == nil {
|
||||
return nil, errors.New("community is nil")
|
||||
}
|
||||
|
||||
becomeMemberPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_MEMBER)
|
||||
isEncrypted := len(becomeMemberPermissions) > 0
|
||||
|
||||
// Check isEncrypted is different to Community's value
|
||||
// If not different return
|
||||
if community.Encrypted() == isEncrypted {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if isEncrypted {
|
||||
// 🪄 The magic that encrypts a community
|
||||
_, err := m.encryptor.GenerateHashRatchetKey(community.ID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = m.SendKeyExchangeMessage(community.ID(), community.GetMemberPubkeys(), common.KeyExMsgReuse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 🧙 There is no magic that decrypts a community, we just need to tell everyone to not use encryption
|
||||
|
||||
// Republish the community.
|
||||
community.SetEncrypted(isEncrypted)
|
||||
err := m.communitiesManager.UpdateCommunity(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := &MessengerResponse{}
|
||||
response.AddCommunity(community)
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
|
|
@ -42,7 +42,6 @@ type CreateCommunity struct {
|
|||
Banner images.CroppedImage `json:"banner"`
|
||||
HistoryArchiveSupportEnabled bool `json:"historyArchiveSupportEnabled,omitempty"`
|
||||
PinMessageAllMembersEnabled bool `json:"pinMessageAllMembersEnabled,omitempty"`
|
||||
Encrypted bool `json:"encrypted,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -129,7 +128,7 @@ func (c *CreateCommunity) ToCommunityDescription() (*protobuf.CommunityDescripti
|
|||
},
|
||||
IntroMessage: c.IntroMessage,
|
||||
OutroMessage: c.OutroMessage,
|
||||
Encrypted: c.Encrypted,
|
||||
Encrypted: false,
|
||||
Tags: c.Tags,
|
||||
}
|
||||
return description, nil
|
||||
|
|
Loading…
Reference in New Issue