Login endpoints improvements (#4980)

This commit is contained in:
Igor Sirotin 2024-03-28 15:01:44 +00:00 committed by GitHub
parent c98acf76f9
commit 223a1d759e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 123 additions and 48 deletions

View File

@ -1 +1 @@
0.177.1 0.178.0

View File

@ -831,7 +831,6 @@ func TestLoginAccount(t *testing.T) {
Emoji: "some", Emoji: "some",
Password: password, Password: password,
BackupDisabledDataDir: tmpdir, BackupDisabledDataDir: tmpdir,
NetworkID: 1,
LogFilePath: tmpdir + "/log", LogFilePath: tmpdir + "/log",
WakuV2Nameserver: &nameserver, WakuV2Nameserver: &nameserver,
} }
@ -1074,8 +1073,7 @@ func TestConvertAccount(t *testing.T) {
defaultSettings, err := defaultSettings(genAccInfo, derivedAccounts, nil) defaultSettings, err := defaultSettings(genAccInfo, derivedAccounts, nil)
require.NoError(t, err) require.NoError(t, err)
nodeConfig, err := defaultNodeConfig(defaultSettings.InstallationID, &requests.CreateAccount{ nodeConfig, err := defaultNodeConfig(defaultSettings.InstallationID, &requests.CreateAccount{
NetworkID: 1, LogLevel: defaultSettings.LogLevel,
LogLevel: defaultSettings.LogLevel,
}) })
require.NoError(t, err) require.NoError(t, err)
nodeConfig.DataDir = rootDataDir nodeConfig.DataDir = rootDataDir
@ -1388,7 +1386,6 @@ func TestCreateWallet(t *testing.T) {
Emoji: "emoji", Emoji: "emoji",
Password: password, Password: password,
BackupDisabledDataDir: tmpdir, BackupDisabledDataDir: tmpdir,
NetworkID: 1,
LogFilePath: tmpdir + "/log", LogFilePath: tmpdir + "/log",
} }
c := make(chan interface{}, 10) c := make(chan interface{}, 10)
@ -1447,7 +1444,6 @@ func TestSetFleet(t *testing.T) {
CustomizationColor: "#ffffff", CustomizationColor: "#ffffff",
Password: password, Password: password,
BackupDisabledDataDir: tmpdir, BackupDisabledDataDir: tmpdir,
NetworkID: 1,
LogFilePath: tmpdir + "/log", LogFilePath: tmpdir + "/log",
Emoji: "some", Emoji: "some",
} }
@ -1517,7 +1513,6 @@ func TestWalletConfigOnLoginAccount(t *testing.T) {
CustomizationColor: "#ffffff", CustomizationColor: "#ffffff",
Password: password, Password: password,
BackupDisabledDataDir: tmpdir, BackupDisabledDataDir: tmpdir,
NetworkID: 1,
LogFilePath: tmpdir + "/log", LogFilePath: tmpdir + "/log",
Emoji: "some", Emoji: "some",
} }
@ -1586,7 +1581,6 @@ func TestTestnetEnabledSettingOnCreateAccount(t *testing.T) {
Emoji: "some", Emoji: "some",
Password: "password123", Password: "password123",
BackupDisabledDataDir: tmpdir, BackupDisabledDataDir: tmpdir,
NetworkID: 1,
LogFilePath: tmpdir + "/log", LogFilePath: tmpdir + "/log",
TestNetworksEnabled: true, TestNetworksEnabled: true,
} }
@ -1608,7 +1602,6 @@ func TestTestnetEnabledSettingOnCreateAccount(t *testing.T) {
Emoji: "some", Emoji: "some",
Password: "password", Password: "password",
BackupDisabledDataDir: tmpdir, BackupDisabledDataDir: tmpdir,
NetworkID: 1,
LogFilePath: tmpdir + "/log", LogFilePath: tmpdir + "/log",
} }
_, err = b.CreateAccountAndLogin(createAccountRequest2) _, err = b.CreateAccountAndLogin(createAccountRequest2)

View File

