feat(users): add roles APIs (#63)

* feat(kvstore): add namespace operations for bool

* feat(userstore): add methods for roles

* chore(multiusers): remove useless todo

* feat(multiusers): add apis for roles

* test(roles): add e2e tests for role APIs

* test(e2e/files): enable files tests
This commit is contained in:
Hexxa 2021-07-10 07:08:32 -05:00 committed by GitHub
parent 4b6f6d9e1f
commit 9748d0cab4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 316 additions and 11 deletions

View file

@ -21,6 +21,7 @@ const (
NamesNs = "users"
PwdsNs = "pwds"
RolesNs = "roles"
RoleListNs = "roleList"
InitTimeKey = "initTime"
)
@ -40,6 +41,9 @@ type IUserStore interface {
SetName(id uint64, name string) error
SetPwd(id uint64, pwd string) error
SetRole(id uint64, role string) error
AddRole(role string) error
DelRole(role string) error
ListRoles() (map[string]bool, error)
}
type KVUserStore struct {
@ -57,6 +61,7 @@ func NewKVUserStore(store kvstore.IKVStore) (*KVUserStore, error) {
PwdsNs,
RolesNs,
InitNs,
RoleListNs,
} {
if err = store.AddNamespace(nsName); err != nil {
return nil, err
@ -71,7 +76,8 @@ func NewKVUserStore(store kvstore.IKVStore) (*KVUserStore, error) {
}
func (us *KVUserStore) Init(rootName, rootPwd string) error {
err := us.AddUser(&User{
var err error
err = us.AddUser(&User{
ID: 0,
Name: rootName,
Pwd: rootPwd,
@ -81,6 +87,13 @@ func (us *KVUserStore) Init(rootName, rootPwd string) error {
return err
}
for _, role := range []string{AdminRole, UserRole, VisitorRole} {
err = us.AddRole(role)
if err != nil {
return err
}
}
return us.store.SetStringIn(InitNs, InitTimeKey, fmt.Sprintf("%d", time.Now().Unix()))
}
@ -244,3 +257,33 @@ func (us *KVUserStore) SetRole(id uint64, role string) error {
return us.store.SetStringIn(RolesNs, userID, role)
}
func (us *KVUserStore) AddRole(role string) error {
us.mtx.Lock()
defer us.mtx.Unlock()
_, ok := us.store.GetBoolIn(RoleListNs, role)
if ok {
return fmt.Errorf("role (%s) exists", role)
}
return us.store.SetBoolIn(RoleListNs, role, true)
}
func (us *KVUserStore) DelRole(role string) error {
us.mtx.Lock()
defer us.mtx.Unlock()
if role == AdminRole || role == UserRole || role == VisitorRole {
return errors.New("predefined roles can not be deleted")
}
return us.store.DelBoolIn(RoleListNs, role)
}
func (us *KVUserStore) ListRoles() (map[string]bool, error) {
us.mtx.Lock()
defer us.mtx.Unlock()
return us.store.ListBoolsIn(RoleListNs)
}

View file

@ -11,7 +11,7 @@ import (
func TestUserStores(t *testing.T) {
rootName, rootPwd := "root", "rootPwd"
testUserStore := func(t *testing.T, store IUserStore) {
testUserMethods := func(t *testing.T, store IUserStore) {
root, err := store.GetUser(0)
if err != nil {
t.Fatal(err)
@ -93,6 +93,47 @@ func TestUserStores(t *testing.T) {
}
}
testRoleMethods := func(t *testing.T, store IUserStore) {
roles := []string{"role1", "role2"}
var err error
for _, role := range roles {
err = store.AddRole(role)
if err != nil {
t.Fatal(err)
}
}
roleMap, err := store.ListRoles()
if err != nil {
t.Fatal(err)
}
for _, role := range append(roles, []string{
AdminRole, UserRole, VisitorRole,
}...) {
if !roleMap[role] {
t.Fatalf("role(%s) not found", role)
}
}
for _, role := range roles {
err = store.DelRole(role)
if err != nil {
t.Fatal(err)
}
}
roleMap, err = store.ListRoles()
if err != nil {
t.Fatal(err)
}
for _, role := range roles {
if roleMap[role] {
t.Fatalf("role(%s) should not exist", role)
}
}
}
t.Run("testing KVUserStore", func(t *testing.T) {
rootPath, err := ioutil.TempDir("./", "quickshare_userstore_test_")
if err != nil {
@ -111,6 +152,7 @@ func TestUserStores(t *testing.T) {
t.Fatal("fail to init kvstore", err)
}
testUserStore(t, store)
testUserMethods(t, store)
testRoleMethods(t, store)
})
}