You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2021/05/31 11:12:13 UTC

[servicecomb-service-center] branch master updated: Add account/auth error code (#1029)

This is an automated email from the ASF dual-hosted git repository.

littlecui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new 2f66380  Add account/auth error code (#1029)
2f66380 is described below

commit 2f66380422260d980f563a8fb1f39befb862b532
Author: humingcheng <hu...@163.com>
AuthorDate: Mon May 31 19:12:03 2021 +0800

    Add account/auth error code (#1029)
    
    * Add account/auth error code
    
    * Add account/auth error code
---
 datasource/etcd/account.go                     |   3 +
 datasource/mongo/account.go                    |   6 +-
 pkg/rest/util.go                               |   5 +
 server/handler/auth/auth.go                    |   5 +
 server/plugin/auth/buildin/buidlin_test.go     |  25 ++-
 server/plugin/auth/buildin/buildin.go          |   9 +-
 server/resource/v4/auth_resource.go            |  65 +++----
 server/resource/v4/auth_resource_test.go       |  15 +-
 server/resource/v4/role_resource.go            |  12 +-
 server/resource/v4/role_resource_test.go       |  98 +++++++----
 server/service/rbac/account_dao.go             | 179 +++++++++++++++++++
 server/service/rbac/account_dao_test.go        | 228 +++++++++++++++++++++++++
 server/service/rbac/authr_plugin.go            |  25 ++-
 server/service/rbac/dao/account_dao.go         | 109 ------------
 server/service/rbac/dao/account_dao_test.go    |  82 ---------
 server/service/rbac/password.go                |   7 +-
 server/service/rbac/rbac.go                    |  27 ++-
 server/service/rbac/rbac_test.go               |  32 +---
 server/service/rbac/role.go                    |   3 +-
 server/service/rbac/{dao => }/role_dao.go      |   2 +-
 server/service/rbac/{dao => }/role_dao_test.go |  53 +++---
 21 files changed, 614 insertions(+), 376 deletions(-)

diff --git a/datasource/etcd/account.go b/datasource/etcd/account.go
index bcf37e4..487adea 100644
--- a/datasource/etcd/account.go
+++ b/datasource/etcd/account.go
@@ -115,6 +115,9 @@ func (ds *DataSource) GetAccount(ctx context.Context, name string) (*rbac.Accoun
 	if err != nil {
 		return nil, err
 	}
+	if resp.Count == 0 {
+		return nil, datasource.ErrAccountNotExist
+	}
 	if resp.Count != 1 {
 		return nil, client.ErrNotUnique
 	}
diff --git a/datasource/mongo/account.go b/datasource/mongo/account.go
index effd9e6..0d297cc 100644
--- a/datasource/mongo/account.go
+++ b/datasource/mongo/account.go
@@ -20,6 +20,7 @@ package mongo
 import (
 	"context"
 	"fmt"
+	"go.mongodb.org/mongo-driver/mongo"
 
 	"github.com/go-chassis/cari/rbac"
 
@@ -80,7 +81,10 @@ func (ds *DataSource) GetAccount(ctx context.Context, name string) (*rbac.Accoun
 		log.Error(msg, err)
 		return nil, err
 	}
-	if result.Err() != nil {
+	if err = result.Err(); err != nil {
+		if err == mongo.ErrNoDocuments {
+			return nil, datasource.ErrAccountNotExist
+		}
 		msg := fmt.Sprintf("failed to query account, account name %s", name)
 		log.Error(msg, result.Err())
 		return nil, datasource.ErrQueryAccountFailed
diff --git a/pkg/rest/util.go b/pkg/rest/util.go
index d707b55..142ef12 100644
--- a/pkg/rest/util.go
+++ b/pkg/rest/util.go
@@ -22,6 +22,7 @@ import (
 	"encoding/json"
 	"errors"
 	"io/ioutil"
+	"github.com/go-chassis/cari/pkg/errsvc"
 	"net/http"
 
 	"github.com/apache/servicecomb-service-center/pkg/log"
@@ -33,6 +34,10 @@ var errNilRequestBody = errors.New("request body is nil")
 
 func WriteError(w http.ResponseWriter, code int32, detail string) {
 	err := discovery.NewError(code, detail)
+	WriteErrsvcError(w, err)
+}
+
+func WriteErrsvcError(w http.ResponseWriter, err *errsvc.Error) {
 	w.Header().Set(HeaderContentType, ContentTypeJSON)
 	w.WriteHeader(err.StatusCode())
 	b, _ := json.Marshal(err)
diff --git a/server/handler/auth/auth.go b/server/handler/auth/auth.go
index 641124b..9e693e4 100644
--- a/server/handler/auth/auth.go
+++ b/server/handler/auth/auth.go
@@ -18,6 +18,7 @@
 package auth
 
 import (
+	"github.com/go-chassis/cari/pkg/errsvc"
 	"net/http"
 
 	"github.com/apache/servicecomb-service-center/pkg/chain"
@@ -45,6 +46,10 @@ func (h *Handler) Handle(i *chain.Invocation) {
 
 	if err := auth.Identify(r); err != nil {
 		log.Errorf(err, "authenticate request failed, %s %s", r.Method, r.RequestURI)
+		if e, ok := err.(*errsvc.Error); ok {
+			i.Fail(e)
+			return
+		}
 		i.Fail(discovery.NewError(rbac.ErrUnauthorized, err.Error()))
 		return
 	}
diff --git a/server/plugin/auth/buildin/buidlin_test.go b/server/plugin/auth/buildin/buidlin_test.go
index f337682..17b7354 100644
--- a/server/plugin/auth/buildin/buidlin_test.go
+++ b/server/plugin/auth/buildin/buidlin_test.go
@@ -22,7 +22,8 @@ import (
 	"context"
 	"github.com/apache/servicecomb-service-center/pkg/rest"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	rbacmodel "github.com/go-chassis/cari/rbac"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"github.com/go-chassis/cari/rbac"
 	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
@@ -30,8 +31,7 @@ import (
 
 	"github.com/apache/servicecomb-service-center/server/config"
 	"github.com/apache/servicecomb-service-center/server/plugin/auth/buildin"
-	"github.com/apache/servicecomb-service-center/server/service/rbac"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
+	rbacsvc "github.com/apache/servicecomb-service-center/server/service/rbac"
 	_ "github.com/apache/servicecomb-service-center/test"
 	"github.com/astaxie/beego"
 	carirbac "github.com/go-chassis/cari/rbac"
@@ -51,8 +51,8 @@ func init() {
 }
 
 func TestTokenAuthenticator_Identify(t *testing.T) {
-	dao.DeleteAccount(context.TODO(), "root")
-	dao.DeleteAccount(context.TODO(), "non-admin")
+	rbacsvc.DeleteAccount(context.TODO(), "root")
+	rbacsvc.DeleteAccount(context.TODO(), "non-admin")
 	t.Run("init rbac", func(t *testing.T) {
 		err := archaius.Init(archaius.WithMemorySource(), archaius.WithENVSource())
 		assert.NoError(t, err)
@@ -67,9 +67,9 @@ func TestTokenAuthenticator_Identify(t *testing.T) {
 		err = ioutil.WriteFile("./rbac.pub", b, 0600)
 		assert.NoError(t, err)
 
-		archaius.Set(rbac.InitPassword, "Complicated_password1")
+		archaius.Set(rbacsvc.InitPassword, "Complicated_password1")
 
-		rbac.Init()
+		rbacsvc.Init()
 	})
 	a := buildin.New()
 	ta := a.(*buildin.TokenAuthenticator)
@@ -77,8 +77,10 @@ func TestTokenAuthenticator_Identify(t *testing.T) {
 	t.Run("without auth header should failed", func(t *testing.T) {
 		r := httptest.NewRequest(http.MethodGet, "/any", nil)
 		err := ta.Identify(r)
+		assert.NotNil(t, err)
 		t.Log(err)
-		assert.Equal(t, carirbac.ErrNoHeader, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, carirbac.ErrNoAuthHeader, svcErr.Code)
 	})
 
 	t.Run("with wrong auth header should failed", func(t *testing.T) {
@@ -105,7 +107,12 @@ func TestTokenAuthenticator_Identify(t *testing.T) {
 		assert.NoError(t, err)
 	})
 	t.Run("valid normal token, should no be able to get account", func(t *testing.T) {
-		err := dao.CreateAccount(context.TODO(), &rbacmodel.Account{Name: "non-admin", Password: "Complicated_password1"})
+		a := &rbac.Account{
+			Name:     "non-admin",
+			Password: "Complicated_password1",
+			Roles:    []string{rbac.RoleDeveloper},
+		}
+		err := rbacsvc.CreateAccount(context.TODO(), a)
 		assert.NoError(t, err)
 		r := httptest.NewRequest(http.MethodGet, "/v4/accounts", nil)
 		to, err := authr.Login(context.TODO(), "non-admin", "Complicated_password1")
diff --git a/server/plugin/auth/buildin/buildin.go b/server/plugin/auth/buildin/buildin.go
index 1b19d33..ff00102 100644
--- a/server/plugin/auth/buildin/buildin.go
+++ b/server/plugin/auth/buildin/buildin.go
@@ -22,7 +22,6 @@ import (
 	"net/http"
 	"strings"
 
-	errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/plugin"
 	"github.com/apache/servicecomb-service-center/pkg/rest"
@@ -73,7 +72,7 @@ func (ba *TokenAuthenticator) Identify(req *http.Request) error {
 	}
 	account, err := rbac.GetAccount(m)
 	if err != nil {
-		log.Error("get account  failed", err)
+		log.Error("get account from token failed", err)
 		return err
 	}
 	util.SetRequestContext(req, rbacsvc.CtxRequestClaims, m)
@@ -84,7 +83,7 @@ func (ba *TokenAuthenticator) Identify(req *http.Request) error {
 
 	if len(account.Roles) == 0 {
 		log.Error("no role found in token", nil)
-		return errors.New(errorsEx.MsgNoPerm)
+		return errors.New("no role found in token")
 	}
 
 	project := req.URL.Query().Get(":project")
@@ -93,7 +92,7 @@ func (ba *TokenAuthenticator) Identify(req *http.Request) error {
 		return err
 	}
 	if !allow {
-		return errors.New(errorsEx.MsgNoPerm)
+		return rbac.NewError(rbac.ErrNoPermission, "")
 	}
 
 	util.SetRequestContext(req, authHandler.CtxResourceLabels, matchedLabels)
@@ -123,7 +122,7 @@ func filterRoles(roleList []string) (hasAdmin bool, normalRoles []string) {
 func (ba *TokenAuthenticator) VerifyToken(req *http.Request) (interface{}, error) {
 	v := req.Header.Get(restful.HeaderAuth)
 	if v == "" {
-		return nil, rbac.ErrNoHeader
+		return nil, rbac.NewError(rbac.ErrNoAuthHeader, "")
 	}
 	s := strings.Split(v, " ")
 	if len(s) != 2 {
diff --git a/server/resource/v4/auth_resource.go b/server/resource/v4/auth_resource.go
index 26c4372..1c92440 100644
--- a/server/resource/v4/auth_resource.go
+++ b/server/resource/v4/auth_resource.go
@@ -20,16 +20,15 @@ package v4
 import (
 	"encoding/json"
 	"fmt"
+	"github.com/go-chassis/cari/pkg/errsvc"
 	"io/ioutil"
 	"net/http"
 
-	"github.com/apache/servicecomb-service-center/datasource"
 	errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/rest"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	rbacsvc "github.com/apache/servicecomb-service-center/server/service/rbac"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
 	"github.com/apache/servicecomb-service-center/server/service/validator"
 
 	"github.com/go-chassis/cari/discovery"
@@ -63,27 +62,13 @@ func (ar *AuthResource) CreateAccount(w http.ResponseWriter, req *http.Request)
 	a := &rbac.Account{}
 	if err = json.Unmarshal(body, a); err != nil {
 		log.Error("json err", err)
-		rest.WriteError(w, discovery.ErrInvalidParams, errorsEx.MsgJSON)
-		return
-	}
-	err = validator.ValidateCreateAccount(a)
-	if err != nil {
-		rest.WriteError(w, discovery.ErrInvalidParams, err.Error())
-		return
-	}
-	err = a.Check()
-	if err != nil {
 		rest.WriteError(w, discovery.ErrInvalidParams, err.Error())
 		return
 	}
-	err = dao.CreateAccount(req.Context(), a)
+	err = rbacsvc.CreateAccount(req.Context(), a)
 	if err != nil {
-		if err == datasource.ErrAccountDuplicated {
-			rest.WriteError(w, rbac.ErrAccountConflict, "")
-			return
-		}
 		log.Error(errorsEx.MsgOperateAccountFailed, err)
-		rest.WriteError(w, discovery.ErrInternal, errorsEx.MsgOperateAccountFailed)
+		writeErrsvcOrInternalErr(w, err)
 		return
 	}
 	rest.WriteSuccess(w, req)
@@ -91,13 +76,10 @@ func (ar *AuthResource) CreateAccount(w http.ResponseWriter, req *http.Request)
 
 func (ar *AuthResource) DeleteAccount(w http.ResponseWriter, req *http.Request) {
 	name := req.URL.Query().Get(":name")
-	if ar.illegalCheck(w, req, name) {
-		return
-	}
-	_, err := dao.DeleteAccount(req.Context(), name)
+	err := rbacsvc.DeleteAccount(req.Context(), name)
 	if err != nil {
 		log.Error(errorsEx.MsgOperateAccountFailed, err)
-		rest.WriteError(w, discovery.ErrInternal, errorsEx.MsgOperateAccountFailed)
+		writeErrsvcOrInternalErr(w, err)
 		return
 	}
 	rest.WriteSuccess(w, req)
@@ -105,9 +87,6 @@ func (ar *AuthResource) DeleteAccount(w http.ResponseWriter, req *http.Request)
 
 func (ar *AuthResource) UpdateAccount(w http.ResponseWriter, req *http.Request) {
 	name := req.URL.Query().Get(":name")
-	if ar.illegalCheck(w, req, name) {
-		return
-	}
 	body, err := ioutil.ReadAll(req.Body)
 	if err != nil {
 		log.Error("read body err", err)
@@ -121,17 +100,17 @@ func (ar *AuthResource) UpdateAccount(w http.ResponseWriter, req *http.Request)
 		return
 	}
 
-	err = dao.UpdateAccount(req.Context(), name, a)
+	err = rbacsvc.UpdateAccount(req.Context(), name, a)
 	if err != nil {
 		log.Error(errorsEx.MsgOperateAccountFailed, err)
-		rest.WriteError(w, discovery.ErrInternal, errorsEx.MsgOperateAccountFailed)
+		writeErrsvcOrInternalErr(w, err)
 		return
 	}
 	rest.WriteSuccess(w, req)
 }
 
 func (ar *AuthResource) ListAccount(w http.ResponseWriter, r *http.Request) {
-	as, n, err := dao.ListAccount(r.Context())
+	as, n, err := rbacsvc.ListAccount(r.Context())
 	if err != nil {
 		log.Error(errorsEx.MsgGetAccountFailed, err)
 		rest.WriteError(w, discovery.ErrInternal, errorsEx.MsgGetAccountFailed)
@@ -145,29 +124,16 @@ func (ar *AuthResource) ListAccount(w http.ResponseWriter, r *http.Request) {
 }
 
 func (ar *AuthResource) GetAccount(w http.ResponseWriter, r *http.Request) {
-	a, err := dao.GetAccount(r.Context(), r.URL.Query().Get(":name"))
+	a, err := rbacsvc.GetAccount(r.Context(), r.URL.Query().Get(":name"))
 	if err != nil {
 		log.Error(errorsEx.MsgGetAccountFailed, err)
-		rest.WriteError(w, discovery.ErrInternal, errorsEx.MsgGetAccountFailed)
+		writeErrsvcOrInternalErr(w, err)
 		return
 	}
 	a.Password = ""
 	rest.WriteResponse(w, r, nil, a)
 }
 
-func (ar *AuthResource) illegalCheck(w http.ResponseWriter, req *http.Request, name string) bool {
-	if name == rbacsvc.RootName {
-		rest.WriteError(w, discovery.ErrInvalidParams, errorsEx.MsgCantOperateRoot)
-		return true
-	}
-	user := rbacsvc.UserFromContext(req.Context())
-	if name == user {
-		rest.WriteError(w, discovery.ErrInvalidParams, errorsEx.MsgCantOperateYour)
-		return true
-	}
-	return false
-}
-
 func (ar *AuthResource) ChangePassword(w http.ResponseWriter, req *http.Request) {
 	name := req.URL.Query().Get(":name")
 	ip := util.GetRealIP(req)
@@ -253,7 +219,7 @@ func (ar *AuthResource) Login(w http.ResponseWriter, r *http.Request) {
 		if err == rbacsvc.ErrUnauthorized {
 			log.Error("not authorized", err)
 			rbacsvc.CountFailure(MakeBanKey(a.Name, ip))
-			rest.WriteError(w, rbac.ErrUnauthorized, err.Error())
+			rest.WriteError(w, rbac.ErrUserOrPwdWrong, err.Error())
 			return
 		}
 		log.Error("can not sign token", err)
@@ -266,3 +232,12 @@ func (ar *AuthResource) Login(w http.ResponseWriter, r *http.Request) {
 func MakeBanKey(name, ip string) string {
 	return name + "::" + ip
 }
+
+func writeErrsvcOrInternalErr(w http.ResponseWriter, err error) {
+	e, ok := err.(*errsvc.Error)
+	if ok {
+		rest.WriteErrsvcError(w, e)
+		return
+	}
+	rest.WriteError(w, discovery.ErrInternal, err.Error())
+}
diff --git a/server/resource/v4/auth_resource_test.go b/server/resource/v4/auth_resource_test.go
index 6e0e233..38c1d7f 100644
--- a/server/resource/v4/auth_resource_test.go
+++ b/server/resource/v4/auth_resource_test.go
@@ -32,8 +32,7 @@ import (
 	"github.com/apache/servicecomb-service-center/pkg/rest"
 	"github.com/apache/servicecomb-service-center/server/config"
 	v4 "github.com/apache/servicecomb-service-center/server/resource/v4"
-	"github.com/apache/servicecomb-service-center/server/service/rbac"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
+	rbacsvc "github.com/apache/servicecomb-service-center/server/service/rbac"
 	_ "github.com/apache/servicecomb-service-center/test"
 	"github.com/astaxie/beego"
 	"github.com/go-chassis/go-archaius"
@@ -71,18 +70,18 @@ func init() {
 		panic(err)
 	}
 
-	archaius.Set(rbac.InitPassword, pwd)
+	archaius.Set(rbacsvc.InitPassword, pwd)
 	ctx := context.TODO()
-	dao.DeleteAccount(ctx, "root")
+	rbacsvc.DeleteAccount(ctx, "root")
 
-	rbac.Init()
+	rbacsvc.Init()
 	rest.RegisterServant(&v4.AuthResource{})
 	rest.RegisterServant(&v4.RoleResource{})
 }
 func TestAuthResource_Login(t *testing.T) {
 	ctx := context.TODO()
 
-	dao.DeleteAccount(ctx, "dev_account")
+	rbacsvc.DeleteAccount(ctx, "dev_account")
 
 	t.Run("invalid user login", func(t *testing.T) {
 		b, _ := json.Marshal(&rbacmodel.Account{Name: "dev_account", Password: pwd})
@@ -190,7 +189,7 @@ func TestAuthResource_DeleteAccount(t *testing.T) {
 		r2.Header.Set(restful.HeaderAuth, "Bearer "+rootToken.TokenStr)
 		w2 := httptest.NewRecorder()
 		rest.GetRouter().ServeHTTP(w2, r2)
-		assert.Equal(t, http.StatusBadRequest, w2.Code)
+		assert.Equal(t, http.StatusForbidden, w2.Code)
 	})
 	t.Run("dev_account can not even delete him self", func(t *testing.T) {
 		b, _ := json.Marshal(&rbacmodel.Account{Name: "dev_account", Password: "Complicated_password2", Roles: []string{"developer"}})
@@ -232,7 +231,7 @@ func TestAuthResource_DeleteAccount(t *testing.T) {
 		r2.Header.Set(restful.HeaderAuth, "Bearer "+yourToken.TokenStr)
 		w2 := httptest.NewRecorder()
 		rest.GetRouter().ServeHTTP(w2, r2)
-		assert.Equal(t, http.StatusBadRequest, w2.Code)
+		assert.Equal(t, http.StatusForbidden, w2.Code)
 
 		r3, _ := http.NewRequest(http.MethodDelete, "/v4/accounts/your_account", nil)
 		r3.Header.Set(restful.HeaderAuth, "Bearer "+rootToken.TokenStr)
diff --git a/server/resource/v4/role_resource.go b/server/resource/v4/role_resource.go
index 17e363b..a2debe8 100644
--- a/server/resource/v4/role_resource.go
+++ b/server/resource/v4/role_resource.go
@@ -21,13 +21,13 @@ import (
 	"encoding/json"
 	"errors"
 	"github.com/apache/servicecomb-service-center/datasource"
+	rbacsvc "github.com/apache/servicecomb-service-center/server/service/rbac"
 	"io/ioutil"
 	"net/http"
 
 	errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/rest"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
 
 	"github.com/go-chassis/cari/discovery"
 	"github.com/go-chassis/cari/rbac"
@@ -51,7 +51,7 @@ func (rr *RoleResource) URLPatterns() []rest.Route {
 
 //ListRoles list all roles and there's permissions
 func (rr *RoleResource) ListRoles(w http.ResponseWriter, req *http.Request) {
-	rs, num, err := dao.ListRole(req.Context())
+	rs, num, err := rbacsvc.ListRole(req.Context())
 	if err != nil {
 		log.Error(errorsEx.MsgGetRoleFailed, err)
 		rest.WriteError(w, discovery.ErrInternal, errorsEx.MsgGetRoleFailed)
@@ -90,7 +90,7 @@ func (rr *RoleResource) CreateRole(w http.ResponseWriter, req *http.Request) {
 		return
 	}
 
-	status, err := dao.CreateRole(req.Context(), role)
+	status, err := rbacsvc.CreateRole(req.Context(), role)
 	if err != nil {
 		log.Error(errorsEx.MsgOperateRoleFailed, err)
 		rest.WriteError(w, discovery.ErrInternal, err.Error())
@@ -113,7 +113,7 @@ func (rr *RoleResource) UpdateRole(w http.ResponseWriter, req *http.Request) {
 		rest.WriteError(w, discovery.ErrInvalidParams, errorsEx.MsgJSON)
 		return
 	}
-	status, err := dao.EditRole(req.Context(), name, role)
+	status, err := rbacsvc.EditRole(req.Context(), name, role)
 	if err != nil {
 		log.Error(errorsEx.MsgOperateRoleFailed, err)
 		rest.WriteError(w, discovery.ErrInternal, errorsEx.MsgOperateRoleFailed)
@@ -125,7 +125,7 @@ func (rr *RoleResource) UpdateRole(w http.ResponseWriter, req *http.Request) {
 
 //GetRole get the role info according to role name
 func (rr *RoleResource) GetRole(w http.ResponseWriter, r *http.Request) {
-	resp, status, err := dao.GetRole(r.Context(), r.URL.Query().Get(":roleName"))
+	resp, status, err := rbacsvc.GetRole(r.Context(), r.URL.Query().Get(":roleName"))
 	if err != nil {
 		log.Error(errorsEx.MsgGetRoleFailed, err)
 		rest.WriteError(w, discovery.ErrInternal, errorsEx.MsgGetRoleFailed)
@@ -139,7 +139,7 @@ func (rr *RoleResource) GetRole(w http.ResponseWriter, r *http.Request) {
 func (rr *RoleResource) DeleteRole(w http.ResponseWriter, req *http.Request) {
 	n := req.URL.Query().Get(":roleName")
 
-	status, err := dao.DeleteRole(req.Context(), n)
+	status, err := rbacsvc.DeleteRole(req.Context(), n)
 	if errors.Is(err, datasource.ErrRoleBindingExist) {
 		rest.WriteError(w, discovery.ErrInvalidParams, errorsEx.MsgJSON)
 		return
diff --git a/server/resource/v4/role_resource_test.go b/server/resource/v4/role_resource_test.go
index 4598496..6ac0e36 100644
--- a/server/resource/v4/role_resource_test.go
+++ b/server/resource/v4/role_resource_test.go
@@ -1,14 +1,15 @@
 package v4_test
 
 import (
+	rbacsvc "github.com/apache/servicecomb-service-center/server/service/rbac"
 	_ "github.com/apache/servicecomb-service-center/test"
+	"github.com/go-chassis/cari/rbac"
 	"strings"
 
 	"bytes"
 	"context"
 	"encoding/json"
 	"github.com/apache/servicecomb-service-center/pkg/rest"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
 	rbacmodel "github.com/go-chassis/cari/rbac"
 	"github.com/go-chassis/go-chassis/v2/server/restful"
 	"github.com/stretchr/testify/assert"
@@ -17,12 +18,46 @@ import (
 	"testing"
 )
 
+func newRole(name string) *rbac.Role {
+	return &rbac.Role{
+		Name: name,
+		Perms: []*rbac.Permission{
+			{
+				Resources: []*rbac.Resource{
+					{
+						Type: rbacsvc.ResourceService,
+					},
+				},
+				Verbs: []string{"*"},
+			},
+		},
+	}
+}
+
+const (
+	testPwd0 = "Ab@00000"
+	testPwd1 = "Ab@11111"
+)
+
+func newAccount(name string) *rbac.Account {
+	return &rbac.Account{
+		Name:     name,
+		Password: testPwd0,
+		Roles:    []string{rbac.RoleAdmin},
+		Status:   "active",
+	}
+}
+
 func TestRoleResource_CreateOrUpdateRole(t *testing.T) {
 	var superToken = &rbacmodel.Token{}
 	ctx := context.TODO()
-	dao.DeleteAccount(ctx, "dev_test")
-	dao.DeleteAccount(ctx, "dev_test2")
-	dao.DeleteRole(ctx, "tester")
+	rbacsvc.DeleteAccount(ctx, "dev_test")
+	rbacsvc.DeleteAccount(ctx, "dev_test2")
+	rbacsvc.DeleteRole(ctx, "tester")
+	devAccount := newAccount("dev_test")
+	testRole := newRole("tester")
+	rbacsvc.DeleteAccount(ctx, devAccount.Name)
+	rbacsvc.DeleteRole(ctx, testRole.Name)
 	t.Run("root login,to get super token", func(t *testing.T) {
 		b, _ := json.Marshal(&rbacmodel.Account{Name: "root", Password: "Complicated_password1"})
 
@@ -34,18 +69,8 @@ func TestRoleResource_CreateOrUpdateRole(t *testing.T) {
 		json.Unmarshal(w.Body.Bytes(), superToken)
 	})
 
-	t.Run("create account dev_test and add a role", func(t *testing.T) {
-		b, _ := json.Marshal(&rbacmodel.Account{Name: "dev_test", Password: "Complicated_password3", Roles: []string{"tester"}})
-
-		r, _ := http.NewRequest(http.MethodPost, "/v4/accounts", bytes.NewBuffer(b))
-		r.Header.Set(restful.HeaderAuth, "Bearer "+superToken.TokenStr)
-		w := httptest.NewRecorder()
-		rest.GetRouter().ServeHTTP(w, r)
-		assert.Equal(t, http.StatusOK, w.Code)
-	})
-
 	t.Run("create a role name tester ", func(t *testing.T) {
-		b, _ := json.Marshal(&rbacmodel.Account{Name: "dev_test", Password: "Complicated_password3", Roles: []string{"tester"}})
+		b, _ := json.Marshal(&rbacmodel.Account{Name: rbacsvc.RootName, Password: "Complicated_password1"})
 
 		r, _ := http.NewRequest(http.MethodPost, "/v4/token", bytes.NewBuffer(b))
 		w := httptest.NewRecorder()
@@ -54,15 +79,7 @@ func TestRoleResource_CreateOrUpdateRole(t *testing.T) {
 		devToken := &rbacmodel.Token{}
 		json.Unmarshal(w.Body.Bytes(), devToken)
 
-		b2, _ := json.Marshal(&rbacmodel.Role{
-			Name: "tester",
-			Perms: []*rbacmodel.Permission{
-				{
-					Resources: []*rbacmodel.Resource{{Type: "service"}, {Type: "instance"}},
-					Verbs:     []string{"get", "create", "update"},
-				},
-			},
-		})
+		b2, _ := json.Marshal(testRole)
 
 		r2, _ := http.NewRequest(http.MethodPost, "/v4/roles", bytes.NewReader(b2))
 		r2.Header.Set(restful.HeaderAuth, "Bearer "+superToken.TokenStr)
@@ -76,21 +93,30 @@ func TestRoleResource_CreateOrUpdateRole(t *testing.T) {
 		rest.GetRouter().ServeHTTP(w3, r3)
 		assert.Equal(t, http.StatusOK, w3.Code)
 
-		b4, _ := json.Marshal(&rbacmodel.Role{
-			Name: "tester",
-			Perms: []*rbacmodel.Permission{
-				{
-					Resources: []*rbacmodel.Resource{{Type: "service"}},
-					Verbs:     []string{"get", "create", "update"},
-				},
+		newTestRole := newRole(testRole.Name)
+		newTestRole.Perms = []*rbac.Permission{
+			{
+				Resources: []*rbacmodel.Resource{{Type: rbacsvc.ResourceAccount}},
+				Verbs:     []string{"*"},
 			},
-		})
+		}
+		b4, _ := json.Marshal(newTestRole)
 		r4, _ := http.NewRequest(http.MethodPut, "/v4/roles/tester", bytes.NewReader(b4))
 		r4.Header.Set(restful.HeaderAuth, "Bearer "+superToken.TokenStr)
 		w4 := httptest.NewRecorder()
 		rest.GetRouter().ServeHTTP(w4, r4)
 		assert.Equal(t, http.StatusOK, w4.Code)
 	})
+	t.Run("create account dev_test and add a role", func(t *testing.T) {
+		devAccount.Roles = []string{testRole.Name}
+		b, _ := json.Marshal(devAccount)
+
+		r, _ := http.NewRequest(http.MethodPost, "/v4/accounts", bytes.NewBuffer(b))
+		r.Header.Set(restful.HeaderAuth, "Bearer "+superToken.TokenStr)
+		w := httptest.NewRecorder()
+		rest.GetRouter().ServeHTTP(w, r)
+		assert.Equal(t, http.StatusOK, w.Code)
+	})
 
 	t.Run("get role", func(t *testing.T) {
 		b, _ := json.Marshal(&rbacmodel.Account{Name: "root", Password: "Complicated_password1"})
@@ -150,10 +176,10 @@ func TestRoleResource_CreateOrUpdateRole(t *testing.T) {
 func TestRoleResource_MoreRoles(t *testing.T) {
 	var to = &rbacmodel.Token{}
 	ctx := context.TODO()
-	dao.DeleteAccount(ctx, "dev_test")
-	dao.DeleteAccount(ctx, "dev_test2")
-	dao.DeleteRole(ctx, "tester")
-	dao.DeleteRole(ctx, "tester2")
+	rbacsvc.DeleteAccount(ctx, "dev_test")
+	rbacsvc.DeleteAccount(ctx, "dev_test2")
+	rbacsvc.DeleteRole(ctx, "tester")
+	rbacsvc.DeleteRole(ctx, "tester2")
 	t.Run("root login", func(t *testing.T) {
 		b, _ := json.Marshal(&rbacmodel.Account{Name: "root", Password: "Complicated_password1"})
 
diff --git a/server/service/rbac/account_dao.go b/server/service/rbac/account_dao.go
new file mode 100644
index 0000000..73ae9d1
--- /dev/null
+++ b/server/service/rbac/account_dao.go
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//Package rbac is dao layer API to help service center manage account, policy and role info
+package rbac
+
+import (
+	"context"
+	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource"
+	errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	"github.com/apache/servicecomb-service-center/pkg/util"
+	"github.com/apache/servicecomb-service-center/server/plugin/quota"
+	"github.com/apache/servicecomb-service-center/server/service/validator"
+	"github.com/go-chassis/cari/discovery"
+	"github.com/go-chassis/cari/rbac"
+)
+
+//CreateAccount save 2 kv
+//1. account info
+func CreateAccount(ctx context.Context, a *rbac.Account) error {
+	quotaCheckErr := quota.Apply(ctx, quota.NewApplyQuotaResource(quota.TypeAccount,
+		util.ParseDomainProject(ctx), "", 1))
+	if quotaCheckErr != nil {
+		return quotaCheckErr
+	}
+	err := validator.ValidateCreateAccount(a)
+	if err != nil {
+		log.Errorf(err, "create account [%s] failed", a.Name)
+		return rbac.NewError(discovery.ErrInvalidParams, err.Error())
+	}
+	err = a.Check()
+	if err != nil {
+		log.Errorf(err, "create account [%s] failed", a.Name)
+		return rbac.NewError(discovery.ErrInvalidParams, err.Error())
+	}
+	if err = checkRoleNames(ctx, a.Roles); err != nil {
+		return rbac.NewError(rbac.ErrAccountHasInvalidRole, err.Error())
+	}
+
+	err = datasource.Instance().CreateAccount(ctx, a)
+	if err == nil {
+		log.Infof("create account [%s] success", a.Name)
+		return nil
+	}
+	log.Errorf(err, "create account [%s] failed", a.Name)
+	if err == datasource.ErrAccountDuplicated {
+		return rbac.NewError(rbac.ErrAccountConflict, err.Error())
+	}
+	return err
+}
+
+// UpdateAccount updates an account's info, except the password
+func UpdateAccount(ctx context.Context, name string, a *rbac.Account) error {
+	// todo params validation
+	if err := illegalCheck(ctx, name); err != nil {
+		return err
+	}
+	if len(a.Status) == 0 && len(a.Roles) == 0 {
+		return rbac.NewError(discovery.ErrInvalidParams, "status and roles cannot be empty both")
+	}
+
+	oldAccount, err := GetAccount(ctx, name)
+	if err != nil {
+		log.Errorf(err, "get account [%s] failed", name)
+		return err
+	}
+	if len(a.Status) != 0 {
+		oldAccount.Status = a.Status
+	}
+	if len(a.Roles) != 0 {
+		oldAccount.Roles = a.Roles
+	}
+	if err = checkRoleNames(ctx, oldAccount.Roles); err != nil {
+		return rbac.NewError(rbac.ErrAccountHasInvalidRole, err.Error())
+	}
+	err = datasource.Instance().UpdateAccount(ctx, name, oldAccount)
+	if err != nil {
+		log.Errorf(err, "can not edit account info")
+		return err
+	}
+	log.Infof("account [%s] is edit", oldAccount.ID)
+	return nil
+}
+
+func GetAccount(ctx context.Context, name string) (*rbac.Account, error) {
+	r, err := datasource.Instance().GetAccount(ctx, name)
+	if err != nil {
+		if err == datasource.ErrAccountNotExist {
+			msg := fmt.Sprintf("account [%s] not exist", name)
+			return nil, rbac.NewError(rbac.ErrAccountNotExist, msg)
+		}
+		return nil, err
+	}
+	return r, nil
+}
+func ListAccount(ctx context.Context) ([]*rbac.Account, int64, error) {
+	return datasource.Instance().ListAccount(ctx)
+}
+func AccountExist(ctx context.Context, name string) (bool, error) {
+	return datasource.Instance().AccountExist(ctx, name)
+}
+func DeleteAccount(ctx context.Context, name string) error {
+	if err := illegalCheck(ctx, name); err != nil {
+		return err
+	}
+	exist, err := datasource.Instance().AccountExist(ctx, name)
+	if err != nil {
+		log.Errorf(err, "check account [%s] exit failed", name)
+		return err
+	}
+	if !exist {
+		msg := fmt.Sprintf("account [%s] not exist", name)
+		return rbac.NewError(rbac.ErrAccountNotExist, msg)
+	}
+	_, err = datasource.Instance().DeleteAccount(ctx, []string{name})
+	return err
+}
+
+//CreateAccount save 2 kv
+//1. account info
+func EditAccount(ctx context.Context, a *rbac.Account) error {
+	exist, err := datasource.Instance().AccountExist(ctx, a.Name)
+	if err != nil {
+		log.Errorf(err, "can not edit account info")
+		return err
+	}
+	if !exist {
+		return rbac.NewError(rbac.ErrAccountNotExist, "")
+	}
+
+	err = datasource.Instance().UpdateAccount(ctx, a.Name, a)
+	if err != nil {
+		log.Errorf(err, "can not edit account info")
+		return err
+	}
+	log.Infof("account [%s] is edit", a.ID)
+	return nil
+}
+
+func checkRoleNames(ctx context.Context, roles []string) error {
+	for _, name := range roles {
+		exist, err := RoleExist(ctx, name)
+		if err != nil {
+			log.Errorf(err, "check role [%s] exist failed", name)
+			return err
+		}
+		if !exist {
+			return datasource.ErrRoleNotExist
+		}
+	}
+	return nil
+}
+
+func illegalCheck(ctx context.Context, target string) error {
+	if target == RootName {
+		return discovery.NewError(discovery.ErrForbidden, errorsEx.MsgCantOperateRoot)
+	}
+	changer := UserFromContext(ctx)
+	if target == changer {
+		return discovery.NewError(discovery.ErrForbidden, errorsEx.MsgCantOperateYour)
+	}
+	return nil
+}
diff --git a/server/service/rbac/account_dao_test.go b/server/service/rbac/account_dao_test.go
new file mode 100644
index 0000000..546c307
--- /dev/null
+++ b/server/service/rbac/account_dao_test.go
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package rbac_test
+
+// initialize
+import (
+	"context"
+	rbacsvc "github.com/apache/servicecomb-service-center/server/service/rbac"
+	"github.com/go-chassis/cari/discovery"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"testing"
+
+	_ "github.com/apache/servicecomb-service-center/test"
+
+	"github.com/astaxie/beego"
+	"github.com/go-chassis/cari/rbac"
+	"github.com/stretchr/testify/assert"
+)
+
+func init() {
+	beego.AppConfig.Set("registry_plugin", "etcd")
+}
+
+const (
+	testPwd0 = "Ab@00000"
+	testPwd1 = "Ab@11111"
+)
+
+func newAccount(name string) *rbac.Account {
+	return &rbac.Account{
+		Name:     name,
+		Password: testPwd0,
+		Roles:    []string{rbac.RoleAdmin},
+		Status:   "active",
+	}
+}
+
+func TestCreateAccount(t *testing.T) {
+	t.Run("create account, should succeed", func(t *testing.T) {
+		a := newAccount("TestCreateAccount_create_account")
+		err := rbacsvc.CreateAccount(context.TODO(), a)
+		assert.Nil(t, err)
+	})
+	t.Run("create account twice, should return: "+rbac.NewError(rbac.ErrAccountConflict, "").Error(), func(t *testing.T) {
+		name := "TestCreateAccount_create_account_twice"
+		a := newAccount(name)
+		err := rbacsvc.CreateAccount(context.TODO(), a)
+		assert.Nil(t, err)
+
+		a = newAccount(name)
+		err = rbacsvc.CreateAccount(context.TODO(), a)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, rbac.ErrAccountConflict, svcErr.Code)
+	})
+	t.Run("account has invalid role, should return: "+rbac.NewError(rbac.ErrAccountHasInvalidRole, "").Error(), func(t *testing.T) {
+		a := newAccount("TestCreateAccount_account_has_invalid_role")
+		a.Roles = append(a.Roles, "invalid_role")
+		err := rbacsvc.CreateAccount(context.TODO(), a)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, rbac.ErrAccountHasInvalidRole, svcErr.Code)
+	})
+}
+
+func TestDeleteAccount(t *testing.T) {
+	t.Run("delete account, should succeed", func(t *testing.T) {
+		a := newAccount("TestDeleteAccount_delete_account")
+		err := rbacsvc.CreateAccount(context.TODO(), a)
+		assert.Nil(t, err)
+
+		exist, err := rbacsvc.AccountExist(context.TODO(), a.Name)
+		assert.Nil(t, err)
+		assert.True(t, exist)
+		err = rbacsvc.DeleteAccount(context.TODO(), a.Name)
+		assert.Nil(t, err)
+		exist, err = rbacsvc.AccountExist(context.TODO(), a.Name)
+		assert.Nil(t, err)
+		assert.False(t, exist)
+	})
+	t.Run("delete no exist account, should return: "+rbac.NewError(rbac.ErrAccountNotExist, "").Error(), func(t *testing.T) {
+		err := rbacsvc.DeleteAccount(context.TODO(), "TestDeleteAccount_delete_no_exist_account")
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, rbac.ErrAccountNotExist, svcErr.Code)
+	})
+	t.Run("delete root, should return: "+rbac.NewError(discovery.ErrForbidden, "").Error(), func(t *testing.T) {
+		err := rbacsvc.DeleteAccount(context.TODO(), "root")
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, discovery.ErrForbidden, svcErr.Code)
+	})
+	t.Run("delete self, should return: "+rbac.NewError(discovery.ErrForbidden, "").Error(), func(t *testing.T) {
+		a := newAccount("TestDeleteAccount_delete_self")
+		err := rbacsvc.CreateAccount(context.TODO(), a)
+		assert.Nil(t, err)
+		claims := map[string]interface{}{
+			rbac.ClaimsUser: a.Name,
+		}
+		ctx := context.WithValue(context.TODO(), rbacsvc.CtxRequestClaims, claims)
+		err = rbacsvc.DeleteAccount(ctx, a.Name)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, discovery.ErrForbidden, svcErr.Code)
+	})
+}
+
+func TestUpdateAccount(t *testing.T) {
+	t.Run("update account, should succeed", func(t *testing.T) {
+		name := "TestUpdateAccount_update_account"
+		a := newAccount(name)
+		err := rbacsvc.CreateAccount(context.TODO(), a)
+		assert.Nil(t, err)
+
+		a = newAccount(name)
+		a.Roles = []string{rbac.RoleAdmin, rbac.RoleDeveloper}
+		err = rbacsvc.UpdateAccount(context.TODO(), a.Name, a)
+		assert.Nil(t, err)
+		resp, err := rbacsvc.GetAccount(context.TODO(), a.Name)
+		assert.Nil(t, err)
+		assert.Equal(t, 2, len(resp.Roles))
+	})
+	t.Run("update no exist account, should return: "+rbac.NewError(rbac.ErrAccountNotExist, "").Error(), func(t *testing.T) {
+		name := "TestUpdateAccount_update_no_exist_account"
+		a := newAccount(name)
+		err := rbacsvc.UpdateAccount(context.TODO(), a.Name, a)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, rbac.ErrAccountNotExist, svcErr.Code)
+	})
+	t.Run("update root, should return: "+discovery.NewError(discovery.ErrForbidden, "").Error(), func(t *testing.T) {
+		a := newAccount("root")
+		err := rbacsvc.UpdateAccount(context.TODO(), a.Name, a)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, discovery.ErrForbidden, svcErr.Code)
+	})
+	t.Run("account has invalid role, should return: "+rbac.NewError(rbac.ErrAccountHasInvalidRole, "").Error(), func(t *testing.T) {
+		name := "TestUpdateAccount_account_has_invalid_role"
+		a := newAccount(name)
+		err := rbacsvc.CreateAccount(context.TODO(), a)
+		assert.Nil(t, err)
+
+		a.Roles = append(a.Roles, "invalid_role")
+		err = rbacsvc.UpdateAccount(context.TODO(), a.Name, a)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, rbac.ErrAccountHasInvalidRole, svcErr.Code)
+	})
+	t.Run("roles status empty both, should return: "+discovery.NewError(discovery.ErrInvalidParams, "").Error(), func(t *testing.T) {
+		name := "TestUpdateAccount_roles_status_empty_both"
+		a := newAccount(name)
+		err := rbacsvc.CreateAccount(context.TODO(), a)
+		assert.Nil(t, err)
+
+		a = newAccount(name)
+		a.Roles = nil
+		a.Status = ""
+		err = rbacsvc.UpdateAccount(context.TODO(), a.Name, a)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, discovery.ErrInvalidParams, svcErr.Code)
+	})
+	t.Run("update self, should return: "+rbac.NewError(discovery.ErrForbidden, "").Error(), func(t *testing.T) {
+		name := "TestDeleteAccount_update_self"
+		a := newAccount(name)
+		err := rbacsvc.CreateAccount(context.TODO(), a)
+		assert.Nil(t, err)
+
+		a = newAccount(name)
+		claims := map[string]interface{}{
+			rbac.ClaimsUser: a.Name,
+		}
+		ctx := context.WithValue(context.TODO(), rbacsvc.CtxRequestClaims, claims)
+		err = rbacsvc.UpdateAccount(ctx, a.Name, a)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, discovery.ErrForbidden, svcErr.Code)
+	})
+}
+
+func TestEditAccount(t *testing.T) {
+	t.Run("edit no exist account, should return: "+rbac.NewError(rbac.ErrAccountNotExist, "").Error(), func(t *testing.T) {
+		a := newAccount("TestEditAccount_edit_no_exist_account")
+		err := rbacsvc.UpdateAccount(context.TODO(), a.Name, a)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, rbac.ErrAccountNotExist, svcErr.Code)
+	})
+}
+
+func TestGetAccount(t *testing.T) {
+	t.Run("get account, should succeed", func(t *testing.T) {
+		a, err := rbacsvc.GetAccount(context.TODO(), "root")
+		assert.Nil(t, err)
+		assert.Equal(t, "root", a.Name)
+	})
+	t.Run("get no exist account, should return: "+rbac.NewError(rbac.ErrAccountNotExist, "").Error(), func(t *testing.T) {
+		a, err := rbacsvc.GetAccount(context.TODO(), "TestGetAccount_no_exist_account")
+		assert.Nil(t, a)
+		assert.NotNil(t, err)
+		svcErr := err.(*errsvc.Error)
+		assert.Equal(t, rbac.ErrAccountNotExist, svcErr.Code)
+	})
+}
+func TestListAccount(t *testing.T) {
+	t.Run("list account, should succeed", func(t *testing.T) {
+		accounts, n, err := rbacsvc.ListAccount(context.TODO())
+		assert.Nil(t, err)
+		assert.True(t, n > 0)
+		assert.Equal(t, n, int64(len(accounts)))
+	})
+}
diff --git a/server/service/rbac/authr_plugin.go b/server/service/rbac/authr_plugin.go
index 00008bc..b6a4615 100644
--- a/server/service/rbac/authr_plugin.go
+++ b/server/service/rbac/authr_plugin.go
@@ -21,6 +21,7 @@ import (
 	"context"
 	"crypto/rsa"
 	"errors"
+	"fmt"
 	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/go-chassis/cari/rbac"
 
@@ -30,7 +31,6 @@ import (
 
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/privacy"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
 )
 
 var ErrUnauthorized = errors.New("wrong user name or password")
@@ -49,11 +49,12 @@ func (a *EmbeddedAuthenticator) Login(ctx context.Context, user string, password
 	for _, o := range opts {
 		o(opt)
 	}
-	account, err := dao.GetAccount(ctx, user)
+	account, err := GetAccount(ctx, user)
 	if err != nil {
 		log.Error("get account err", err)
 		return "", err
 	}
+
 	same := privacy.SamePassword(account.Password, password)
 	if user == account.Name && same {
 		secret, err := GetPrivateKey()
@@ -85,6 +86,9 @@ func (a *EmbeddedAuthenticator) Authenticate(ctx context.Context, tokenStr strin
 	}
 	claims, err := a.authToken(tokenStr, p)
 	if err != nil {
+		if a.isTokenExpiredError(err) {
+			return nil, rbac.NewError(rbac.ErrTokenExpired, "")
+		}
 		return nil, err
 	}
 	accountNameI := claims[rbac.ClaimsUser]
@@ -97,11 +101,26 @@ func (a *EmbeddedAuthenticator) Authenticate(ctx context.Context, tokenStr strin
 		return nil, err
 	}
 	if !exist {
-		return nil, datasource.ErrAccountNotExist
+		msg := fmt.Sprintf("account [%s] is deleted", n)
+		return nil, rbac.NewError(rbac.ErrTokenOwnedAccountDeleted, msg)
 	}
 	return claims, nil
 }
 
+func (a *EmbeddedAuthenticator) isTokenExpiredError(err error) bool {
+	if err == nil {
+		return false
+	}
+	vErr, ok := err.(*jwt.ValidationError)
+	if !ok {
+		return false
+	}
+	if vErr.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 {
+		return true
+	}
+	return false
+}
+
 func (a *EmbeddedAuthenticator) authToken(tokenStr string, pub *rsa.PublicKey) (map[string]interface{}, error) {
 	return token.Verify(tokenStr, func(claims interface{}, method token.SigningMethod) (interface{}, error) {
 		return pub, nil
diff --git a/server/service/rbac/dao/account_dao.go b/server/service/rbac/dao/account_dao.go
deleted file mode 100644
index fe7279b..0000000
--- a/server/service/rbac/dao/account_dao.go
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//Package rbac is dao layer API to help service center manage account, policy and role info
-package dao
-
-import (
-	"context"
-	"errors"
-	"github.com/apache/servicecomb-service-center/datasource"
-	"github.com/apache/servicecomb-service-center/pkg/log"
-	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/quota"
-
-	rbacmodel "github.com/go-chassis/cari/rbac"
-)
-
-//CreateAccount save 2 kv
-//1. account info
-func CreateAccount(ctx context.Context, a *rbacmodel.Account) error {
-	err := quota.Apply(ctx, quota.NewApplyQuotaResource(quota.TypeAccount,
-		util.ParseDomainProject(ctx), "", 1))
-	if err != nil {
-		return err
-	}
-	return datasource.Instance().CreateAccount(ctx, a)
-}
-
-// UpdateAccount updates an account's info, except the password
-func UpdateAccount(ctx context.Context, name string, a *rbacmodel.Account) error {
-	// todo params validation
-	if len(a.Status) == 0 && len(a.Roles) == 0 {
-		return errors.New("status and roles cannot be empty both")
-	}
-	exist, err := datasource.Instance().AccountExist(ctx, name)
-	if err != nil {
-		log.Errorf(err, "check account [%s] exit failed", name)
-		return err
-	}
-	if !exist {
-		return datasource.ErrAccountNotExist
-	}
-	oldAccount, err := GetAccount(ctx, name)
-	if err != nil {
-		log.Errorf(err, "get account [%s] failed", name)
-		return err
-	}
-	if len(a.Status) != 0 {
-		oldAccount.Status = a.Status
-	}
-	if len(a.Roles) != 0 {
-		oldAccount.Roles = a.Roles
-	}
-	err = datasource.Instance().UpdateAccount(ctx, name, oldAccount)
-	if err != nil {
-		log.Errorf(err, "can not edit account info")
-		return err
-	}
-	log.Infof("account [%s] is edit", oldAccount.ID)
-	return nil
-}
-
-func GetAccount(ctx context.Context, name string) (*rbacmodel.Account, error) {
-	return datasource.Instance().GetAccount(ctx, name)
-}
-func ListAccount(ctx context.Context) ([]*rbacmodel.Account, int64, error) {
-	return datasource.Instance().ListAccount(ctx)
-}
-func AccountExist(ctx context.Context, name string) (bool, error) {
-	return datasource.Instance().AccountExist(ctx, name)
-}
-func DeleteAccount(ctx context.Context, name string) (bool, error) {
-	return datasource.Instance().DeleteAccount(ctx, []string{name})
-}
-
-//CreateAccount save 2 kv
-//1. account info
-func EditAccount(ctx context.Context, a *rbacmodel.Account) error {
-	exist, err := datasource.Instance().AccountExist(ctx, a.Name)
-	if err != nil {
-		log.Errorf(err, "can not edit account info")
-		return err
-	}
-	if !exist {
-		return datasource.ErrAccountCanNotEdit
-	}
-
-	err = datasource.Instance().UpdateAccount(ctx, a.Name, a)
-	if err != nil {
-		log.Errorf(err, "can not edit account info")
-		return err
-	}
-	log.Infof("account [%s] is edit", a.ID)
-	return nil
-}
diff --git a/server/service/rbac/dao/account_dao_test.go b/server/service/rbac/dao/account_dao_test.go
deleted file mode 100644
index 79a48a3..0000000
--- a/server/service/rbac/dao/account_dao_test.go
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dao_test
-
-// initialize
-import (
-	"context"
-	"testing"
-
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
-	_ "github.com/apache/servicecomb-service-center/test"
-
-	"github.com/astaxie/beego"
-	"github.com/go-chassis/cari/rbac"
-	"github.com/stretchr/testify/assert"
-	"golang.org/x/crypto/bcrypt"
-)
-
-func init() {
-	beego.AppConfig.Set("registry_plugin", "etcd")
-}
-
-func newAccount(name string) *rbac.Account {
-	return &rbac.Account{
-		Name:     name,
-		Password: "Ab@11111",
-		Roles:    []string{rbac.RoleAdmin},
-	}
-}
-
-func TestAccountDao_CreateAccount(t *testing.T) {
-	account := newAccount("createAccountTest")
-	dao.DeleteAccount(context.TODO(), account.Name)
-	_ = dao.CreateAccount(context.Background(), account)
-	t.Run("get account", func(t *testing.T) {
-		r, err := dao.GetAccount(context.Background(), account.Name)
-		assert.NoError(t, err)
-		assert.Equal(t, account.Name, r.Name)
-		hash, err := bcrypt.GenerateFromPassword([]byte(account.Password), 14)
-		err = bcrypt.CompareHashAndPassword(hash, []byte(account.Password))
-		assert.NoError(t, err)
-	})
-}
-func TestAccountDao_UpdateAccount(t *testing.T) {
-	account := newAccount("updateAccountTest")
-	t.Run("update an none exist account", func(t *testing.T) {
-		newAccount := &rbac.Account{Roles: []string{"admin"}}
-		err := dao.UpdateAccount(context.Background(), "noExist", newAccount)
-		assert.Error(t, err)
-	})
-
-	dao.DeleteAccount(context.TODO(), account.Name)
-	err := dao.CreateAccount(context.Background(), account)
-	assert.NoError(t, err)
-
-	t.Run("update account", func(t *testing.T) {
-		newAccount := &rbac.Account{
-			Roles: []string{rbac.RoleDeveloper},
-		}
-		err = dao.UpdateAccount(context.Background(), account.Name, newAccount)
-		assert.NoError(t, err)
-		a, err := dao.GetAccount(context.Background(), account.Name)
-		assert.NoError(t, err)
-		assert.Equal(t, 1, len(a.Roles))
-		assert.Equal(t, rbac.RoleDeveloper, a.Roles[0])
-	})
-}
diff --git a/server/service/rbac/password.go b/server/service/rbac/password.go
index a8d5dd3..aaf4e21 100644
--- a/server/service/rbac/password.go
+++ b/server/service/rbac/password.go
@@ -27,7 +27,6 @@ import (
 	"golang.org/x/crypto/bcrypt"
 
 	"github.com/apache/servicecomb-service-center/pkg/log"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
 )
 
 func ChangePassword(ctx context.Context, changerRole []string, changerName string, a *rbacmodel.Account) error {
@@ -49,7 +48,7 @@ func ChangePassword(ctx context.Context, changerRole []string, changerName strin
 	return ErrNoPermChangeAccount
 }
 func changePasswordForcibly(ctx context.Context, name, pwd string) error {
-	old, err := dao.GetAccount(ctx, name)
+	old, err := GetAccount(ctx, name)
 	if err != nil {
 		log.Error("can not change pwd", err)
 		return err
@@ -64,7 +63,7 @@ func changePassword(ctx context.Context, name, currentPassword, pwd string) erro
 	if currentPassword == pwd {
 		return ErrSamePassword
 	}
-	old, err := dao.GetAccount(ctx, name)
+	old, err := GetAccount(ctx, name)
 	if err != nil {
 		log.Error("can not change pwd", err)
 		return err
@@ -88,7 +87,7 @@ func doChangePassword(ctx context.Context, old *rbacmodel.Account, pwd string) e
 		return err
 	}
 	old.Password = stringutil.Bytes2str(hash)
-	err = dao.EditAccount(ctx, old)
+	err = EditAccount(ctx, old)
 	if err != nil {
 		log.Error("can not change pwd", err)
 		return err
diff --git a/server/service/rbac/rbac.go b/server/service/rbac/rbac.go
index 4807a34..d72597c 100644
--- a/server/service/rbac/rbac.go
+++ b/server/service/rbac/rbac.go
@@ -21,8 +21,7 @@ import (
 	"context"
 	"crypto/rsa"
 	"errors"
-	"github.com/apache/servicecomb-service-center/datasource"
-	"github.com/apache/servicecomb-service-center/server/service/validator"
+	"github.com/go-chassis/cari/pkg/errsvc"
 	"io/ioutil"
 
 	"github.com/go-chassis/cari/rbac"
@@ -30,7 +29,6 @@ import (
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/server/config"
 	"github.com/apache/servicecomb-service-center/server/plugin/security/cipher"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
 	"github.com/go-chassis/go-archaius"
 	"github.com/go-chassis/go-chassis/v2/security/authr"
 	"github.com/go-chassis/go-chassis/v2/security/secret"
@@ -61,7 +59,9 @@ func Init() {
 	if err != nil {
 		log.Fatal("can not enable auth module", err)
 	}
-	accountExist, err := dao.AccountExist(context.Background(), RootName)
+	// role init before account
+	initBuildInRole()
+	accountExist, err := AccountExist(context.Background(), RootName)
 	if err != nil {
 		log.Fatal("can not enable auth module", err)
 	}
@@ -70,7 +70,6 @@ func Init() {
 	}
 	readPrivateKey()
 	readPublicKey()
-	initBuildInRole()
 	rbac.Add2WhiteAPIList(APITokenGranter)
 	log.Info("rbac is enabled")
 }
@@ -118,19 +117,17 @@ func initFirstTime(admin string) {
 		Password: pwd,
 		Roles:    []string{rbac.RoleAdmin},
 	}
-	err = validator.ValidateCreateAccount(a)
-	if err != nil {
-		log.Fatal("invalid pwd", err)
+	err = CreateAccount(context.Background(), a)
+	if err == nil {
+		log.Info("root account init success")
 		return
 	}
-	if err := dao.CreateAccount(context.Background(), a); err != nil {
-		if err == datasource.ErrAccountDuplicated {
-			log.Info("root account already exists")
-			return
-		}
-		log.Fatal("can not enable rbac, init root account failed", err)
+	svcErr, ok := err.(*errsvc.Error)
+	if ok && svcErr.Code == rbac.ErrAccountConflict {
+		log.Info("root account already exist")
+		return
 	}
-	log.Info("root account init success")
+	log.Fatal("can not enable rbac, init root account failed", err)
 }
 
 func getPassword() (string, error) {
diff --git a/server/service/rbac/rbac_test.go b/server/service/rbac/rbac_test.go
index 65ae32f..fd55df6 100644
--- a/server/service/rbac/rbac_test.go
+++ b/server/service/rbac/rbac_test.go
@@ -22,7 +22,6 @@ import (
 	"github.com/apache/servicecomb-service-center/pkg/privacy"
 	"github.com/apache/servicecomb-service-center/server/config"
 	rbacsvc "github.com/apache/servicecomb-service-center/server/service/rbac"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
 	_ "github.com/apache/servicecomb-service-center/test"
 	"github.com/astaxie/beego"
 	"github.com/go-chassis/cari/rbac"
@@ -62,18 +61,10 @@ func init() {
 	}
 
 	archaius.Set(rbacsvc.InitPassword, "Complicated_password1")
-	dao.DeleteAccount(context.Background(), "root")
-	dao.DeleteAccount(context.Background(), "a")
-	dao.DeleteAccount(context.Background(), "b")
-
 	rbacsvc.Init()
 }
 
 func TestInitRBAC(t *testing.T) {
-	a, err := dao.GetAccount(context.Background(), "root")
-	assert.NoError(t, err)
-	assert.Equal(t, "root", a.Name)
-
 	t.Run("login and authenticate", func(t *testing.T) {
 		token, err := authr.Login(context.Background(), "root", "Complicated_password1")
 		assert.NoError(t, err)
@@ -87,29 +78,24 @@ func TestInitRBAC(t *testing.T) {
 	})
 
 	t.Run("change pwd,admin can change any one password", func(t *testing.T) {
-		persisted := &rbac.Account{Name: "a", Password: "Complicated_password1"}
-		err := dao.CreateAccount(context.Background(), persisted)
+		persisted := newAccount("admin_change_other_pwd")
+		err := rbacsvc.CreateAccount(context.Background(), persisted)
 		assert.NoError(t, err)
-		err = rbacsvc.ChangePassword(context.Background(), []string{rbac.RoleAdmin}, "admin", &rbac.Account{Name: "a", Password: "Complicated_password2"})
+		err = rbacsvc.ChangePassword(context.Background(), []string{rbac.RoleAdmin}, rbac.RoleAdmin, &rbac.Account{Name: persisted.Name, Password: "Complicated_password2"})
 		assert.NoError(t, err)
-		a, err := dao.GetAccount(context.Background(), "a")
+		a, err := rbacsvc.GetAccount(context.Background(), persisted.Name)
 		assert.NoError(t, err)
 		assert.True(t, privacy.SamePassword(a.Password, "Complicated_password2"))
 	})
 	t.Run("change self password", func(t *testing.T) {
-		err := dao.CreateAccount(context.Background(), &rbac.Account{Name: "b", Password: "Complicated_password1"})
-		assert.NoError(t, err)
-		err = rbacsvc.ChangePassword(context.Background(), nil, "b", &rbac.Account{Name: "b", CurrentPassword: "Complicated_password1", Password: "Complicated_password2"})
+		a := newAccount("change_self_pwd")
+		err := rbacsvc.CreateAccount(context.Background(), a)
 		assert.NoError(t, err)
-		a, err := dao.GetAccount(context.Background(), "b")
+		err = rbacsvc.ChangePassword(context.Background(), nil, a.Name, &rbac.Account{Name: a.Name, CurrentPassword: testPwd0, Password: testPwd1})
 		assert.NoError(t, err)
-		assert.True(t, privacy.SamePassword(a.Password, "Complicated_password2"))
-
-	})
-	t.Run("list kv", func(t *testing.T) {
-		_, n, err := dao.ListAccount(context.TODO())
+		resp, err := rbacsvc.GetAccount(context.Background(), a.Name)
 		assert.NoError(t, err)
-		assert.Greater(t, n, int64(2))
+		assert.True(t, privacy.SamePassword(resp.Password, testPwd1))
 	})
 }
 func BenchmarkAuthResource_Login(b *testing.B) {
diff --git a/server/service/rbac/role.go b/server/service/rbac/role.go
index 1523579..8753706 100644
--- a/server/service/rbac/role.go
+++ b/server/service/rbac/role.go
@@ -22,7 +22,6 @@ import (
 	"github.com/go-chassis/cari/rbac"
 
 	"github.com/apache/servicecomb-service-center/pkg/log"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
 )
 
 var roleMap = map[string]*rbac.Role{}
@@ -46,7 +45,7 @@ func initBuildInRole() {
 }
 
 func createBuildInRole(r *rbac.Role) {
-	status, err := dao.CreateRole(context.Background(), r)
+	status, err := CreateRole(context.Background(), r)
 	if err != nil {
 		log.Fatalf(err, "create role [%s] failed", r.Name)
 		return
diff --git a/server/service/rbac/dao/role_dao.go b/server/service/rbac/role_dao.go
similarity index 99%
rename from server/service/rbac/dao/role_dao.go
rename to server/service/rbac/role_dao.go
index df8feef..b9f4e3d 100644
--- a/server/service/rbac/dao/role_dao.go
+++ b/server/service/rbac/role_dao.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package dao
+package rbac
 
 import (
 	"context"
diff --git a/server/service/rbac/dao/role_dao_test.go b/server/service/rbac/role_dao_test.go
similarity index 70%
rename from server/service/rbac/dao/role_dao_test.go
rename to server/service/rbac/role_dao_test.go
index 443332f..995a576 100644
--- a/server/service/rbac/dao/role_dao_test.go
+++ b/server/service/rbac/role_dao_test.go
@@ -1,16 +1,15 @@
-package dao_test
+package rbac_test
 
 import (
 	"context"
 	rbacsvc "github.com/apache/servicecomb-service-center/server/service/rbac"
-	"github.com/apache/servicecomb-service-center/server/service/rbac/dao"
 	"github.com/go-chassis/cari/discovery"
 	"github.com/go-chassis/cari/rbac"
 	"github.com/stretchr/testify/assert"
 	"testing"
 )
 
-func exampleRole(name string) *rbac.Role {
+func newRole(name string) *rbac.Role {
 	return &rbac.Role{
 		Name: name,
 		Perms: []*rbac.Permission{
@@ -28,18 +27,18 @@ func exampleRole(name string) *rbac.Role {
 
 func TestCreateRole(t *testing.T) {
 	t.Run("create new role, should succeed", func(t *testing.T) {
-		r := exampleRole("TestCreateRole_createNewRole")
-		status, err := dao.CreateRole(context.TODO(), r)
+		r := newRole("TestCreateRole_createNewRole")
+		status, err := rbacsvc.CreateRole(context.TODO(), r)
 		assert.Nil(t, err)
 		assert.True(t, status.IsSucceed())
 	})
 	t.Run("create role twice, should return: "+rbac.NewError(rbac.ErrRoleConflict, "").Error(), func(t *testing.T) {
-		r := exampleRole("TestCreateRole_createRoleTwice")
-		status, err := dao.CreateRole(context.TODO(), r)
+		r := newRole("TestCreateRole_createRoleTwice")
+		status, err := rbacsvc.CreateRole(context.TODO(), r)
 		assert.Nil(t, err)
 		assert.True(t, status.IsSucceed())
 		// twice
-		status, err = dao.CreateRole(context.TODO(), r)
+		status, err = rbacsvc.CreateRole(context.TODO(), r)
 		assert.Nil(t, err)
 		assert.Equal(t, rbac.ErrRoleConflict, status.GetCode())
 	})
@@ -47,17 +46,17 @@ func TestCreateRole(t *testing.T) {
 
 func TestGetRole(t *testing.T) {
 	t.Run("get no exist role, should return: "+rbac.NewError(rbac.ErrRoleNotExist, "").Error(), func(t *testing.T) {
-		r, status, err := dao.GetRole(context.TODO(), "TestGetRole_getNoExistRole")
+		r, status, err := rbacsvc.GetRole(context.TODO(), "TestGetRole_getNoExistRole")
 		assert.Nil(t, err)
 		assert.Equal(t, rbac.ErrRoleNotExist, status.GetCode())
 		assert.Nil(t, r)
 	})
 	t.Run("get exist role, should success", func(t *testing.T) {
-		r := exampleRole("TestGetRole_getExistRole")
-		status, err := dao.CreateRole(context.TODO(), r)
+		r := newRole("TestGetRole_getExistRole")
+		status, err := rbacsvc.CreateRole(context.TODO(), r)
 		assert.Nil(t, err)
 		assert.True(t, status.IsSucceed())
-		resp, status, err := dao.GetRole(context.TODO(), r.Name)
+		resp, status, err := rbacsvc.GetRole(context.TODO(), r.Name)
 		assert.Nil(t, err)
 		assert.True(t, status.IsSucceed())
 		assert.Equal(t, r.Name, resp.Name)
@@ -66,14 +65,14 @@ func TestGetRole(t *testing.T) {
 
 func TestEditRole(t *testing.T) {
 	t.Run("edit no exist role, should return: "+rbac.NewError(rbac.ErrRoleNotExist, "").Error(), func(t *testing.T) {
-		r := exampleRole("TestEditRole_editNoExistRole")
-		status, err := dao.EditRole(context.TODO(), r.Name, r)
+		r := newRole("TestEditRole_editNoExistRole")
+		status, err := rbacsvc.EditRole(context.TODO(), r.Name, r)
 		assert.Nil(t, err)
 		assert.Equal(t, rbac.ErrRoleNotExist, status.GetCode())
 	})
 	t.Run("edit role, should success", func(t *testing.T) {
-		r := exampleRole("TestGetRole_editRole")
-		status, err := dao.CreateRole(context.TODO(), r)
+		r := newRole("TestGetRole_editRole")
+		status, err := rbacsvc.CreateRole(context.TODO(), r)
 		assert.Nil(t, err)
 		assert.True(t, status.IsSucceed())
 
@@ -97,18 +96,18 @@ func TestEditRole(t *testing.T) {
 				Verbs: []string{"*"},
 			},
 		}
-		status, err = dao.EditRole(context.TODO(), r.Name, r)
+		status, err = rbacsvc.EditRole(context.TODO(), r.Name, r)
 		assert.Nil(t, err)
 		assert.True(t, status.IsSucceed())
 
-		resp, status, err := dao.GetRole(context.TODO(), r.Name)
+		resp, status, err := rbacsvc.GetRole(context.TODO(), r.Name)
 		assert.Nil(t, err)
 		assert.True(t, status.IsSucceed())
 		assert.Equal(t, 2, len(resp.Perms))
 	})
 	t.Run("edit build in role, should return: "+discovery.NewError(discovery.ErrForbidden, "").Error(), func(t *testing.T) {
 		for _, name := range []string{rbac.RoleDeveloper, rbac.RoleDeveloper} {
-			status, err := dao.EditRole(context.TODO(), name, exampleRole(""))
+			status, err := rbacsvc.EditRole(context.TODO(), name, newRole(""))
 			assert.Nil(t, err)
 			assert.Equal(t, discovery.ErrForbidden, status.GetCode())
 		}
@@ -117,27 +116,27 @@ func TestEditRole(t *testing.T) {
 
 func TestDeleteRole(t *testing.T) {
 	t.Run("delete no exist role, should return: "+rbac.NewError(rbac.ErrRoleNotExist, "").Error(), func(t *testing.T) {
-		status, err := dao.DeleteRole(context.TODO(), "TestDeleteRole_deleteNoExistRole")
+		status, err := rbacsvc.DeleteRole(context.TODO(), "TestDeleteRole_deleteNoExistRole")
 		assert.Nil(t, err)
 		assert.Equal(t, rbac.ErrRoleNotExist, status.GetCode())
 	})
 	t.Run("delete role, should success", func(t *testing.T) {
-		r := exampleRole("TestDeleteRole_deleteRole")
-		status, err := dao.CreateRole(context.TODO(), r)
+		r := newRole("TestDeleteRole_deleteRole")
+		status, err := rbacsvc.CreateRole(context.TODO(), r)
 		assert.Nil(t, err)
 		assert.True(t, status.IsSucceed())
 
-		status, err = dao.DeleteRole(context.TODO(), r.Name)
+		status, err = rbacsvc.DeleteRole(context.TODO(), r.Name)
 		assert.Nil(t, err)
 		assert.True(t, status.IsSucceed())
 
-		exist, err := dao.RoleExist(context.TODO(), r.Name)
+		exist, err := rbacsvc.RoleExist(context.TODO(), r.Name)
 		assert.Nil(t, err)
 		assert.False(t, exist)
 	})
 	t.Run("delete build in role, should return: "+discovery.NewError(discovery.ErrForbidden, "").Error(), func(t *testing.T) {
 		for _, name := range []string{rbac.RoleDeveloper, rbac.RoleDeveloper} {
-			status, err := dao.DeleteRole(context.TODO(), name)
+			status, err := rbacsvc.DeleteRole(context.TODO(), name)
 			assert.Nil(t, err)
 			assert.Equal(t, discovery.ErrForbidden, status.GetCode())
 		}
@@ -146,7 +145,7 @@ func TestDeleteRole(t *testing.T) {
 
 func TestListRole(t *testing.T) {
 	t.Run("list role, should success", func(t *testing.T) {
-		roles, total, err := dao.ListRole(context.TODO())
+		roles, total, err := rbacsvc.ListRole(context.TODO())
 		assert.Nil(t, err)
 		assert.True(t, total > 0)
 		assert.Equal(t, int64(len(roles)), total)
@@ -155,7 +154,7 @@ func TestListRole(t *testing.T) {
 
 func TestRoleExistt(t *testing.T) {
 	t.Run("check no exist role, should success and not exist", func(t *testing.T) {
-		exist, err := dao.RoleExist(context.TODO(), "TestRoleExist_checkNoExistRole")
+		exist, err := rbacsvc.RoleExist(context.TODO(), "TestRoleExist_checkNoExistRole")
 		assert.Nil(t, err)
 		assert.False(t, exist)
 	})