@ -4,6 +4,7 @@ import (
"crypto/rand" "crypto/rand"
"encoding/json" "encoding/json"
"math/big" "math/big"
"path/filepath"
"github.com/google/uuid" "github.com/google/uuid"
@ -25,6 +26,9 @@ const walletAccountDefaultName = "Account 1"
const keystoreRelativePath = "keystore" const keystoreRelativePath = "keystore"
const defaultKeycardPairingDataFile = "/ethereum/mainnet_rpc/keycard/pairings.json" const defaultKeycardPairingDataFile = "/ethereum/mainnet_rpc/keycard/pairings.json"
const defaultArchivesRelativePath = "data/archivedata"
const defaultTorrentTorrentsRelativePath = "data/torrents"
var paths = []string{pathWalletRoot, pathEIP1581, pathDefaultChat, pathDefaultWallet} var paths = []string{pathWalletRoot, pathEIP1581, pathDefaultChat, pathDefaultWallet}
var DefaultFleet = params.FleetShardsTest 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) { func defaultNodeConfig(installationID string, request *requests.CreateAccount, opts ...params.Option) (*params.NodeConfig, error) {
// Set mainnet // Set mainnet
nodeConfig := &params.NodeConfig{} nodeConfig := &params.NodeConfig{}
nodeConfig.NetworkID = request.NetworkID
nodeConfig.LogEnabled = request.LogEnabled nodeConfig.LogEnabled = request.LogEnabled
nodeConfig.LogFile = "geth.log" nodeConfig.LogFile = "geth.log"
nodeConfig.LogDir = request.LogFilePath nodeConfig.LogDir = request.LogFilePath
nodeConfig.LogLevel = "ERROR" nodeConfig.LogLevel = "ERROR"
nodeConfig.DataDir = "/ethereum/mainnet_rpc" nodeConfig.DataDir = "/ethereum/mainnet_rpc"
nodeConfig.KeycardPairingDataFile = defaultKeycardPairingDataFile nodeConfig.KeycardPairingDataFile = defaultKeycardPairingDataFile
nodeConfig.ProcessBackedupMessages = false
if request.LogLevel != nil { if request.LogLevel != nil {
nodeConfig.LogLevel = *request.LogLevel 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 != "" { if request.UpstreamConfig != "" {
@ -206,6 +221,9 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount, o
Enabled: true, Enabled: true,
URL: request.UpstreamConfig, URL: request.UpstreamConfig,
} }
} else {
nodeConfig.UpstreamConfig.URL = defaultNetworks[0].RPCURL
nodeConfig.UpstreamConfig.Enabled = true
} }
nodeConfig.Name = "StatusIM" nodeConfig.Name = "StatusIM"
@ -248,10 +266,14 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount, o
if request.VerifyTransactionURL != nil { if request.VerifyTransactionURL != nil {
nodeConfig.ShhextConfig.VerifyTransactionURL = *request.VerifyTransactionURL nodeConfig.ShhextConfig.VerifyTransactionURL = *request.VerifyTransactionURL
} else {
nodeConfig.ShhextConfig.VerifyTransactionURL = defaultNetworks[0].FallbackURL
} }
if request.VerifyENSURL != nil { if request.VerifyENSURL != nil {
nodeConfig.ShhextConfig.VerifyENSURL = *request.VerifyENSURL nodeConfig.ShhextConfig.VerifyENSURL = *request.VerifyENSURL
} else {
nodeConfig.ShhextConfig.VerifyENSURL = defaultNetworks[0].FallbackURL
} }
if request.VerifyTransactionChainID != nil { if request.VerifyTransactionChainID != nil {
@ -270,7 +292,24 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount, o
nodeConfig.LogEnabled = false 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 { for _, opt := range opts {
if err := opt(nodeConfig); err != nil { if err := opt(nodeConfig); err != nil {

View File

@ -632,6 +632,10 @@ func (b *GethStatusBackend) loginAccount(request *requests.Login) error {
return err return err
} }
if request.RuntimeLogLevel != "" {
b.config.LogLevel = request.RuntimeLogLevel
}
if b.config.WakuV2Config.Enabled && request.WakuV2Nameserver != "" { if b.config.WakuV2Config.Enabled && request.WakuV2Nameserver != "" {
b.config.WakuV2Config.Nameserver = request.WakuV2Nameserver b.config.WakuV2Config.Nameserver = request.WakuV2Nameserver
} }
@ -1284,7 +1288,7 @@ func (b *GethStatusBackend) RestoreAccountAndLogin(request *requests.RestoreAcco
return nil, err 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) { func (b *GethStatusBackend) GetKeyUIDByMnemonic(mnemonic string) (string, error) {
@ -1298,7 +1302,7 @@ func (b *GethStatusBackend) GetKeyUIDByMnemonic(mnemonic string) (string, error)
return info.KeyUID, nil 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 keystoreDir := keystoreRelativePath
b.UpdateRootDataDir(request.BackupDisabledDataDir) b.UpdateRootDataDir(request.BackupDisabledDataDir)
@ -1353,10 +1357,28 @@ func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizati
Name: request.DisplayName, Name: request.DisplayName,
CustomizationColor: multiacccommon.CustomizationColor(request.CustomizationColor), CustomizationColor: multiacccommon.CustomizationColor(request.CustomizationColor),
CustomizationColorClock: customizationColorClock, CustomizationColorClock: customizationColorClock,
KDFIterations: dbsetup.ReducedKDFIterationsNumber, KDFIterations: request.KdfIterations,
} }
if account.KDFIterations == 0 {
account.KDFIterations = dbsetup.ReducedKDFIterationsNumber
}
if request.ImagePath != "" { 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 { if err != nil {
return nil, err return nil, err
} }
@ -1387,7 +1409,7 @@ func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizati
if err != nil { if err != nil {
return nil, err return nil, err
} }
if mnemonic != "" { if mnemonic != "" && fetchBackup {
nodeConfig.ProcessBackedupMessages = true 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) { func (b *GethStatusBackend) CreateAccountAndLogin(request *requests.CreateAccount, opts ...params.Option) (*multiaccounts.Account, error) {
validation := &requests.CreateAccountValidation{
if err := request.Validate(); err != nil { AllowEmptyDisplayName: false,
}
if err := request.Validate(validation); err != nil {
return nil, err 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 { func (b *GethStatusBackend) ConvertToRegularAccount(mnemonic string, currPassword string, newPassword string) error {

View File

@ -68,7 +68,6 @@ func startMessenger(cCtx *cli.Context, name string, port int) (*StatusCLI, error
Emoji: "some", Emoji: "some",
Password: "some-password", Password: "some-password",
BackupDisabledDataDir: fmt.Sprintf("./test-%s", strings.ToLower(name)), BackupDisabledDataDir: fmt.Sprintf("./test-%s", strings.ToLower(name)),
NetworkID: 1,
LogFilePath: "log", LogFilePath: "log",
} }
opts := []params.Option{withHTTP(port)} opts := []params.Option{withHTTP(port)}

View File

@ -260,10 +260,12 @@ func Login(accountData, password string) string {
return makeJSONResponse(nil) 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, // 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 // and injects verified key as shh identity. It then updates the accounts node db configuration
// mergin the values received in the configJSON parameter // mergin the values received in the configJSON parameter
//
// Deprecated: Use LoginAccount instead.
func LoginWithConfig(accountData, password, configJSON string) string { func LoginWithConfig(accountData, password, configJSON string) string {
err := login(accountData, password, configJSON) err := login(accountData, password, configJSON)
if err != nil { if err != nil {
@ -279,7 +281,9 @@ func CreateAccountAndLogin(requestJSON string) string {
return makeJSONResponse(err) return makeJSONResponse(err)
} }
err = request.Validate() err = request.Validate(&requests.CreateAccountValidation{
AllowEmptyDisplayName: false,
})
if err != nil { if err != nil {
return makeJSONResponse(err) return makeJSONResponse(err)
} }
@ -346,7 +350,8 @@ func RestoreAccountAndLogin(requestJSON string) string {
return makeJSONResponse(nil) 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 { func SaveAccountAndLogin(accountData, password, settingsJSON, configJSON, subaccountData string) string {
var account multiaccounts.Account var account multiaccounts.Account
err := json.Unmarshal([]byte(accountData), &account) err := json.Unmarshal([]byte(accountData), &account)

View File

@ -9,18 +9,27 @@ var ErrCreateAccountInvalidPassword = errors.New("create-account: invalid passwo
var ErrCreateAccountInvalidCustomizationColor = errors.New("create-account: invalid customization color") var ErrCreateAccountInvalidCustomizationColor = errors.New("create-account: invalid customization color")
var ErrCreateAccountInvalidRootKeystoreDir = errors.New("create-account: invalid root keystore directory") var ErrCreateAccountInvalidRootKeystoreDir = errors.New("create-account: invalid root keystore directory")
var ErrCreateAccountInvalidBackupDisabledDataDir = errors.New("create-account: invalid backup disabled data 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 { type CreateAccount struct {
// BackupDisabledDataDir is the directory where backup is disabled // BackupDisabledDataDir is the directory where backup is disabled
// WARNING: This is used as `RootDataDir`. Consider renaming?
BackupDisabledDataDir string `json:"backupDisabledDataDir"` BackupDisabledDataDir string `json:"backupDisabledDataDir"`
KdfIterations int `json:"kdfIterations"`
DeviceName string `json:"deviceName"` DeviceName string `json:"deviceName"`
DisplayName string `json:"displayName"` DisplayName string `json:"displayName"`
Password string `json:"password"` Password string `json:"password"`
ImagePath string `json:"imagePath"` ImagePath string `json:"imagePath"`
CustomizationColor string `json:"customizationColor"` ImageCropRectangle *ImageCropRectangle `json:"imageCropRectangle"`
Emoji string `json:"emoji"` CustomizationColor string `json:"customizationColor"`
Emoji string `json:"emoji"`
WakuV2Nameserver *string `json:"wakuV2Nameserver"` WakuV2Nameserver *string `json:"wakuV2Nameserver"`
WakuV2LightClient bool `json:"wakuV2LightClient"` WakuV2LightClient bool `json:"wakuV2LightClient"`
@ -37,12 +46,17 @@ type CreateAccount struct {
VerifyTransactionChainID *int64 `json:"verifyTransactionChainID"` VerifyTransactionChainID *int64 `json:"verifyTransactionChainID"`
UpstreamConfig string `json:"upstreamConfig"` UpstreamConfig string `json:"upstreamConfig"`
CurrentNetwork string `json:"currentNetwork"` // Deprecated: CurrentNetwork is deprecated. It was passed and not used, so nothing should be passed instead.
NetworkID uint64 `json:"networkId"` // If you want to use non-default network, use NetworkID.
CurrentNetwork string `json:"currentNetwork"`
NetworkID *uint64 `json:"networkId"`
TestNetworksEnabled bool `json:"testNetworksEnabled"` TestNetworksEnabled bool `json:"testNetworksEnabled"`
WalletSecretsConfig WalletSecretsConfig
TorrentConfigEnabled *bool
TorrentConfigPort *int
} }
type WalletSecretsConfig struct { type WalletSecretsConfig struct {
@ -66,13 +80,10 @@ type WalletSecretsConfig struct {
AlchemyOptimismSepoliaToken string `json:"alchemyOptimismSepoliaToken"` AlchemyOptimismSepoliaToken string `json:"alchemyOptimismSepoliaToken"`
} }
func (c *CreateAccount) Validate() error { func (c *CreateAccount) Validate(validation *CreateAccountValidation) error {
return ValidateAccountCreationRequest(*c)
}
func ValidateAccountCreationRequest(c CreateAccount) error {
// TODO(cammellos): Add proper validation for password/displayname/etc // 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 return ErrCreateAccountInvalidDisplayName
} }
@ -88,10 +99,10 @@ func ValidateAccountCreationRequest(c CreateAccount) error {
return ErrCreateAccountInvalidBackupDisabledDataDir return ErrCreateAccountInvalidBackupDisabledDataDir
} }
if len(c.LogFilePath) == 0 {
return ErrCreateAccountInvalidLogFilePath
}
return nil return nil
}
// NOTE: Reasoning for this struct here: https://github.com/status-im/status-go/pull/4980#discussion_r1539219099
type CreateAccountValidation struct {
AllowEmptyDisplayName bool
} }

View File

@ -5,10 +5,11 @@ import "errors"
var ErrLoginInvalidKeyUID = errors.New("login: invalid key-uid") var ErrLoginInvalidKeyUID = errors.New("login: invalid key-uid")
type Login struct { type Login struct {
Password string `json:"password"` Password string `json:"password"`
KeyUID string `json:"keyUid"` KeyUID string `json:"keyUid"`
KdfIterations int `json:"kdfIterations"`
KdfIterations int `json:"kdfIterations"`
RuntimeLogLevel string `json:"runtimeLogLevel"`
WakuV2Nameserver string `json:"wakuV2Nameserver"` WakuV2Nameserver string `json:"wakuV2Nameserver"`
WalletSecretsConfig WalletSecretsConfig

View File

@ -7,7 +7,8 @@ import (
var ErrRestoreAccountInvalidMnemonic = errors.New("restore-account: invalid mnemonic") var ErrRestoreAccountInvalidMnemonic = errors.New("restore-account: invalid mnemonic")
type RestoreAccount struct { type RestoreAccount struct {
Mnemonic string `json:"mnemonic"` Mnemonic string `json:"mnemonic"`
FetchBackup bool `json:"fetchBackup"`
CreateAccount CreateAccount
} }
@ -16,5 +17,7 @@ func (c *RestoreAccount) Validate() error {
return ErrRestoreAccountInvalidMnemonic return ErrRestoreAccountInvalidMnemonic
} }
return ValidateAccountCreationRequest(c.CreateAccount) return c.CreateAccount.Validate(&CreateAccountValidation{
AllowEmptyDisplayName: true,
})
} }