From 02b822802c12f956c037ffdb23494f1e02f035d6 Mon Sep 17 00:00:00 2001 From: Andrey Bocharnikov Date: Mon, 1 Jul 2024 22:52:57 +0400 Subject: [PATCH] chore(community)_: serialise community jsons with image URLs Fix status-im/status-desktop#15340 --- common/utils.go | 12 ++ protocol/communities/community.go | 198 +++--------------- .../community_encryption_key_action_test.go | 2 +- protocol/communities/community_test.go | 6 +- protocol/communities/manager.go | 45 +++- protocol/communities/manager_test.go | 4 +- protocol/communities/persistence_mapping.go | 15 +- protocol/communities/persistence_test.go | 4 +- protocol/communities_messenger_test.go | 11 +- protocol/messenger.go | 20 +- protocol/messenger_activity_center_test.go | 2 +- protocol/messenger_communities.go | 16 -- protocol/messenger_remove_message_test.go | 4 +- protocol/messenger_test.go | 2 +- protocol/persistence_quoted_message_test.go | 2 +- server/server_media_interface.go | 6 + services/ext/api.go | 10 +- 17 files changed, 140 insertions(+), 219 deletions(-) create mode 100644 server/server_media_interface.go diff --git a/common/utils.go b/common/utils.go index 011da7a61..9daa839ad 100644 --- a/common/utils.go +++ b/common/utils.go @@ -3,6 +3,7 @@ package common import ( "crypto/ecdsa" "errors" + "reflect" "regexp" "strings" @@ -72,3 +73,14 @@ func IsENSName(displayName string) bool { return false } + +func IsNil(i interface{}) bool { + if i == nil { + return true + } + switch reflect.TypeOf(i).Kind() { + case reflect.Ptr, reflect.Interface: + return reflect.ValueOf(i).IsNil() + } + return false +} diff --git a/protocol/communities/community.go b/protocol/communities/community.go index 70ea8ca4c..9e7dabc62 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/status-im/status-go/api/multiformat" + utils "github.com/status-im/status-go/common" "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/images" @@ -65,13 +66,14 @@ type EventsData struct { } type Community struct { - config *Config - mutex sync.Mutex - timesource common.TimeSource - encryptor DescriptionEncryptor + config *Config + mutex sync.Mutex + timesource common.TimeSource + encryptor DescriptionEncryptor + mediaServer server.MediaServerInterface } -func New(config Config, timesource common.TimeSource, encryptor DescriptionEncryptor) (*Community, error) { +func New(config Config, timesource common.TimeSource, encryptor DescriptionEncryptor, mediaServer server.MediaServerInterface) (*Community, error) { if config.MemberIdentity == nil { return nil, errors.New("no member identity") } @@ -92,7 +94,12 @@ func New(config Config, timesource common.TimeSource, encryptor DescriptionEncry config.CommunityDescription = &protobuf.CommunityDescription{} } - return &Community{config: &config, timesource: timesource, encryptor: encryptor}, nil + return &Community{ + config: &config, + timesource: timesource, + encryptor: encryptor, + mediaServer: mediaServer, + }, nil } type CommunityAdminSettings struct { @@ -257,7 +264,7 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) { return json.Marshal(communityItem) } -func (o *Community) MarshalJSONWithMediaServer(mediaServer *server.MediaServer) ([]byte, error) { +func (o *Community) MarshalJSON() ([]byte, error) { if o.config.MemberIdentity == nil { return nil, errors.New("member identity not set") } @@ -353,159 +360,6 @@ func (o *Community) MarshalJSONWithMediaServer(mediaServer *server.MediaServer) } canView := o.CanView(o.MemberIdentity(), id) - chat := CommunityChat{ - ID: id, - Name: c.Identity.DisplayName, - Emoji: c.Identity.Emoji, - Color: c.Identity.Color, - Description: c.Identity.Description, - Permissions: c.Permissions, - Members: c.Members, - CanPost: canPost, - CanView: canView, - CanPostReactions: canPostReactions, - ViewersCanPostReactions: c.ViewersCanPostReactions, - TokenGated: o.channelEncrypted(id), - CategoryID: c.CategoryId, - HideIfPermissionsNotMet: c.HideIfPermissionsNotMet, - Position: int(c.Position), - MissingEncryptionKey: !o.IsMemberInChat(o.MemberIdentity(), id) && o.IsMemberLikelyInChat(id), - } - communityItem.Chats[id] = chat - } - communityItem.TokenPermissions = o.tokenPermissions() - communityItem.PendingAndBannedMembers = o.PendingAndBannedMembers() - communityItem.Members = o.config.CommunityDescription.Members - communityItem.Permissions = o.config.CommunityDescription.Permissions - communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage - communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage - - // update token meta image to url rather than base64 image - var tokenMetadata []*protobuf.CommunityTokenMetadata - for _, m := range o.config.CommunityDescription.CommunityTokensMetadata { - copyM := proto.Clone(m).(*protobuf.CommunityTokenMetadata) - copyM.Image = mediaServer.MakeCommunityDescriptionTokenImageURL(o.IDString(), copyM.GetSymbol()) - tokenMetadata = append(tokenMetadata, copyM) - } - communityItem.CommunityTokensMetadata = tokenMetadata - - communityItem.ActiveMembersCount = o.config.CommunityDescription.ActiveMembersCount - - if o.config.CommunityDescription.Identity != nil { - communityItem.Name = o.Name() - communityItem.Color = o.config.CommunityDescription.Identity.Color - communityItem.Description = o.config.CommunityDescription.Identity.Description - for t := range o.config.CommunityDescription.Identity.Images { - if communityItem.Images == nil { - communityItem.Images = make(map[string]Image) - } - communityItem.Images[t] = Image{Uri: mediaServer.MakeCommunityImageURL(o.IDString(), t)} - } - } - - communityItem.CommunityAdminSettings = CommunityAdminSettings{ - PinMessageAllMembersEnabled: false, - } - - if o.config.CommunityDescription.AdminSettings != nil { - communityItem.CommunityAdminSettings.PinMessageAllMembersEnabled = o.config.CommunityDescription.AdminSettings.PinMessageAllMembersEnabled - } - } - return json.Marshal(communityItem) -} - -func (o *Community) MarshalJSON() ([]byte, error) { - if o.config.MemberIdentity == nil { - 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"` - JoinedAt int64 `json:"joinedAt"` - 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"` - PendingAndBannedMembers map[string]CommunityMemberState `json:"pendingAndBannedMembers"` - TokenPermissions map[string]*CommunityTokenPermission `json:"tokenPermissions"` - CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"` - ActiveMembersCount uint64 `json:"activeMembersCount"` - PubsubTopic string `json:"pubsubTopic"` - PubsubTopicKey string `json:"pubsubTopicKey"` - Shard *shard.Shard `json:"shard"` - LastOpenedAt int64 `json:"lastOpenedAt"` - Clock uint64 `json:"clock"` - }{ - ID: o.ID(), - Clock: o.Clock(), - MemberRole: o.MemberRole(o.MemberIdentity()), - IsControlNode: o.IsControlNode(), - Verified: o.config.Verified, - Chats: make(map[string]CommunityChat), - Categories: make(map[string]CommunityCategory), - Joined: o.config.Joined, - JoinedAt: o.config.JoinedAt, - Spectated: o.config.Spectated, - CanRequestAccess: o.CanRequestAccess(o.MemberIdentity()), - CanJoin: o.canJoin(), - CanManageUsers: o.CanManageUsers(o.MemberIdentity()), - CanDeleteMessageForEveryone: o.CanDeleteMessageForEveryone(o.MemberIdentity()), - RequestedToJoinAt: o.RequestedToJoinAt(), - IsMember: o.isMember(), - Muted: o.config.Muted, - MuteTill: o.config.MuteTill, - Tags: o.Tags(), - Encrypted: o.Encrypted(), - PubsubTopic: o.PubsubTopic(), - PubsubTopicKey: o.PubsubTopicKey(), - Shard: o.Shard(), - LastOpenedAt: o.config.LastOpenedAt, - } - if o.config.CommunityDescription != nil { - for id, c := range o.config.CommunityDescription.Categories { - category := CommunityCategory{ - ID: id, - Name: c.Name, - Position: int(c.Position), - } - communityItem.Encrypted = o.Encrypted() - communityItem.Categories[id] = category - } - for id, c := range o.config.CommunityDescription.Chats { - // NOTE: Here `CanPost` is only set for ChatMessage. But it can be different for reactions/pin/etc. - // Consider adding more properties to `CommunityChat` to reflect that. - canPost, err := o.CanPost(o.MemberIdentity(), id, protobuf.ApplicationMetadataMessage_CHAT_MESSAGE) - if err != nil { - return nil, err - } - canPostReactions, err := o.CanPost(o.MemberIdentity(), id, protobuf.ApplicationMetadataMessage_EMOJI_REACTION) - if err != nil { - return nil, err - } - canView := o.CanView(o.MemberIdentity(), id) - chat := CommunityChat{ ID: id, Name: c.Identity.DisplayName, @@ -535,18 +389,32 @@ func (o *Community) MarshalJSON() ([]byte, error) { communityItem.Permissions = o.config.CommunityDescription.Permissions communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage - communityItem.CommunityTokensMetadata = o.config.CommunityDescription.CommunityTokensMetadata + + // update token meta image to url rather than base64 image + var tokenMetadata []*protobuf.CommunityTokenMetadata + + if !utils.IsNil(o.mediaServer) { + for _, m := range o.config.CommunityDescription.CommunityTokensMetadata { + copyM := proto.Clone(m).(*protobuf.CommunityTokenMetadata) + copyM.Image = o.mediaServer.MakeCommunityDescriptionTokenImageURL(o.IDString(), copyM.GetSymbol()) + tokenMetadata = append(tokenMetadata, copyM) + } + communityItem.CommunityTokensMetadata = tokenMetadata + } communityItem.ActiveMembersCount = o.config.CommunityDescription.ActiveMembersCount if o.config.CommunityDescription.Identity != nil { communityItem.Name = o.Name() communityItem.Color = o.config.CommunityDescription.Identity.Color communityItem.Description = o.config.CommunityDescription.Identity.Description - for t, i := range o.config.CommunityDescription.Identity.Images { - if communityItem.Images == nil { - communityItem.Images = make(map[string]images.IdentityImage) + + if !utils.IsNil(o.mediaServer) { + for t := range o.config.CommunityDescription.Identity.Images { + if communityItem.Images == nil { + communityItem.Images = make(map[string]Image) + } + communityItem.Images[t] = Image{Uri: o.mediaServer.MakeCommunityImageURL(o.IDString(), t)} } - communityItem.Images[t] = images.IdentityImage{Name: t, Payload: i.Payload} } } diff --git a/protocol/communities/community_encryption_key_action_test.go b/protocol/communities/community_encryption_key_action_test.go index 1b8d19843..17d202a44 100644 --- a/protocol/communities/community_encryption_key_action_test.go +++ b/protocol/communities/community_encryption_key_action_test.go @@ -34,7 +34,7 @@ func createTestCommunity(identity *ecdsa.PrivateKey) (*Community, error) { MemberIdentity: identity, } - return New(config, &TimeSourceStub{}, &DescriptionEncryptorMock{}) + return New(config, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil) } func TestCommunityEncryptionKeyActionSuite(t *testing.T) { diff --git a/protocol/communities/community_test.go b/protocol/communities/community_test.go index 250025020..3581fd9ef 100644 --- a/protocol/communities/community_test.go +++ b/protocol/communities/community_test.go @@ -444,7 +444,7 @@ func (s *CommunitySuite) TestValidateRequestToJoin() { for _, tc := range testCases { s.Run(tc.name, func() { - org, err := New(tc.config, &TimeSourceStub{}, &DescriptionEncryptorMock{}) + org, err := New(tc.config, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil) s.Require().NoError(err) err = org.ValidateRequestToJoin(tc.signer, tc.request) s.Require().Equal(tc.err, err) @@ -530,7 +530,7 @@ func (s *CommunitySuite) TestCanPost() { for _, tc := range testCases { s.Run(tc.name, func() { var err error - org, err := New(tc.config, &TimeSourceStub{}, &DescriptionEncryptorMock{}) + org, err := New(tc.config, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil) s.Require().NoError(err) canPost, err := org.CanPost(tc.member, testChatID1, protobuf.ApplicationMetadataMessage_CHAT_MESSAGE) @@ -927,7 +927,7 @@ func (s *CommunitySuite) buildCommunity(owner *ecdsa.PublicKey) *Community { config.ID = owner config.CommunityDescription = s.buildCommunityDescription() - org, err := New(config, &TimeSourceStub{}, &DescriptionEncryptorMock{}) + org, err := New(config, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil) s.Require().NoError(err) return org } diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index 6386cdaaa..c49b71a29 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -38,6 +38,7 @@ import ( "github.com/status-im/status-go/protocol/requests" "github.com/status-im/status-go/protocol/transport" "github.com/status-im/status-go/rpc/network" + "github.com/status-im/status-go/server" "github.com/status-im/status-go/services/wallet/bigint" walletcommon "github.com/status-im/status-go/services/wallet/common" "github.com/status-im/status-go/services/wallet/thirdparty" @@ -107,6 +108,7 @@ type Manager struct { PermissionChecker PermissionChecker keyDistributor KeyDistributor communityLock *CommunityLock + mediaServer server.MediaServerInterface } type CommunityLock struct { @@ -380,7 +382,20 @@ type OwnerVerifier interface { SafeGetSignerPubKey(ctx context.Context, chainID uint64, communityID string) (string, error) } -func NewManager(identity *ecdsa.PrivateKey, installationID string, db *sql.DB, encryptor *encryption.Protocol, logger *zap.Logger, ensverifier *ens.Verifier, ownerVerifier OwnerVerifier, transport *transport.Transport, timesource common.TimeSource, keyDistributor KeyDistributor, opts ...ManagerOption) (*Manager, error) { +func NewManager( + identity *ecdsa.PrivateKey, + installationID string, + db *sql.DB, + encryptor *encryption.Protocol, + logger *zap.Logger, + ensverifier *ens.Verifier, + ownerVerifier OwnerVerifier, + transport *transport.Transport, + timesource common.TimeSource, + keyDistributor KeyDistributor, + mediaServer server.MediaServerInterface, + opts ...ManagerOption, +) (*Manager, error) { if identity == nil { return nil, errors.New("empty identity") } @@ -412,6 +427,7 @@ func NewManager(identity *ecdsa.PrivateKey, installationID string, db *sql.DB, e timesource: timesource, keyDistributor: keyDistributor, communityLock: NewCommunityLock(logger), + mediaServer: mediaServer, } manager.persistence = &Persistence{ @@ -440,7 +456,6 @@ func NewManager(identity *ecdsa.PrivateKey, installationID string, db *sql.DB, e } if ensverifier != nil { - sub := ensverifier.Subscribe() manager.ensSubscription = sub manager.ensVerifier = ensverifier @@ -490,6 +505,10 @@ type CommunityResponse struct { FailedToDecrypt []*CommunityPrivateDataFailedToDecrypt `json:"-"` } +func (m *Manager) SetMediaServer(mediaServer server.MediaServerInterface) { + m.mediaServer = mediaServer +} + func (m *Manager) Subscribe() chan *Subscription { subscription := make(chan *Subscription, 100) m.subscriptions = append(m.subscriptions, subscription) @@ -856,7 +875,7 @@ func (m *Manager) CreateCommunity(request *requests.CreateCommunity, publish boo if m.encryptor != nil { descriptionEncryptor = m } - community, err := New(config, m.timesource, descriptionEncryptor) + community, err := New(config, m.timesource, descriptionEncryptor, m.mediaServer) if err != nil { return nil, err } @@ -1079,7 +1098,6 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map } revealedAccount, memberHasWallet := membersAccounts[memberKey] - if !memberHasWallet { result.membersToRemove[memberKey] = struct{}{} continue @@ -1725,7 +1743,7 @@ func (m *Manager) ImportCommunity(key *ecdsa.PrivateKey, clock uint64) (*Communi if m.encryptor != nil { descriptionEncryptor = m } - community, err = New(config, m.timesource, descriptionEncryptor) + community, err = New(config, m.timesource, descriptionEncryptor, m.mediaServer) if err != nil { return nil, err } @@ -2151,7 +2169,7 @@ func (m *Manager) HandleCommunityDescriptionMessage(signer *ecdsa.PublicKey, des if m.encryptor != nil { descriptionEncryptor = m } - community, err = New(config, m.timesource, descriptionEncryptor) + community, err = New(config, m.timesource, descriptionEncryptor, m.mediaServer) if err != nil { return nil, err } @@ -3890,7 +3908,7 @@ func (m *Manager) dbRecordBundleToCommunity(r *CommunityRecordBundle) (*Communit descriptionEncryptor = m } - return recordBundleToCommunity(r, m.identity, m.installationID, m.logger, m.timesource, descriptionEncryptor, func(community *Community) error { + initializer := func(community *Community) error { _, description, err := m.preprocessDescription(community.ID(), community.config.CommunityDescription) if err != nil { return err @@ -3918,7 +3936,18 @@ func (m *Manager) dbRecordBundleToCommunity(r *CommunityRecordBundle) (*Communit } return nil - }) + } + + return recordBundleToCommunity( + r, + m.identity, + m.installationID, + m.logger, + m.timesource, + descriptionEncryptor, + m.mediaServer, + initializer, + ) } func (m *Manager) GetByID(id []byte) (*Community, error) { diff --git a/protocol/communities/manager_test.go b/protocol/communities/manager_test.go index f6e7bd02e..6b31b0054 100644 --- a/protocol/communities/manager_test.go +++ b/protocol/communities/manager_test.go @@ -60,7 +60,7 @@ func (s *ManagerSuite) buildManagers(ownerVerifier OwnerVerifier) (*Manager, *Ar logger, err := zap.NewDevelopment() s.Require().NoError(err) - m, err := NewManager(key, "", db, nil, logger, nil, ownerVerifier, nil, &TimeSourceStub{}, nil) + m, err := NewManager(key, "", db, nil, logger, nil, ownerVerifier, nil, &TimeSourceStub{}, nil, nil) s.Require().NoError(err) s.Require().NoError(m.Start()) @@ -226,7 +226,7 @@ func (s *ManagerSuite) setupManagerForTokenPermissions() (*Manager, *testCollect WithTokenManager(tm), } - m, err := NewManager(key, "", db, nil, nil, nil, nil, nil, &TimeSourceStub{}, nil, options...) + m, err := NewManager(key, "", db, nil, nil, nil, nil, nil, &TimeSourceStub{}, nil, nil, options...) s.Require().NoError(err) s.Require().NoError(m.Start()) diff --git a/protocol/communities/persistence_mapping.go b/protocol/communities/persistence_mapping.go index bc795bb64..a8964187e 100644 --- a/protocol/communities/persistence_mapping.go +++ b/protocol/communities/persistence_mapping.go @@ -8,6 +8,7 @@ import ( "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/common/shard" + "github.com/status-im/status-go/server" ) func communityToRecord(community *Community) (*CommunityRecord, error) { @@ -71,8 +72,16 @@ func recordToRequestToJoin(r *RequestToJoinRecord) *RequestToJoin { } } -func recordBundleToCommunity(r *CommunityRecordBundle, memberIdentity *ecdsa.PrivateKey, installationID string, - logger *zap.Logger, timesource common.TimeSource, encryptor DescriptionEncryptor, initializer func(*Community) error) (*Community, error) { +func recordBundleToCommunity( + r *CommunityRecordBundle, + memberIdentity *ecdsa.PrivateKey, + installationID string, + logger *zap.Logger, + timesource common.TimeSource, + encryptor DescriptionEncryptor, + mediaServer server.MediaServerInterface, + initializer func(*Community) error, +) (*Community, error) { var privateKey *ecdsa.PrivateKey var controlNode *ecdsa.PublicKey var err error @@ -139,7 +148,7 @@ func recordBundleToCommunity(r *CommunityRecordBundle, memberIdentity *ecdsa.Pri Shard: s, } - community, err := New(config, timesource, encryptor) + community, err := New(config, timesource, encryptor, mediaServer) if err != nil { return nil, err } diff --git a/protocol/communities/persistence_test.go b/protocol/communities/persistence_test.go index b24e50a52..42053ecb9 100644 --- a/protocol/communities/persistence_test.go +++ b/protocol/communities/persistence_test.go @@ -48,7 +48,7 @@ func (s *PersistenceSuite) SetupTest() { s.Require().NoError(err) s.db = &Persistence{db: db, recordBundleToCommunity: func(r *CommunityRecordBundle) (*Community, error) { - return recordBundleToCommunity(r, s.identity, "", nil, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil) + return recordBundleToCommunity(r, s.identity, "", nil, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil, nil) }} } @@ -264,7 +264,7 @@ func (s *PersistenceSuite) makeNewCommunity(identity *ecdsa.PrivateKey) *Communi ControlNode: &comPrivKey.PublicKey, ControlDevice: true, ID: &comPrivKey.PublicKey, - }, &TimeSourceStub{}, &DescriptionEncryptorMock{}) + }, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil) s.NoError(err, "New shouldn't give any error") md, err := com.MarshaledDescription() diff --git a/protocol/communities_messenger_test.go b/protocol/communities_messenger_test.go index 97f726e9b..37c4364e6 100644 --- a/protocol/communities_messenger_test.go +++ b/protocol/communities_messenger_test.go @@ -4352,15 +4352,15 @@ func (s *MessengerCommunitiesSuite) sendImageToCommunity(sender *Messenger, chat } func (s *MessengerCommunitiesSuite) TestSerializedCommunities() { - community, _ := s.createCommunity() addMediaServer := func(messenger *Messenger) { mediaServer, err := server.NewMediaServer(messenger.database, nil, nil, nil) s.Require().NoError(err) s.Require().NoError(mediaServer.Start()) - messenger.httpServer = mediaServer + messenger.SetMediaServer(mediaServer) } addMediaServer(s.owner) + community, _ := s.createCommunity() // update community description description := community.Description() identImageName := "small" @@ -4393,7 +4393,7 @@ func (s *MessengerCommunitiesSuite) TestSerializedCommunities() { s.Len(b.Description().Identity.Images, 1) s.Equal(identImagePayload, b.Description().Identity.Images[identImageName].Payload) - c, err := s.owner.SerializedCommunities() + c, err := s.owner.Communities() s.Require().NoError(err) s.Require().Len(c, 1) d, err := json.Marshal(c) @@ -4516,17 +4516,16 @@ func (s *MessengerCommunitiesSuite) fetchImage(fullURL string) ([]byte, error) { func (s *MessengerCommunitiesSuite) TestMemberMessagesHasImageLink() { // GIVEN - community, communityChat := s.createCommunity() - addMediaServer := func(messenger *Messenger) { mediaServer, err := server.NewMediaServer(messenger.database, nil, nil, nil) s.Require().NoError(err) s.Require().NoError(mediaServer.Start()) - messenger.httpServer = mediaServer + messenger.SetMediaServer(mediaServer) } addMediaServer(s.alice) addMediaServer(s.bob) addMediaServer(s.owner) + community, communityChat := s.createCommunity() request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} diff --git a/protocol/messenger.go b/protocol/messenger.go index 80a467252..dad7c706d 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -499,7 +499,20 @@ func NewMessenger( encryptor: encryptionProtocol, } - communitiesManager, err := communities.NewManager(identity, installationID, database, encryptionProtocol, logger, ensVerifier, c.communityTokensService, transp, transp, communitiesKeyDistributor, managerOptions...) + communitiesManager, err := communities.NewManager( + identity, + installationID, + database, + encryptionProtocol, + logger, + ensVerifier, + c.communityTokensService, + transp, + transp, + communitiesKeyDistributor, + c.httpServer, + managerOptions..., + ) if err != nil { return nil, err } @@ -931,6 +944,11 @@ func (m *Messenger) Start() (*MessengerResponse, error) { return response, nil } +func (m *Messenger) SetMediaServer(server *server.MediaServer) { + m.httpServer = server + m.communitiesManager.SetMediaServer(server) +} + func (m *Messenger) IdentityPublicKey() *ecdsa.PublicKey { return &m.identity.PublicKey } diff --git a/protocol/messenger_activity_center_test.go b/protocol/messenger_activity_center_test.go index 3b295558d..15a3ed302 100644 --- a/protocol/messenger_activity_center_test.go +++ b/protocol/messenger_activity_center_test.go @@ -137,7 +137,7 @@ func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() { s.Require().NoError(err) s.Require().NotNil(mediaServer) s.Require().NoError(mediaServer.Start()) - alice.httpServer = mediaServer + alice.SetMediaServer(mediaServer) // Create a community community, chat := s.createCommunity(bob) diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index dd41d41d0..be34032e0 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -4839,22 +4839,6 @@ func (m *Messenger) CreateResponseWithACNotification(communityID string, acType return response, nil } -func (m *Messenger) SerializedCommunities() ([]json.RawMessage, error) { - cs, err := m.Communities() - if err != nil { - return nil, err - } - res := make([]json.RawMessage, 0, len(cs)) - for _, c := range cs { - b, err := c.MarshalJSONWithMediaServer(m.httpServer) - if err != nil { - return nil, err - } - res = append(res, b) - } - return res, nil -} - // SendMessageToControlNode sends a message to the control node of the community. // use pointer to rawMessage to get the message ID and other updated properties. func (m *Messenger) SendMessageToControlNode(community *communities.Community, rawMessage *common.RawMessage) ([]byte, error) { diff --git a/protocol/messenger_remove_message_test.go b/protocol/messenger_remove_message_test.go index 6f2ca4246..a98270641 100644 --- a/protocol/messenger_remove_message_test.go +++ b/protocol/messenger_remove_message_test.go @@ -502,7 +502,7 @@ func (s *MessengerRemoveMessageSuite) TestDeleteMessageReplyToImage() { s.Require().NotNil(mediaServer) s.Require().NoError(mediaServer.Start()) - theirMessenger.httpServer = mediaServer + theirMessenger.SetMediaServer(mediaServer) // We reply to our own message with an image imageMessage, err := buildImageWithoutAlbumIDMessage(*theirChat) @@ -555,7 +555,7 @@ func (s *MessengerRemoveMessageSuite) TestDeleteMessageForMeReplyToImage() { s.Require().NotNil(mediaServer) s.Require().NoError(mediaServer.Start()) - theirMessenger.httpServer = mediaServer + theirMessenger.SetMediaServer(mediaServer) // We reply to our own message with an image imageMessage, err := buildImageWithoutAlbumIDMessage(*theirChat) diff --git a/protocol/messenger_test.go b/protocol/messenger_test.go index ac085fe53..aa9da1117 100644 --- a/protocol/messenger_test.go +++ b/protocol/messenger_test.go @@ -2269,7 +2269,7 @@ func (s *MessengerSuite) TestSendMessageWithPreviews() { s.Require().NoError(err) err = httpServer.SetPort(9876) s.NoError(err) - s.m.httpServer = httpServer + s.m.SetMediaServer(httpServer) chat := CreatePublicChat("test-chat", s.m.transport) err = s.m.SaveChat(chat) diff --git a/protocol/persistence_quoted_message_test.go b/protocol/persistence_quoted_message_test.go index 471910c69..5c11ec58d 100644 --- a/protocol/persistence_quoted_message_test.go +++ b/protocol/persistence_quoted_message_test.go @@ -217,7 +217,7 @@ func (s *TestMessengerPrepareMessageSuite) Test_WHEN_MessageContainsImage_THEN_P mediaServer, err := server.NewMediaServer(s.m.database, nil, nil, nil) s.Require().NoError(err) s.Require().NoError(mediaServer.Start()) - s.m.httpServer = mediaServer + s.m.SetMediaServer(mediaServer) // WHEN: message is prepared loadedMessage, err := s.m.MessageByID(message.ID) diff --git a/server/server_media_interface.go b/server/server_media_interface.go new file mode 100644 index 000000000..a62d5a165 --- /dev/null +++ b/server/server_media_interface.go @@ -0,0 +1,6 @@ +package server + +type MediaServerInterface interface { + MakeCommunityDescriptionTokenImageURL(communityID, symbol string) string + MakeCommunityImageURL(communityID, name string) string +} diff --git a/services/ext/api.go b/services/ext/api.go index 97947e686..795fde96b 100644 --- a/services/ext/api.go +++ b/services/ext/api.go @@ -4,7 +4,6 @@ import ( "context" "crypto/ecdsa" "encoding/hex" - "encoding/json" "errors" "fmt" "math/big" @@ -395,16 +394,13 @@ func (api *PublicAPI) SetInstallationName(installationID string, name string) er } // Communities returns a list of communities that are stored -// Deprecated: Use SerializedCommunities instead func (api *PublicAPI) Communities(parent context.Context) ([]*communities.Community, error) { return api.service.messenger.Communities() } -// SerializedCommunities returns a list of serialized communities. -// The key difference from the Communities function is that it uses MediaServer -// to construct image URLs for all the images rather than using base64 encoding. -func (api *PublicAPI) SerializedCommunities(parent context.Context) ([]json.RawMessage, error) { - return api.service.messenger.SerializedCommunities() +// Deprecated: renamed back to Communities. Should be removed after implementing on all platforms +func (api *PublicAPI) SerializedCommunities(parent context.Context) ([]*communities.Community, error) { + return api.Communities(parent) } // JoinedCommunities returns a list of communities that the user has joined