OSDN Git Service

Add Update Account Alias Api (#1461)
authorJohn Chi <jcunionmatrix@gmail.com>
Wed, 14 Nov 2018 10:19:39 +0000 (18:19 +0800)
committerPaladz <yzhu101@uottawa.ca>
Wed, 14 Nov 2018 10:19:39 +0000 (18:19 +0800)
* feat(api): add update account alias api

* feat(api): update account alias api add account_alias parameter

* fix(api): delete old alias from database when update account alias

account/accounts.go
account/accounts_test.go
api/accounts.go
api/api.go
cmd/bytomcli/commands/account.go
cmd/bytomcli/commands/bytomcli.go

index d8ae5e6..ec1d380 100644 (file)
@@ -167,6 +167,39 @@ func (m *Manager) Create(xpubs []chainkd.XPub, quorum int, alias string) (*Accou
        return account, nil
 }
 
+func (m *Manager) UpdateAccountAlias(accountID string, newAlias string) (err error) {
+       m.accountMu.Lock()
+       defer m.accountMu.Unlock()
+
+       account, err := m.FindByID(accountID)
+       if err != nil {
+               return err
+       }
+       oldAlias := account.Alias
+
+       normalizedAlias := strings.ToLower(strings.TrimSpace(newAlias))
+       if existed := m.db.Get(aliasKey(normalizedAlias)); existed != nil {
+               return ErrDuplicateAlias
+       }
+
+       m.cacheMu.Lock()
+       m.aliasCache.Remove(oldAlias)
+       m.cacheMu.Unlock()
+
+       account.Alias = normalizedAlias
+       rawAccount, err := json.Marshal(account)
+       if err != nil {
+               return ErrMarshalAccount
+       }
+
+       storeBatch := m.db.NewBatch()
+       storeBatch.Delete(aliasKey(oldAlias))
+       storeBatch.Set(Key(accountID), rawAccount)
+       storeBatch.Set(aliasKey(normalizedAlias), []byte(accountID))
+       storeBatch.Write()
+       return nil
+}
+
 // CreateAddress generate an address for the select account
 func (m *Manager) CreateAddress(accountID string, change bool) (cp *CtrlProgram, err error) {
        account, err := m.FindByID(accountID)
index 7f26e5b..2623f98 100644 (file)
@@ -81,6 +81,39 @@ func TestCreateAccountReusedAlias(t *testing.T) {
        }
 }
 
+func TestUpdateAccountAlias(t *testing.T) {
+       oldAlias := "test-alias"
+       newAlias := "my-alias"
+
+       m := mockAccountManager(t)
+       account := m.createTestAccount(t, oldAlias, nil)
+       if err := m.UpdateAccountAlias("testID", newAlias); err == nil {
+               t.Fatal("expected error when using an invalid account id")
+       }
+
+       err := m.UpdateAccountAlias(account.ID, oldAlias)
+       if errors.Root(err) != ErrDuplicateAlias {
+               t.Errorf("expected %s when using a duplicate alias, got %v", ErrDuplicateAlias, err)
+       }
+
+       if err := m.UpdateAccountAlias(account.ID, newAlias); err != nil {
+               t.Errorf("expected account %v alias should be update", account)
+       }
+
+       updatedAccount, err := m.FindByID(account.ID)
+       if err != nil {
+               t.Errorf("unexpected error %v", err)
+       }
+
+       if updatedAccount.Alias != newAlias {
+               t.Fatalf("alias:\ngot:  %v\nwant: %v", updatedAccount.Alias, newAlias)
+       }
+
+       if _, err = m.FindByAlias(oldAlias); errors.Root(err) != ErrFindAccount {
+               t.Errorf("expected %s when using a old alias, got %v", ErrFindAccount, err)
+       }
+}
+
 func TestDeleteAccount(t *testing.T) {
        m := mockAccountManager(t)
 
@@ -168,7 +201,7 @@ func TestGetAccountIndexKey(t *testing.T) {
        if !reflect.DeepEqual(GetAccountIndexKey(xpubs1), GetAccountIndexKey(xpubs2)) {
                t.Fatal("GetAccountIndexKey test err")
        }
-       
+
        if reflect.DeepEqual(xpubs1, xpubs2) {
                t.Fatal("GetAccountIndexKey test err")
        }
index b84e25d..5013ae4 100644 (file)
@@ -31,6 +31,26 @@ func (a *API) createAccount(ctx context.Context, ins struct {
        return NewSuccessResponse(annotatedAccount)
 }
 
+// POST update-account-alias
+func (a *API) updateAccountAlias(ctx context.Context, ins struct {
+       AccountID    string `json:"account_id"`
+       AccountAlias string `json:"account_alias"`
+       NewAlias     string `json:"new_alias"`
+}) Response {
+       accountID := ins.AccountID
+       if ins.AccountAlias != "" {
+               foundAccount, err := a.wallet.AccountMgr.FindByAlias(ins.AccountAlias)
+               if err != nil {
+                       return NewErrorResponse(err)
+               }
+               accountID = foundAccount.ID
+       }
+       if err := a.wallet.AccountMgr.UpdateAccountAlias(accountID, ins.NewAlias); err != nil {
+               return NewErrorResponse(err)
+       }
+       return NewSuccessResponse(nil)
+}
+
 // AccountInfo is request struct for deleteAccount
 type AccountInfo struct {
        Info string `json:"account_info"`
index 198c38e..5fae6ae 100644 (file)
@@ -200,6 +200,7 @@ func (a *API) buildHandler() {
                walletEnable = true
 
                m.Handle("/create-account", jsonHandler(a.createAccount))
+               m.Handle("/update-account-alias", jsonHandler(a.updateAccountAlias))
                m.Handle("/list-accounts", jsonHandler(a.listAccounts))
                m.Handle("/delete-account", jsonHandler(a.deleteAccount))
 
index 1b45283..2bb79e9 100644 (file)
@@ -15,6 +15,9 @@ func init() {
        createAccountCmd.PersistentFlags().IntVarP(&accountQuorum, "quorom", "q", 1, "quorum must be greater than 0 and less than or equal to the number of signers")
        createAccountCmd.PersistentFlags().StringVarP(&accountToken, "access", "a", "", "access token")
 
+       updateAccountAliasCmd.PersistentFlags().StringVar(&accountID, "id", "", "account ID")
+       updateAccountAliasCmd.PersistentFlags().StringVar(&accountAlias, "alias", "", "account alias")
+
        listAccountsCmd.PersistentFlags().StringVar(&accountID, "id", "", "account ID")
        listAccountsCmd.PersistentFlags().StringVar(&accountAlias, "alias", "", "account alias")
 
@@ -73,6 +76,26 @@ var createAccountCmd = &cobra.Command{
        },
 }
 
+var updateAccountAliasCmd = &cobra.Command{
+       Use:   "update-account-alias <newAlias>",
+       Short: "update account alias",
+       Args:  cobra.ExactArgs(1),
+       Run: func(cmd *cobra.Command, args []string) {
+               var ins = struct {
+                       AccountID    string `json:"account_id"`
+                       AccountAlias string `json:"account_alias"`
+                       NewAlias     string `json:"new_alias"`
+               }{AccountID: accountID, AccountAlias: accountAlias, NewAlias: args[0]}
+
+               _, exitCode := util.ClientCall("/update-account-alias", &ins)
+               if exitCode != util.Success {
+                       os.Exit(exitCode)
+               }
+
+               jww.FEEDBACK.Println("Successfully update account alias")
+       },
+}
+
 var listAccountsCmd = &cobra.Command{
        Use:   "list-accounts",
        Short: "List the existing accounts",
index bc5285b..a089e4e 100644 (file)
@@ -114,6 +114,7 @@ func AddCommands() {
        BytomcliCmd.AddCommand(createAccountCmd)
        BytomcliCmd.AddCommand(deleteAccountCmd)
        BytomcliCmd.AddCommand(listAccountsCmd)
+       BytomcliCmd.AddCommand(updateAccountAliasCmd)
        BytomcliCmd.AddCommand(createAccountReceiverCmd)
        BytomcliCmd.AddCommand(listAddressesCmd)
        BytomcliCmd.AddCommand(validateAddressCmd)
@@ -181,6 +182,7 @@ func AddTemplateFunc() {
                createAccountCmd.Name(),
                listAccountsCmd.Name(),
                deleteAccountCmd.Name(),
+               updateAccountAliasCmd.Name(),
                createAccountReceiverCmd.Name(),
                listAddressesCmd.Name(),
                validateAddressCmd.Name(),