chore(community)_: serialise community jsons with image URLs

Fix status-im/status-desktop#15340
This commit is contained in:
Andrey Bocharnikov 2024-07-01 22:52:57 +04:00
parent 798877788c
commit 02b822802c
17 changed files with 140 additions and 219 deletions

View File

@ -3,6 +3,7 @@ package common
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"errors" "errors"
"reflect"
"regexp" "regexp"
"strings" "strings"
@ -72,3 +73,14 @@ func IsENSName(displayName string) bool {
return false 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
}

View File

@ -18,6 +18,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/api/multiformat" "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/crypto"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/images" "github.com/status-im/status-go/images"
@ -65,13 +66,14 @@ type EventsData struct {
} }
type Community struct { type Community struct {
config *Config config *Config
mutex sync.Mutex mutex sync.Mutex
timesource common.TimeSource timesource common.TimeSource
encryptor DescriptionEncryptor 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 { if config.MemberIdentity == nil {
return nil, errors.New("no member identity") return nil, errors.New("no member identity")
} }
@ -92,7 +94,12 @@ func New(config Config, timesource common.TimeSource, encryptor DescriptionEncry
config.CommunityDescription = &protobuf.CommunityDescription{} 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 { type CommunityAdminSettings struct {
@ -257,7 +264,7 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
return json.Marshal(communityItem) return json.Marshal(communityItem)
} }
func (o *Community) MarshalJSONWithMediaServer(mediaServer *server.MediaServer) ([]byte, error) { func (o *Community) MarshalJSON() ([]byte, error) {
if o.config.MemberIdentity == nil { if o.config.MemberIdentity == nil {
return nil, errors.New("member identity not set") 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) 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{ chat := CommunityChat{
ID: id, ID: id,
Name: c.Identity.DisplayName, Name: c.Identity.DisplayName,
@ -535,18 +389,32 @@ func (o *Community) MarshalJSON() ([]byte, error) {
communityItem.Permissions = o.config.CommunityDescription.Permissions communityItem.Permissions = o.config.CommunityDescription.Permissions
communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage
communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage 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 communityItem.ActiveMembersCount = o.config.CommunityDescription.ActiveMembersCount
if o.config.CommunityDescription.Identity != nil { if o.config.CommunityDescription.Identity != nil {
communityItem.Name = o.Name() communityItem.Name = o.Name()
communityItem.Color = o.config.CommunityDescription.Identity.Color communityItem.Color = o.config.CommunityDescription.Identity.Color
communityItem.Description = o.config.CommunityDescription.Identity.Description communityItem.Description = o.config.CommunityDescription.Identity.Description
for t, i := range o.config.CommunityDescription.Identity.Images {
if communityItem.Images == nil { if !utils.IsNil(o.mediaServer) {
communityItem.Images = make(map[string]images.IdentityImage) 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}
} }
} }

View File

@ -34,7 +34,7 @@ func createTestCommunity(identity *ecdsa.PrivateKey) (*Community, error) {
MemberIdentity: identity, MemberIdentity: identity,
} }
return New(config, &TimeSourceStub{}, &DescriptionEncryptorMock{}) return New(config, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil)
} }
func TestCommunityEncryptionKeyActionSuite(t *testing.T) { func TestCommunityEncryptionKeyActionSuite(t *testing.T) {

View File

@ -444,7 +444,7 @@ func (s *CommunitySuite) TestValidateRequestToJoin() {
for _, tc := range testCases { for _, tc := range testCases {
s.Run(tc.name, func() { s.Run(tc.name, func() {
org, err := New(tc.config, &TimeSourceStub{}, &DescriptionEncryptorMock{}) org, err := New(tc.config, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil)
s.Require().NoError(err) s.Require().NoError(err)
err = org.ValidateRequestToJoin(tc.signer, tc.request) err = org.ValidateRequestToJoin(tc.signer, tc.request)
s.Require().Equal(tc.err, err) s.Require().Equal(tc.err, err)
@ -530,7 +530,7 @@ func (s *CommunitySuite) TestCanPost() {
for _, tc := range testCases { for _, tc := range testCases {
s.Run(tc.name, func() { s.Run(tc.name, func() {
var err error var err error
org, err := New(tc.config, &TimeSourceStub{}, &DescriptionEncryptorMock{}) org, err := New(tc.config, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil)
s.Require().NoError(err) s.Require().NoError(err)
canPost, err := org.CanPost(tc.member, testChatID1, protobuf.ApplicationMetadataMessage_CHAT_MESSAGE) 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.ID = owner
config.CommunityDescription = s.buildCommunityDescription() config.CommunityDescription = s.buildCommunityDescription()
org, err := New(config, &TimeSourceStub{}, &DescriptionEncryptorMock{}) org, err := New(config, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil)
s.Require().NoError(err) s.Require().NoError(err)
return org return org
} }

View File

@ -38,6 +38,7 @@ import (
"github.com/status-im/status-go/protocol/requests" "github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/protocol/transport" "github.com/status-im/status-go/protocol/transport"
"github.com/status-im/status-go/rpc/network" "github.com/status-im/status-go/rpc/network"
"github.com/status-im/status-go/server"
"github.com/status-im/status-go/services/wallet/bigint" "github.com/status-im/status-go/services/wallet/bigint"
walletcommon "github.com/status-im/status-go/services/wallet/common" walletcommon "github.com/status-im/status-go/services/wallet/common"
"github.com/status-im/status-go/services/wallet/thirdparty" "github.com/status-im/status-go/services/wallet/thirdparty"
@ -107,6 +108,7 @@ type Manager struct {
PermissionChecker PermissionChecker PermissionChecker PermissionChecker
keyDistributor KeyDistributor keyDistributor KeyDistributor
communityLock *CommunityLock communityLock *CommunityLock
mediaServer server.MediaServerInterface
} }
type CommunityLock struct { type CommunityLock struct {
@ -380,7 +382,20 @@ type OwnerVerifier interface {
SafeGetSignerPubKey(ctx context.Context, chainID uint64, communityID string) (string, error) 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 { if identity == nil {
return nil, errors.New("empty identity") return nil, errors.New("empty identity")
} }
@ -412,6 +427,7 @@ func NewManager(identity *ecdsa.PrivateKey, installationID string, db *sql.DB, e
timesource: timesource, timesource: timesource,
keyDistributor: keyDistributor, keyDistributor: keyDistributor,
communityLock: NewCommunityLock(logger), communityLock: NewCommunityLock(logger),
mediaServer: mediaServer,
} }
manager.persistence = &Persistence{ manager.persistence = &Persistence{
@ -440,7 +456,6 @@ func NewManager(identity *ecdsa.PrivateKey, installationID string, db *sql.DB, e
} }
if ensverifier != nil { if ensverifier != nil {
sub := ensverifier.Subscribe() sub := ensverifier.Subscribe()
manager.ensSubscription = sub manager.ensSubscription = sub
manager.ensVerifier = ensverifier manager.ensVerifier = ensverifier
@ -490,6 +505,10 @@ type CommunityResponse struct {
FailedToDecrypt []*CommunityPrivateDataFailedToDecrypt `json:"-"` FailedToDecrypt []*CommunityPrivateDataFailedToDecrypt `json:"-"`
} }
func (m *Manager) SetMediaServer(mediaServer server.MediaServerInterface) {
m.mediaServer = mediaServer
}
func (m *Manager) Subscribe() chan *Subscription { func (m *Manager) Subscribe() chan *Subscription {
subscription := make(chan *Subscription, 100) subscription := make(chan *Subscription, 100)
m.subscriptions = append(m.subscriptions, subscription) m.subscriptions = append(m.subscriptions, subscription)
@ -856,7 +875,7 @@ func (m *Manager) CreateCommunity(request *requests.CreateCommunity, publish boo
if m.encryptor != nil { if m.encryptor != nil {
descriptionEncryptor = m descriptionEncryptor = m
} }
community, err := New(config, m.timesource, descriptionEncryptor) community, err := New(config, m.timesource, descriptionEncryptor, m.mediaServer)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1079,7 +1098,6 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
} }
revealedAccount, memberHasWallet := membersAccounts[memberKey] revealedAccount, memberHasWallet := membersAccounts[memberKey]
if !memberHasWallet { if !memberHasWallet {
result.membersToRemove[memberKey] = struct{}{} result.membersToRemove[memberKey] = struct{}{}
continue continue
@ -1725,7 +1743,7 @@ func (m *Manager) ImportCommunity(key *ecdsa.PrivateKey, clock uint64) (*Communi
if m.encryptor != nil { if m.encryptor != nil {
descriptionEncryptor = m descriptionEncryptor = m
} }
community, err = New(config, m.timesource, descriptionEncryptor) community, err = New(config, m.timesource, descriptionEncryptor, m.mediaServer)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -2151,7 +2169,7 @@ func (m *Manager) HandleCommunityDescriptionMessage(signer *ecdsa.PublicKey, des
if m.encryptor != nil { if m.encryptor != nil {
descriptionEncryptor = m descriptionEncryptor = m
} }
community, err = New(config, m.timesource, descriptionEncryptor) community, err = New(config, m.timesource, descriptionEncryptor, m.mediaServer)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3890,7 +3908,7 @@ func (m *Manager) dbRecordBundleToCommunity(r *CommunityRecordBundle) (*Communit
descriptionEncryptor = m 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) _, description, err := m.preprocessDescription(community.ID(), community.config.CommunityDescription)
if err != nil { if err != nil {
return err return err
@ -3918,7 +3936,18 @@ func (m *Manager) dbRecordBundleToCommunity(r *CommunityRecordBundle) (*Communit
} }
return nil 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) { func (m *Manager) GetByID(id []byte) (*Community, error) {

View File

@ -60,7 +60,7 @@ func (s *ManagerSuite) buildManagers(ownerVerifier OwnerVerifier) (*Manager, *Ar
logger, err := zap.NewDevelopment() logger, err := zap.NewDevelopment()
s.Require().NoError(err) 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(err)
s.Require().NoError(m.Start()) s.Require().NoError(m.Start())
@ -226,7 +226,7 @@ func (s *ManagerSuite) setupManagerForTokenPermissions() (*Manager, *testCollect
WithTokenManager(tm), 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(err)
s.Require().NoError(m.Start()) s.Require().NoError(m.Start())

View File

@ -8,6 +8,7 @@ import (
"github.com/status-im/status-go/eth-node/crypto" "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"
"github.com/status-im/status-go/protocol/common/shard" "github.com/status-im/status-go/protocol/common/shard"
"github.com/status-im/status-go/server"
) )
func communityToRecord(community *Community) (*CommunityRecord, error) { func communityToRecord(community *Community) (*CommunityRecord, error) {
@ -71,8 +72,16 @@ func recordToRequestToJoin(r *RequestToJoinRecord) *RequestToJoin {
} }
} }
func recordBundleToCommunity(r *CommunityRecordBundle, memberIdentity *ecdsa.PrivateKey, installationID string, func recordBundleToCommunity(
logger *zap.Logger, timesource common.TimeSource, encryptor DescriptionEncryptor, initializer func(*Community) error) (*Community, error) { 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 privateKey *ecdsa.PrivateKey
var controlNode *ecdsa.PublicKey var controlNode *ecdsa.PublicKey
var err error var err error
@ -139,7 +148,7 @@ func recordBundleToCommunity(r *CommunityRecordBundle, memberIdentity *ecdsa.Pri
Shard: s, Shard: s,
} }
community, err := New(config, timesource, encryptor) community, err := New(config, timesource, encryptor, mediaServer)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -48,7 +48,7 @@ func (s *PersistenceSuite) SetupTest() {
s.Require().NoError(err) s.Require().NoError(err)
s.db = &Persistence{db: db, recordBundleToCommunity: func(r *CommunityRecordBundle) (*Community, error) { 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, ControlNode: &comPrivKey.PublicKey,
ControlDevice: true, ControlDevice: true,
ID: &comPrivKey.PublicKey, ID: &comPrivKey.PublicKey,
}, &TimeSourceStub{}, &DescriptionEncryptorMock{}) }, &TimeSourceStub{}, &DescriptionEncryptorMock{}, nil)
s.NoError(err, "New shouldn't give any error") s.NoError(err, "New shouldn't give any error")
md, err := com.MarshaledDescription() md, err := com.MarshaledDescription()

View File

@ -4352,15 +4352,15 @@ func (s *MessengerCommunitiesSuite) sendImageToCommunity(sender *Messenger, chat
} }
func (s *MessengerCommunitiesSuite) TestSerializedCommunities() { func (s *MessengerCommunitiesSuite) TestSerializedCommunities() {
community, _ := s.createCommunity()
addMediaServer := func(messenger *Messenger) { addMediaServer := func(messenger *Messenger) {
mediaServer, err := server.NewMediaServer(messenger.database, nil, nil, nil) mediaServer, err := server.NewMediaServer(messenger.database, nil, nil, nil)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().NoError(mediaServer.Start()) s.Require().NoError(mediaServer.Start())
messenger.httpServer = mediaServer messenger.SetMediaServer(mediaServer)
} }
addMediaServer(s.owner) addMediaServer(s.owner)
community, _ := s.createCommunity()
// update community description // update community description
description := community.Description() description := community.Description()
identImageName := "small" identImageName := "small"
@ -4393,7 +4393,7 @@ func (s *MessengerCommunitiesSuite) TestSerializedCommunities() {
s.Len(b.Description().Identity.Images, 1) s.Len(b.Description().Identity.Images, 1)
s.Equal(identImagePayload, b.Description().Identity.Images[identImageName].Payload) 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().NoError(err)
s.Require().Len(c, 1) s.Require().Len(c, 1)
d, err := json.Marshal(c) d, err := json.Marshal(c)
@ -4516,17 +4516,16 @@ func (s *MessengerCommunitiesSuite) fetchImage(fullURL string) ([]byte, error) {
func (s *MessengerCommunitiesSuite) TestMemberMessagesHasImageLink() { func (s *MessengerCommunitiesSuite) TestMemberMessagesHasImageLink() {
// GIVEN // GIVEN
community, communityChat := s.createCommunity()
addMediaServer := func(messenger *Messenger) { addMediaServer := func(messenger *Messenger) {
mediaServer, err := server.NewMediaServer(messenger.database, nil, nil, nil) mediaServer, err := server.NewMediaServer(messenger.database, nil, nil, nil)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().NoError(mediaServer.Start()) s.Require().NoError(mediaServer.Start())
messenger.httpServer = mediaServer messenger.SetMediaServer(mediaServer)
} }
addMediaServer(s.alice) addMediaServer(s.alice)
addMediaServer(s.bob) addMediaServer(s.bob)
addMediaServer(s.owner) addMediaServer(s.owner)
community, communityChat := s.createCommunity()
request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} request := &requests.RequestToJoinCommunity{CommunityID: community.ID()}

View File

@ -499,7 +499,20 @@ func NewMessenger(
encryptor: encryptionProtocol, 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 { if err != nil {
return nil, err return nil, err
} }
@ -931,6 +944,11 @@ func (m *Messenger) Start() (*MessengerResponse, error) {
return response, nil return response, nil
} }
func (m *Messenger) SetMediaServer(server *server.MediaServer) {
m.httpServer = server
m.communitiesManager.SetMediaServer(server)
}
func (m *Messenger) IdentityPublicKey() *ecdsa.PublicKey { func (m *Messenger) IdentityPublicKey() *ecdsa.PublicKey {
return &m.identity.PublicKey return &m.identity.PublicKey
} }

View File

@ -137,7 +137,7 @@ func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() {
s.Require().NoError(err) s.Require().NoError(err)
s.Require().NotNil(mediaServer) s.Require().NotNil(mediaServer)
s.Require().NoError(mediaServer.Start()) s.Require().NoError(mediaServer.Start())
alice.httpServer = mediaServer alice.SetMediaServer(mediaServer)
// Create a community // Create a community
community, chat := s.createCommunity(bob) community, chat := s.createCommunity(bob)

View File

@ -4839,22 +4839,6 @@ func (m *Messenger) CreateResponseWithACNotification(communityID string, acType
return response, nil 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. // SendMessageToControlNode sends a message to the control node of the community.
// use pointer to rawMessage to get the message ID and other updated properties. // 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) { func (m *Messenger) SendMessageToControlNode(community *communities.Community, rawMessage *common.RawMessage) ([]byte, error) {

View File

@ -502,7 +502,7 @@ func (s *MessengerRemoveMessageSuite) TestDeleteMessageReplyToImage() {
s.Require().NotNil(mediaServer) s.Require().NotNil(mediaServer)
s.Require().NoError(mediaServer.Start()) s.Require().NoError(mediaServer.Start())
theirMessenger.httpServer = mediaServer theirMessenger.SetMediaServer(mediaServer)
// We reply to our own message with an image // We reply to our own message with an image
imageMessage, err := buildImageWithoutAlbumIDMessage(*theirChat) imageMessage, err := buildImageWithoutAlbumIDMessage(*theirChat)
@ -555,7 +555,7 @@ func (s *MessengerRemoveMessageSuite) TestDeleteMessageForMeReplyToImage() {
s.Require().NotNil(mediaServer) s.Require().NotNil(mediaServer)
s.Require().NoError(mediaServer.Start()) s.Require().NoError(mediaServer.Start())
theirMessenger.httpServer = mediaServer theirMessenger.SetMediaServer(mediaServer)
// We reply to our own message with an image // We reply to our own message with an image
imageMessage, err := buildImageWithoutAlbumIDMessage(*theirChat) imageMessage, err := buildImageWithoutAlbumIDMessage(*theirChat)

View File

@ -2269,7 +2269,7 @@ func (s *MessengerSuite) TestSendMessageWithPreviews() {
s.Require().NoError(err) s.Require().NoError(err)
err = httpServer.SetPort(9876) err = httpServer.SetPort(9876)
s.NoError(err) s.NoError(err)
s.m.httpServer = httpServer s.m.SetMediaServer(httpServer)
chat := CreatePublicChat("test-chat", s.m.transport) chat := CreatePublicChat("test-chat", s.m.transport)
err = s.m.SaveChat(chat) err = s.m.SaveChat(chat)

View File

@ -217,7 +217,7 @@ func (s *TestMessengerPrepareMessageSuite) Test_WHEN_MessageContainsImage_THEN_P
mediaServer, err := server.NewMediaServer(s.m.database, nil, nil, nil) mediaServer, err := server.NewMediaServer(s.m.database, nil, nil, nil)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().NoError(mediaServer.Start()) s.Require().NoError(mediaServer.Start())
s.m.httpServer = mediaServer s.m.SetMediaServer(mediaServer)
// WHEN: message is prepared // WHEN: message is prepared
loadedMessage, err := s.m.MessageByID(message.ID) loadedMessage, err := s.m.MessageByID(message.ID)

View File

@ -0,0 +1,6 @@
package server
type MediaServerInterface interface {
MakeCommunityDescriptionTokenImageURL(communityID, symbol string) string
MakeCommunityImageURL(communityID, name string) string
}

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"crypto/ecdsa" "crypto/ecdsa"
"encoding/hex" "encoding/hex"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
@ -395,16 +394,13 @@ func (api *PublicAPI) SetInstallationName(installationID string, name string) er
} }
// Communities returns a list of communities that are stored // Communities returns a list of communities that are stored
// Deprecated: Use SerializedCommunities instead
func (api *PublicAPI) Communities(parent context.Context) ([]*communities.Community, error) { func (api *PublicAPI) Communities(parent context.Context) ([]*communities.Community, error) {
return api.service.messenger.Communities() return api.service.messenger.Communities()
} }
// SerializedCommunities returns a list of serialized communities. // Deprecated: renamed back to Communities. Should be removed after implementing on all platforms
// The key difference from the Communities function is that it uses MediaServer func (api *PublicAPI) SerializedCommunities(parent context.Context) ([]*communities.Community, error) {
// to construct image URLs for all the images rather than using base64 encoding. return api.Communities(parent)
func (api *PublicAPI) SerializedCommunities(parent context.Context) ([]json.RawMessage, error) {
return api.service.messenger.SerializedCommunities()
} }
// JoinedCommunities returns a list of communities that the user has joined // JoinedCommunities returns a list of communities that the user has joined