feat: media server and colorhash related change (#3500)

This commit is contained in:
yqrashawn 2023-05-18 14:27:16 +08:00 committed by GitHub
parent c26f45ae3d
commit 6fed50ce53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 149 additions and 59 deletions

View File

@ -1 +1 @@
0.151.8 0.151.9

View File

@ -35,6 +35,8 @@ import (
"github.com/status-im/status-go/nodecfg" "github.com/status-im/status-go/nodecfg"
"github.com/status-im/status-go/params" "github.com/status-im/status-go/params"
"github.com/status-im/status-go/protocol" "github.com/status-im/status-go/protocol"
identityUtils "github.com/status-im/status-go/protocol/identity"
"github.com/status-im/status-go/protocol/identity/colorhash"
"github.com/status-im/status-go/protocol/requests" "github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/rpc" "github.com/status-im/status-go/rpc"
"github.com/status-im/status-go/services/ext" "github.com/status-im/status-go/services/ext"
@ -180,6 +182,13 @@ func (b *GethStatusBackend) OpenAccounts() error {
b.multiaccountsDB = db b.multiaccountsDB = db
// Probably we should iron out a bit better how to create/dispose of the status-service // Probably we should iron out a bit better how to create/dispose of the status-service
b.statusNode.SetMultiaccountsDB(db) b.statusNode.SetMultiaccountsDB(db)
err = b.statusNode.StartMediaServerWithoutDB()
if err != nil {
b.log.Error("failed to start media server without app db", "err", err)
return err
}
return nil return nil
} }
@ -968,12 +977,44 @@ func (b *GethStatusBackend) VerifyDatabasePassword(keyUID string, password strin
return nil return nil
} }
func (b *GethStatusBackend) SaveAccountAndStartNodeWithKey(acc multiaccounts.Account, password string, settings settings.Settings, nodecfg *params.NodeConfig, subaccs []*accounts.Account, keyHex string) error { func enrichMultiaccountInfo(account *multiaccounts.Account, subaccs []*accounts.Account) error {
err := b.SaveAccount(acc) if account.ColorHash != nil && account.ColorID != 0 {
return nil
}
for i, acc := range subaccs {
subaccs[i].KeyUID = account.KeyUID
if acc.Chat {
colorHash, err := colorhash.GenerateFor(string(acc.PublicKey.Bytes()))
if err != nil { if err != nil {
return err return err
} }
err = b.ensureAppDBOpened(acc, password) account.ColorHash = colorHash
colorID, err := identityUtils.ToColorID(string(acc.PublicKey.Bytes()))
if err != nil {
return err
}
account.ColorID = colorID
break
}
}
return nil
}
func (b *GethStatusBackend) SaveAccountAndStartNodeWithKey(account multiaccounts.Account, password string, settings settings.Settings, nodecfg *params.NodeConfig, subaccs []*accounts.Account, keyHex string) error {
err := enrichMultiaccountInfo(&account, subaccs)
if err != nil {
return err
}
err = b.SaveAccount(account)
if err != nil {
return err
}
err = b.ensureAppDBOpened(account, password)
if err != nil { if err != nil {
return err return err
} }
@ -981,7 +1022,7 @@ func (b *GethStatusBackend) SaveAccountAndStartNodeWithKey(acc multiaccounts.Acc
if err != nil { if err != nil {
return err return err
} }
return b.StartNodeWithKey(acc, password, keyHex) return b.StartNodeWithKey(account, password, keyHex)
} }
// StartNodeWithAccountAndInitialConfig is used after account and config was generated. // StartNodeWithAccountAndInitialConfig is used after account and config was generated.
@ -995,7 +1036,12 @@ func (b *GethStatusBackend) StartNodeWithAccountAndInitialConfig(
subaccs []*accounts.Account, subaccs []*accounts.Account,
) error { ) error {
b.log.Info("node config", "config", nodecfg) b.log.Info("node config", "config", nodecfg)
err := b.SaveAccount(account)
err := enrichMultiaccountInfo(&account, subaccs)
if err != nil {
return err
}
err = b.SaveAccount(account)
if err != nil { if err != nil {
return err return err
} }

View File

@ -335,26 +335,6 @@ func SaveAccountAndLogin(accountData, password, settingsJSON, configJSON, subacc
return makeJSONResponse(err) return makeJSONResponse(err)
} }
for i, acc := range subaccs {
subaccs[i].KeyUID = account.KeyUID
if acc.Chat {
colorHash, err := colorhash.GenerateFor(string(acc.PublicKey.Bytes()))
if err != nil {
return makeJSONResponse(err)
}
account.ColorHash = colorHash
colorID, err := identityUtils.ToColorID(string(acc.PublicKey.Bytes()))
if err != nil {
return makeJSONResponse(err)
}
account.ColorID = colorID
break
}
}
api.RunAsync(func() error { api.RunAsync(func() error {
log.Debug("starting a node, and saving account with configuration", "key-uid", account.KeyUID) log.Debug("starting a node, and saving account with configuration", "key-uid", account.KeyUID)
err := statusBackend.StartNodeWithAccountAndInitialConfig(account, password, settings, &conf, subaccs) err := statusBackend.StartNodeWithAccountAndInitialConfig(account, password, settings, &conf, subaccs)
@ -417,26 +397,6 @@ func SaveAccountAndLoginWithKeycard(accountData, password, settingsJSON, configJ
return makeJSONResponse(err) return makeJSONResponse(err)
} }
for i, acc := range subaccs {
subaccs[i].KeyUID = account.KeyUID
if acc.Chat {
colorHash, err := colorhash.GenerateFor(string(acc.PublicKey.Bytes()))
if err != nil {
return makeJSONResponse(err)
}
account.ColorHash = colorHash
colorID, err := identityUtils.ToColorID(string(acc.PublicKey.Bytes()))
if err != nil {
return makeJSONResponse(err)
}
account.ColorID = colorID
break
}
}
api.RunAsync(func() error { api.RunAsync(func() error {
log.Debug("starting a node, and saving account with configuration", "key-uid", account.KeyUID) log.Debug("starting a node, and saving account with configuration", "key-uid", account.KeyUID)
err := statusBackend.SaveAccountAndStartNodeWithKey(account, password, settings, &conf, subaccs, keyHex) err := statusBackend.SaveAccountAndStartNodeWithKey(account, password, settings, &conf, subaccs, keyHex)

View File

@ -362,7 +362,6 @@ func (db *Database) DeleteAccount(keyUID string) error {
} }
// Account images // Account images
func (db *Database) GetIdentityImages(keyUID string) (iis []*images.IdentityImage, err error) { func (db *Database) GetIdentityImages(keyUID string) (iis []*images.IdentityImage, err error) {
rows, err := db.db.Query(`SELECT key_uid, name, image_payload, width, height, file_size, resize_target, clock FROM identity_images WHERE key_uid = ?`, keyUID) rows, err := db.db.Query(`SELECT key_uid, name, image_payload, width, height, file_size, resize_target, clock FROM identity_images WHERE key_uid = ?`, keyUID)
if err != nil { if err != nil {

View File

@ -188,6 +188,34 @@ type StartOptions struct {
AccountsManager *accounts.Manager AccountsManager *accounts.Manager
} }
// StartMediaServerWithoutDB starts media server without starting the node
// The server can only handle requests that don't require appdb or IPFS downloader
func (n *StatusNode) StartMediaServerWithoutDB() error {
if n.isRunning() {
n.log.Debug("node is already running, no need to StartMediaServerWithoutDB")
return nil
}
if n.httpServer != nil {
if err := n.httpServer.Stop(); err != nil {
return err
}
}
httpServer, err := server.NewMediaServer(nil, nil, n.multiaccountsDB)
if err != nil {
return err
}
n.httpServer = httpServer
if err := n.httpServer.Start(); err != nil {
return err
}
return nil
}
// StartWithOptions starts current StatusNode, failing if it's already started. // StartWithOptions starts current StatusNode, failing if it's already started.
// It takes some options that allows to further configure starting process. // It takes some options that allows to further configure starting process.
func (n *StatusNode) StartWithOptions(config *params.NodeConfig, options StartOptions) error { func (n *StatusNode) StartWithOptions(config *params.NodeConfig, options StartOptions) error {
@ -240,18 +268,24 @@ func (n *StatusNode) startWithDB(config *params.NodeConfig, accs *accounts.Manag
n.downloader = ipfs.NewDownloader(config.RootDataDir) n.downloader = ipfs.NewDownloader(config.RootDataDir)
if n.httpServer != nil {
if err := n.httpServer.Stop(); err != nil {
return err
}
}
httpServer, err := server.NewMediaServer(n.appDB, n.downloader, n.multiaccountsDB) httpServer, err := server.NewMediaServer(n.appDB, n.downloader, n.multiaccountsDB)
if err != nil { if err != nil {
return err return err
} }
if err := httpServer.Start(); err != nil { n.httpServer = httpServer
if err := n.httpServer.Start(); err != nil {
return err return err
} }
n.httpServer = httpServer if err := n.initServices(config, n.httpServer); err != nil {
if err := n.initServices(config, httpServer); err != nil {
return err return err
} }
return n.startGethNode() return n.startGethNode()

View File

@ -36,6 +36,18 @@ const (
type HandlerPatternMap map[string]http.HandlerFunc type HandlerPatternMap map[string]http.HandlerFunc
func handleRequestDBMissing(logger *zap.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
logger.Error("can't handle media request without appdb")
}
}
func handleRequestDownloaderMissing(logger *zap.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
logger.Error("can't handle media request without ipfs downloader")
}
}
func handleAccountImages(multiaccountsDB *multiaccounts.Database, logger *zap.Logger) http.HandlerFunc { func handleAccountImages(multiaccountsDB *multiaccounts.Database, logger *zap.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query() params := r.URL.Query()
@ -60,21 +72,33 @@ func handleAccountImages(multiaccountsDB *multiaccounts.Database, logger *zap.Lo
var payload = identityImage.Payload var payload = identityImage.Payload
if ringEnabled(params) { if ringEnabled(params) {
account, err := multiaccountsDB.GetAccount(keyUids[0])
if err != nil {
logger.Error("handleAccountImages: failed to GetAccount .", zap.String("keyUid", keyUids[0]), zap.Error(err))
return
}
accColorHash := account.ColorHash
if accColorHash == nil {
pks, ok := params["publicKey"] pks, ok := params["publicKey"]
if !ok || len(pks) == 0 { if !ok || len(pks) == 0 {
logger.Error("no publicKey") logger.Error("no publicKey")
return return
} }
colorHash, err := colorhash.GenerateFor(pks[0])
accColorHash, err = colorhash.GenerateFor(pks[0])
if err != nil { if err != nil {
logger.Error("could not generate color hash") logger.Error("could not generate color hash")
return return
} }
}
var theme = getTheme(params, logger) var theme = getTheme(params, logger)
payload, err = ring.DrawRing(&ring.DrawRingParam{ payload, err = ring.DrawRing(&ring.DrawRingParam{
Theme: theme, ColorHash: colorHash, ImageBytes: identityImage.Payload, Height: identityImage.Height, Width: identityImage.Width, Theme: theme, ColorHash: accColorHash, ImageBytes: identityImage.Payload, Height: identityImage.Height, Width: identityImage.Width,
}) })
if err != nil { if err != nil {
@ -103,6 +127,10 @@ func handleAccountImages(multiaccountsDB *multiaccounts.Database, logger *zap.Lo
} }
func handleContactImages(db *sql.DB, logger *zap.Logger) http.HandlerFunc { func handleContactImages(db *sql.DB, logger *zap.Logger) http.HandlerFunc {
if db == nil {
return handleRequestDBMissing(logger)
}
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query() params := r.URL.Query()
pks, ok := params["publicKey"] pks, ok := params["publicKey"]
@ -226,6 +254,10 @@ func handleIdenticon(logger *zap.Logger) http.HandlerFunc {
} }
func handleDiscordAuthorAvatar(db *sql.DB, logger *zap.Logger) http.HandlerFunc { func handleDiscordAuthorAvatar(db *sql.DB, logger *zap.Logger) http.HandlerFunc {
if db == nil {
return handleRequestDBMissing(logger)
}
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
authorIDs, ok := r.URL.Query()["authorId"] authorIDs, ok := r.URL.Query()["authorId"]
if !ok || len(authorIDs) == 0 { if !ok || len(authorIDs) == 0 {
@ -260,6 +292,10 @@ func handleDiscordAuthorAvatar(db *sql.DB, logger *zap.Logger) http.HandlerFunc
} }
func handleDiscordAttachment(db *sql.DB, logger *zap.Logger) http.HandlerFunc { func handleDiscordAttachment(db *sql.DB, logger *zap.Logger) http.HandlerFunc {
if db == nil {
return handleRequestDBMissing(logger)
}
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
messageIDs, ok := r.URL.Query()["messageId"] messageIDs, ok := r.URL.Query()["messageId"]
if !ok || len(messageIDs) == 0 { if !ok || len(messageIDs) == 0 {
@ -299,6 +335,10 @@ func handleDiscordAttachment(db *sql.DB, logger *zap.Logger) http.HandlerFunc {
} }
func handleImage(db *sql.DB, logger *zap.Logger) http.HandlerFunc { func handleImage(db *sql.DB, logger *zap.Logger) http.HandlerFunc {
if db == nil {
return handleRequestDBMissing(logger)
}
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
messageIDs, ok := r.URL.Query()["messageId"] messageIDs, ok := r.URL.Query()["messageId"]
if !ok || len(messageIDs) == 0 { if !ok || len(messageIDs) == 0 {
@ -332,6 +372,10 @@ func handleImage(db *sql.DB, logger *zap.Logger) http.HandlerFunc {
} }
func handleAudio(db *sql.DB, logger *zap.Logger) http.HandlerFunc { func handleAudio(db *sql.DB, logger *zap.Logger) http.HandlerFunc {
if db == nil {
return handleRequestDBMissing(logger)
}
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
messageIDs, ok := r.URL.Query()["messageId"] messageIDs, ok := r.URL.Query()["messageId"]
if !ok || len(messageIDs) == 0 { if !ok || len(messageIDs) == 0 {
@ -361,6 +405,10 @@ func handleAudio(db *sql.DB, logger *zap.Logger) http.HandlerFunc {
} }
func handleIPFS(downloader *ipfs.Downloader, logger *zap.Logger) http.HandlerFunc { func handleIPFS(downloader *ipfs.Downloader, logger *zap.Logger) http.HandlerFunc {
if downloader == nil {
return handleRequestDownloaderMissing(logger)
}
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
hashes, ok := r.URL.Query()["hash"] hashes, ok := r.URL.Query()["hash"]
if !ok || len(hashes) == 0 { if !ok || len(hashes) == 0 {

View File

@ -110,6 +110,9 @@ func (s *SyncDeviceSuite) prepareBackendWithAccount(tmpdir string) *api.GethStat
accounts := []*accounts.Account{walletAccount, chatAccount} accounts := []*accounts.Account{walletAccount, chatAccount}
err = backend.StartNodeWithAccountAndInitialConfig(account, s.password, *settings, nodeConfig, accounts) err = backend.StartNodeWithAccountAndInitialConfig(account, s.password, *settings, nodeConfig, accounts)
require.NoError(s.T(), err) require.NoError(s.T(), err)
multiaccounts, err := backend.GetAccounts()
require.NoError(s.T(), err)
require.NotEmpty(s.T(), multiaccounts[0].ColorHash)
return backend return backend
} }