From 223a1d759e348e2450fe9e3f2a413f667f4c8b93 Mon Sep 17 00:00:00 2001 From: Igor Sirotin Date: Thu, 28 Mar 2024 15:01:44 +0000 Subject: [PATCH] Login endpoints improvements (#4980) --- VERSION | 2 +- api/backend_test.go | 9 +---- api/defaults.go | 43 +++++++++++++++++++++-- api/geth_backend.go | 40 +++++++++++++++++----- cmd/status-cli/util.go | 1 - mobile/status.go | 11 ++++-- protocol/requests/create_account.go | 51 +++++++++++++++++----------- protocol/requests/login.go | 7 ++-- protocol/requests/restore_account.go | 7 ++-- 9 files changed, 123 insertions(+), 48 deletions(-) diff --git a/VERSION b/VERSION index 4ef231165..8fbb120cd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.177.1 +0.178.0 diff --git a/api/backend_test.go b/api/backend_test.go index f8aad85c4..4d8509a8e 100644 --- a/api/backend_test.go +++ b/api/backend_test.go @@ -831,7 +831,6 @@ func TestLoginAccount(t *testing.T) { Emoji: "some", Password: password, BackupDisabledDataDir: tmpdir, - NetworkID: 1, LogFilePath: tmpdir + "/log", WakuV2Nameserver: &nameserver, } @@ -1074,8 +1073,7 @@ func TestConvertAccount(t *testing.T) { defaultSettings, err := defaultSettings(genAccInfo, derivedAccounts, nil) require.NoError(t, err) nodeConfig, err := defaultNodeConfig(defaultSettings.InstallationID, &requests.CreateAccount{ - NetworkID: 1, - LogLevel: defaultSettings.LogLevel, + LogLevel: defaultSettings.LogLevel, }) require.NoError(t, err) nodeConfig.DataDir = rootDataDir @@ -1388,7 +1386,6 @@ func TestCreateWallet(t *testing.T) { Emoji: "emoji", Password: password, BackupDisabledDataDir: tmpdir, - NetworkID: 1, LogFilePath: tmpdir + "/log", } c := make(chan interface{}, 10) @@ -1447,7 +1444,6 @@ func TestSetFleet(t *testing.T) { CustomizationColor: "#ffffff", Password: password, BackupDisabledDataDir: tmpdir, - NetworkID: 1, LogFilePath: tmpdir + "/log", Emoji: "some", } @@ -1517,7 +1513,6 @@ func TestWalletConfigOnLoginAccount(t *testing.T) { CustomizationColor: "#ffffff", Password: password, BackupDisabledDataDir: tmpdir, - NetworkID: 1, LogFilePath: tmpdir + "/log", Emoji: "some", } @@ -1586,7 +1581,6 @@ func TestTestnetEnabledSettingOnCreateAccount(t *testing.T) { Emoji: "some", Password: "password123", BackupDisabledDataDir: tmpdir, - NetworkID: 1, LogFilePath: tmpdir + "/log", TestNetworksEnabled: true, } @@ -1608,7 +1602,6 @@ func TestTestnetEnabledSettingOnCreateAccount(t *testing.T) { Emoji: "some", Password: "password", BackupDisabledDataDir: tmpdir, - NetworkID: 1, LogFilePath: tmpdir + "/log", } _, err = b.CreateAccountAndLogin(createAccountRequest2) diff --git a/api/defaults.go b/api/defaults.go index b69a0c9f4..10a34c5ee 100644 --- a/api/defaults.go +++ b/api/defaults.go @@ -4,6 +4,7 @@ import ( "crypto/rand" "encoding/json" "math/big" + "path/filepath" "github.com/google/uuid" @@ -25,6 +26,9 @@ const walletAccountDefaultName = "Account 1" const keystoreRelativePath = "keystore" const defaultKeycardPairingDataFile = "/ethereum/mainnet_rpc/keycard/pairings.json" +const defaultArchivesRelativePath = "data/archivedata" +const defaultTorrentTorrentsRelativePath = "data/torrents" + var paths = []string{pathWalletRoot, pathEIP1581, pathDefaultChat, pathDefaultWallet} var DefaultFleet = params.FleetShardsTest @@ -189,16 +193,27 @@ func buildWalletConfig(request *requests.WalletSecretsConfig) params.WalletConfi func defaultNodeConfig(installationID string, request *requests.CreateAccount, opts ...params.Option) (*params.NodeConfig, error) { // Set mainnet nodeConfig := ¶ms.NodeConfig{} - nodeConfig.NetworkID = request.NetworkID nodeConfig.LogEnabled = request.LogEnabled nodeConfig.LogFile = "geth.log" nodeConfig.LogDir = request.LogFilePath nodeConfig.LogLevel = "ERROR" nodeConfig.DataDir = "/ethereum/mainnet_rpc" nodeConfig.KeycardPairingDataFile = defaultKeycardPairingDataFile + nodeConfig.ProcessBackedupMessages = false if request.LogLevel != nil { nodeConfig.LogLevel = *request.LogLevel + nodeConfig.LogEnabled = true + } else { + nodeConfig.LogEnabled = false + } + + nodeConfig.Networks = BuildDefaultNetworks(request) + + if request.NetworkID != nil { + nodeConfig.NetworkID = *request.NetworkID + } else { + nodeConfig.NetworkID = nodeConfig.Networks[0].ChainID } if request.UpstreamConfig != "" { @@ -206,6 +221,9 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount, o Enabled: true, URL: request.UpstreamConfig, } + } else { + nodeConfig.UpstreamConfig.URL = defaultNetworks[0].RPCURL + nodeConfig.UpstreamConfig.Enabled = true } nodeConfig.Name = "StatusIM" @@ -248,10 +266,14 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount, o if request.VerifyTransactionURL != nil { nodeConfig.ShhextConfig.VerifyTransactionURL = *request.VerifyTransactionURL + } else { + nodeConfig.ShhextConfig.VerifyTransactionURL = defaultNetworks[0].FallbackURL } if request.VerifyENSURL != nil { nodeConfig.ShhextConfig.VerifyENSURL = *request.VerifyENSURL + } else { + nodeConfig.ShhextConfig.VerifyENSURL = defaultNetworks[0].FallbackURL } if request.VerifyTransactionChainID != nil { @@ -270,7 +292,24 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount, o nodeConfig.LogEnabled = false } - nodeConfig.Networks = BuildDefaultNetworks(request) + if request.NetworkID != nil { + nodeConfig.NetworkID = *request.NetworkID + } + + nodeConfig.TorrentConfig = params.TorrentConfig{ + Enabled: false, + Port: 0, + DataDir: filepath.Join(nodeConfig.RootDataDir, defaultArchivesRelativePath), + TorrentDir: filepath.Join(nodeConfig.RootDataDir, defaultTorrentTorrentsRelativePath), + } + + if request.TorrentConfigEnabled != nil { + nodeConfig.TorrentConfig.Enabled = *request.TorrentConfigEnabled + + } + if request.TorrentConfigPort != nil { + nodeConfig.TorrentConfig.Port = *request.TorrentConfigPort + } for _, opt := range opts { if err := opt(nodeConfig); err != nil { diff --git a/api/geth_backend.go b/api/geth_backend.go index fe48d54fa..6486990d4 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -632,6 +632,10 @@ func (b *GethStatusBackend) loginAccount(request *requests.Login) error { return err } + if request.RuntimeLogLevel != "" { + b.config.LogLevel = request.RuntimeLogLevel + } + if b.config.WakuV2Config.Enabled && request.WakuV2Nameserver != "" { b.config.WakuV2Config.Nameserver = request.WakuV2Nameserver } @@ -1284,7 +1288,7 @@ func (b *GethStatusBackend) RestoreAccountAndLogin(request *requests.RestoreAcco return nil, err } - return b.generateOrImportAccount(request.Mnemonic, 0, &request.CreateAccount) + return b.generateOrImportAccount(request.Mnemonic, 0, request.FetchBackup, &request.CreateAccount) } func (b *GethStatusBackend) GetKeyUIDByMnemonic(mnemonic string) (string, error) { @@ -1298,7 +1302,7 @@ func (b *GethStatusBackend) GetKeyUIDByMnemonic(mnemonic string) (string, error) return info.KeyUID, nil } -func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizationColorClock uint64, request *requests.CreateAccount, opts ...params.Option) (*multiaccounts.Account, error) { +func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizationColorClock uint64, fetchBackup bool, request *requests.CreateAccount, opts ...params.Option) (*multiaccounts.Account, error) { keystoreDir := keystoreRelativePath b.UpdateRootDataDir(request.BackupDisabledDataDir) @@ -1353,10 +1357,28 @@ func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizati Name: request.DisplayName, CustomizationColor: multiacccommon.CustomizationColor(request.CustomizationColor), CustomizationColorClock: customizationColorClock, - KDFIterations: dbsetup.ReducedKDFIterationsNumber, + KDFIterations: request.KdfIterations, } + + if account.KDFIterations == 0 { + account.KDFIterations = dbsetup.ReducedKDFIterationsNumber + } + if request.ImagePath != "" { - iis, err := images.GenerateIdentityImages(request.ImagePath, 0, 0, 1000, 1000) + imageCropRectangle := request.ImageCropRectangle + if imageCropRectangle == nil { + // Default crop rectangle used by mobile + imageCropRectangle = &requests.ImageCropRectangle{ + Ax: 0, + Ay: 0, + Bx: 1000, + By: 1000, + } + } + + iis, err := images.GenerateIdentityImages(request.ImagePath, + imageCropRectangle.Ax, imageCropRectangle.Ay, imageCropRectangle.Bx, imageCropRectangle.By) + if err != nil { return nil, err } @@ -1387,7 +1409,7 @@ func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizati if err != nil { return nil, err } - if mnemonic != "" { + if mnemonic != "" && fetchBackup { nodeConfig.ProcessBackedupMessages = true } @@ -1432,11 +1454,13 @@ func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizati } func (b *GethStatusBackend) CreateAccountAndLogin(request *requests.CreateAccount, opts ...params.Option) (*multiaccounts.Account, error) { - - if err := request.Validate(); err != nil { + validation := &requests.CreateAccountValidation{ + AllowEmptyDisplayName: false, + } + if err := request.Validate(validation); err != nil { return nil, err } - return b.generateOrImportAccount("", 1, request, opts...) + return b.generateOrImportAccount("", 1, false, request, opts...) } func (b *GethStatusBackend) ConvertToRegularAccount(mnemonic string, currPassword string, newPassword string) error { diff --git a/cmd/status-cli/util.go b/cmd/status-cli/util.go index d0767ccb9..019d4ee4a 100644 --- a/cmd/status-cli/util.go +++ b/cmd/status-cli/util.go @@ -68,7 +68,6 @@ func startMessenger(cCtx *cli.Context, name string, port int) (*StatusCLI, error Emoji: "some", Password: "some-password", BackupDisabledDataDir: fmt.Sprintf("./test-%s", strings.ToLower(name)), - NetworkID: 1, LogFilePath: "log", } opts := []params.Option{withHTTP(port)} diff --git a/mobile/status.go b/mobile/status.go index 4fb2ceeaf..d9b942203 100644 --- a/mobile/status.go +++ b/mobile/status.go @@ -260,10 +260,12 @@ func Login(accountData, password string) string { return makeJSONResponse(nil) } -// Login loads a key file (for a given address), tries to decrypt it using the password, +// LoginWithConfig loads a key file (for a given address), tries to decrypt it using the password, // to verify ownership if verified, purges all the previous identities from Whisper, // and injects verified key as shh identity. It then updates the accounts node db configuration // mergin the values received in the configJSON parameter +// +// Deprecated: Use LoginAccount instead. func LoginWithConfig(accountData, password, configJSON string) string { err := login(accountData, password, configJSON) if err != nil { @@ -279,7 +281,9 @@ func CreateAccountAndLogin(requestJSON string) string { return makeJSONResponse(err) } - err = request.Validate() + err = request.Validate(&requests.CreateAccountValidation{ + AllowEmptyDisplayName: false, + }) if err != nil { return makeJSONResponse(err) } @@ -346,7 +350,8 @@ func RestoreAccountAndLogin(requestJSON string) string { return makeJSONResponse(nil) } -// SaveAccountAndLogin saves account in status-go database.. +// SaveAccountAndLogin saves account in status-go database. +// Deprecated: Use CreateAccountAndLogin instead. func SaveAccountAndLogin(accountData, password, settingsJSON, configJSON, subaccountData string) string { var account multiaccounts.Account err := json.Unmarshal([]byte(accountData), &account) diff --git a/protocol/requests/create_account.go b/protocol/requests/create_account.go index fa2fe5dfc..ffc8d7b00 100644 --- a/protocol/requests/create_account.go +++ b/protocol/requests/create_account.go @@ -9,18 +9,27 @@ var ErrCreateAccountInvalidPassword = errors.New("create-account: invalid passwo var ErrCreateAccountInvalidCustomizationColor = errors.New("create-account: invalid customization color") var ErrCreateAccountInvalidRootKeystoreDir = errors.New("create-account: invalid root keystore directory") var ErrCreateAccountInvalidBackupDisabledDataDir = errors.New("create-account: invalid backup disabled data directory") -var ErrCreateAccountInvalidLogFilePath = errors.New("create-account: invalid log file path") + +type ImageCropRectangle struct { + Ax int `json:"ax"` + Ay int `json:"ay"` + Bx int `json:"bx"` + By int `json:"by"` +} type CreateAccount struct { // BackupDisabledDataDir is the directory where backup is disabled + // WARNING: This is used as `RootDataDir`. Consider renaming? BackupDisabledDataDir string `json:"backupDisabledDataDir"` + KdfIterations int `json:"kdfIterations"` - DeviceName string `json:"deviceName"` - DisplayName string `json:"displayName"` - Password string `json:"password"` - ImagePath string `json:"imagePath"` - CustomizationColor string `json:"customizationColor"` - Emoji string `json:"emoji"` + DeviceName string `json:"deviceName"` + DisplayName string `json:"displayName"` + Password string `json:"password"` + ImagePath string `json:"imagePath"` + ImageCropRectangle *ImageCropRectangle `json:"imageCropRectangle"` + CustomizationColor string `json:"customizationColor"` + Emoji string `json:"emoji"` WakuV2Nameserver *string `json:"wakuV2Nameserver"` WakuV2LightClient bool `json:"wakuV2LightClient"` @@ -37,12 +46,17 @@ type CreateAccount struct { VerifyTransactionChainID *int64 `json:"verifyTransactionChainID"` UpstreamConfig string `json:"upstreamConfig"` - CurrentNetwork string `json:"currentNetwork"` - NetworkID uint64 `json:"networkId"` + // Deprecated: CurrentNetwork is deprecated. It was passed and not used, so nothing should be passed instead. + // If you want to use non-default network, use NetworkID. + CurrentNetwork string `json:"currentNetwork"` + NetworkID *uint64 `json:"networkId"` TestNetworksEnabled bool `json:"testNetworksEnabled"` WalletSecretsConfig + + TorrentConfigEnabled *bool + TorrentConfigPort *int } type WalletSecretsConfig struct { @@ -66,13 +80,10 @@ type WalletSecretsConfig struct { AlchemyOptimismSepoliaToken string `json:"alchemyOptimismSepoliaToken"` } -func (c *CreateAccount) Validate() error { - return ValidateAccountCreationRequest(*c) -} - -func ValidateAccountCreationRequest(c CreateAccount) error { +func (c *CreateAccount) Validate(validation *CreateAccountValidation) error { // TODO(cammellos): Add proper validation for password/displayname/etc - if len(c.DisplayName) == 0 { + // Empty display name is allowed during account restore + if len(c.DisplayName) == 0 && !validation.AllowEmptyDisplayName { return ErrCreateAccountInvalidDisplayName } @@ -88,10 +99,10 @@ func ValidateAccountCreationRequest(c CreateAccount) error { return ErrCreateAccountInvalidBackupDisabledDataDir } - if len(c.LogFilePath) == 0 { - return ErrCreateAccountInvalidLogFilePath - } - return nil - +} + +// NOTE: Reasoning for this struct here: https://github.com/status-im/status-go/pull/4980#discussion_r1539219099 +type CreateAccountValidation struct { + AllowEmptyDisplayName bool } diff --git a/protocol/requests/login.go b/protocol/requests/login.go index 31727fb18..4c895c0fa 100644 --- a/protocol/requests/login.go +++ b/protocol/requests/login.go @@ -5,10 +5,11 @@ import "errors" var ErrLoginInvalidKeyUID = errors.New("login: invalid key-uid") type Login struct { - Password string `json:"password"` - KeyUID string `json:"keyUid"` - KdfIterations int `json:"kdfIterations"` + Password string `json:"password"` + KeyUID string `json:"keyUid"` + KdfIterations int `json:"kdfIterations"` + RuntimeLogLevel string `json:"runtimeLogLevel"` WakuV2Nameserver string `json:"wakuV2Nameserver"` WalletSecretsConfig diff --git a/protocol/requests/restore_account.go b/protocol/requests/restore_account.go index 1095507b1..e6bf54861 100644 --- a/protocol/requests/restore_account.go +++ b/protocol/requests/restore_account.go @@ -7,7 +7,8 @@ import ( var ErrRestoreAccountInvalidMnemonic = errors.New("restore-account: invalid mnemonic") type RestoreAccount struct { - Mnemonic string `json:"mnemonic"` + Mnemonic string `json:"mnemonic"` + FetchBackup bool `json:"fetchBackup"` CreateAccount } @@ -16,5 +17,7 @@ func (c *RestoreAccount) Validate() error { return ErrRestoreAccountInvalidMnemonic } - return ValidateAccountCreationRequest(c.CreateAccount) + return c.CreateAccount.Validate(&CreateAccountValidation{ + AllowEmptyDisplayName: true, + }) }