mirror of https://github.com/poanetwork/gecko.git
Merge pull request #141 from adasari/delete_keystore_user
Added DeleteUser API. Resolves #107
This commit is contained in:
commit
7a4b1a0fdc
|
@ -301,6 +301,70 @@ func (ks *Keystore) ImportUser(r *http.Request, args *ImportUserArgs, reply *Imp
|
|||
return nil
|
||||
}
|
||||
|
||||
// DeleteUserArgs are arguments for passing into DeleteUser requests
|
||||
type DeleteUserArgs struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// DeleteUserReply is the response from calling DeleteUser
|
||||
type DeleteUserReply struct {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
// DeleteUser deletes user with the provided username and password.
|
||||
func (ks *Keystore) DeleteUser(_ *http.Request, args *DeleteUserArgs, reply *DeleteUserReply) error {
|
||||
ks.lock.Lock()
|
||||
defer ks.lock.Unlock()
|
||||
|
||||
ks.log.Verbo("DeleteUser called with %s", args.Username)
|
||||
|
||||
if args.Username == "" {
|
||||
return errEmptyUsername
|
||||
}
|
||||
|
||||
// check if user exists and valid user.
|
||||
usr, err := ks.getUser(args.Username)
|
||||
switch {
|
||||
case err != nil || usr == nil:
|
||||
return fmt.Errorf("user doesn't exist: %s", args.Username)
|
||||
case !usr.CheckPassword(args.Password):
|
||||
return fmt.Errorf("incorrect password for user %q", args.Username)
|
||||
}
|
||||
|
||||
userNameBytes := []byte(args.Username)
|
||||
userBatch := ks.userDB.NewBatch()
|
||||
if err := userBatch.Delete(userNameBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userDataDB := prefixdb.New(userNameBytes, ks.bcDB)
|
||||
dataBatch := userDataDB.NewBatch()
|
||||
|
||||
it := userDataDB.NewIterator()
|
||||
defer it.Release()
|
||||
|
||||
for it.Next() {
|
||||
if err = dataBatch.Delete(it.Key()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = it.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := atomic.WriteAll(dataBatch, userBatch); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// delete from users map.
|
||||
delete(ks.users, args.Username)
|
||||
|
||||
reply.Success = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewBlockchainKeyStore ...
|
||||
func (ks *Keystore) NewBlockchainKeyStore(blockchainID ids.ID) *BlockchainKeystore {
|
||||
return &BlockchainKeystore{
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/ava-labs/gecko/database/memdb"
|
||||
|
@ -280,3 +281,89 @@ func TestServiceExportImport(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceDeleteUser(t *testing.T) {
|
||||
testUser := "testUser"
|
||||
password := "passwTest@fake01ord"
|
||||
tests := []struct {
|
||||
desc string
|
||||
setup func(ks *Keystore) error
|
||||
request *DeleteUserArgs
|
||||
want *DeleteUserReply
|
||||
wantError bool
|
||||
}{{
|
||||
desc: "empty user name case",
|
||||
request: &DeleteUserArgs{},
|
||||
wantError: true,
|
||||
}, {
|
||||
desc: "user not exists case",
|
||||
request: &DeleteUserArgs{Username: "dummy"},
|
||||
wantError: true,
|
||||
}, {
|
||||
desc: "user exists and invalid password case",
|
||||
request: &DeleteUserArgs{Username: testUser, Password: "password"},
|
||||
wantError: true,
|
||||
}, {
|
||||
desc: "user exists and valid password case",
|
||||
setup: func(ks *Keystore) error {
|
||||
return ks.CreateUser(nil, &CreateUserArgs{Username: testUser, Password: password}, &CreateUserReply{})
|
||||
},
|
||||
request: &DeleteUserArgs{Username: testUser, Password: password},
|
||||
want: &DeleteUserReply{Success: true},
|
||||
}, {
|
||||
desc: "delete a user, imported from import api case",
|
||||
setup: func(ks *Keystore) error {
|
||||
|
||||
reply := CreateUserReply{}
|
||||
if err := ks.CreateUser(nil, &CreateUserArgs{Username: testUser, Password: password}, &reply); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// created data in bob db
|
||||
db, err := ks.GetDatabase(ids.Empty, testUser, password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := db.Put([]byte("hello"), []byte("world")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
request: &DeleteUserArgs{Username: testUser, Password: password},
|
||||
want: &DeleteUserReply{Success: true},
|
||||
}}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
ks := Keystore{}
|
||||
ks.Initialize(logging.NoLog{}, memdb.New())
|
||||
|
||||
if tt.setup != nil {
|
||||
if err := tt.setup(&ks); err != nil {
|
||||
t.Fatalf("failed to create user setup in keystore: %v", err)
|
||||
}
|
||||
}
|
||||
got := &DeleteUserReply{}
|
||||
err := ks.DeleteUser(nil, tt.request, got)
|
||||
if (err != nil) != tt.wantError {
|
||||
t.Fatalf("DeleteUser() failed: error %v, wantError %v", err, tt.wantError)
|
||||
}
|
||||
|
||||
if !tt.wantError && !reflect.DeepEqual(tt.want, got) {
|
||||
t.Fatalf("DeleteUser() failed: got %v, want %v", got, tt.want)
|
||||
}
|
||||
|
||||
if err == nil && got.Success { // delete is successful
|
||||
if _, ok := ks.users[testUser]; ok {
|
||||
t.Fatalf("DeleteUser() failed: expected the user %s should be delete from users map", testUser)
|
||||
}
|
||||
|
||||
// deleted user details should be available to create user again.
|
||||
if err = ks.CreateUser(nil, &CreateUserArgs{Username: testUser, Password: password}, &CreateUserReply{}); err != nil {
|
||||
t.Fatalf("failed to create user: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue