From 2a74aa1b8ea25e672be7a107489a17fb1fcea511 Mon Sep 17 00:00:00 2001 From: Hoang Date: Wed, 10 Nov 2021 16:53:31 +0700 Subject: [PATCH 1/6] add isPermissionMethod --- action.go | 9 +++++++-- user/db.go | 15 +++++++++++++++ user/handle.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/action.go b/action.go index 122ba1d..ca773c8 100644 --- a/action.go +++ b/action.go @@ -33,8 +33,8 @@ func (s Service) ChangeUserStatus(userID, newStatus string) error { return user.ChangeUserStatus(userID, newStatus) } -// GetAllUser ... -func (s Service) GetAllUser(query model.UserAllQuery) model.UserAll { +// GetAllUsers ... +func (s Service) GetAllUsers(query model.UserAllQuery) model.UserAll { return user.All(query) } @@ -48,6 +48,11 @@ func (s Service) LoginWithEmailAndPassword(email, password string) (model.User, return user.LoginWithEmailAndPassword(email, password) } +// IsPermission ... +func (s Service) IsPermission(userID, permission string) bool { + return user.IsPermission(userID, permission) +} + // // Role // diff --git a/user/db.go b/user/db.go index d6f9aa4..1c2fccb 100644 --- a/user/db.go +++ b/user/db.go @@ -66,6 +66,21 @@ func roleFindByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, err return doc, err } +// permissionCountByCondition ... +func permissionCountByCondition(ctx context.Context, cond interface{}) int64 { + var ( + col = database.GetPermissionCol() + ) + total, err := col.CountDocuments(ctx, cond) + if err != nil { + logger.Error("usermngmt - Permission - CountDocuments", logger.LogData{ + "err": err.Error(), + "cond": cond, + }) + } + return total +} + func create(ctx context.Context, doc model.DBUser) error { var ( col = database.GetUserCol() diff --git a/user/handle.go b/user/handle.go index fc5831c..503689d 100644 --- a/user/handle.go +++ b/user/handle.go @@ -319,3 +319,54 @@ func LoginWithEmailAndPassword(email, password string) (result model.User, err e result = getResponse(ctx, user) return } + +// IsPermission ... +func IsPermission(userID, permission string) (result bool) { + var ( + ctx = context.Background() + ) + + // Validate userID, permission + if userID == "" || permission == "" { + logger.Error("usermngmt - IsPermission: email or password cannot be empty", logger.LogData{ + "userID": userID, + "permission": permission, + }) + return + } + id, isValid := mongodb.NewIDFromString(userID) + if !isValid { + logger.Error("usermngmt - IsPermission: invalid user id", logger.LogData{ + "userID": userID, + "permission": permission, + }) + return + } + + // Find user + user, _ := findByID(ctx, id) + if user.ID.IsZero() { + logger.Error("usermngmt - IsPermission: user not found", logger.LogData{ + "userID": userID, + "permission": permission, + }) + return + } + + // Check isAdmin + if role, _ := roleFindByID(ctx, user.RoleID); role.IsAdmin { + result = true + return + } + + // Check permission + if total := permissionCountByCondition(ctx, bson.M{ + "roleId": user.RoleID, + "code": permission, + }); total > 0 { + result = true + return + } + + return +} From b2373bbada1dd28e5c239b9721174e43a650a963 Mon Sep 17 00:00:00 2001 From: Hoang Date: Wed, 10 Nov 2021 17:02:16 +0700 Subject: [PATCH 2/6] change name to HasPermission --- action.go | 6 +++--- user/handle.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/action.go b/action.go index ca773c8..bba4ad7 100644 --- a/action.go +++ b/action.go @@ -48,9 +48,9 @@ func (s Service) LoginWithEmailAndPassword(email, password string) (model.User, return user.LoginWithEmailAndPassword(email, password) } -// IsPermission ... -func (s Service) IsPermission(userID, permission string) bool { - return user.IsPermission(userID, permission) +// HasPermission ... +func (s Service) HasPermission(userID, permission string) bool { + return user.HasPermission(userID, permission) } // diff --git a/user/handle.go b/user/handle.go index 503689d..96ed3c0 100644 --- a/user/handle.go +++ b/user/handle.go @@ -320,8 +320,8 @@ func LoginWithEmailAndPassword(email, password string) (result model.User, err e return } -// IsPermission ... -func IsPermission(userID, permission string) (result bool) { +// HasPermission ... +func HasPermission(userID, permission string) (result bool) { var ( ctx = context.Background() ) From 7c232c043492c1e769d2f776594dcd0b01a07cd0 Mon Sep 17 00:00:00 2001 From: Hoang Date: Thu, 11 Nov 2021 10:20:08 +0700 Subject: [PATCH 3/6] fix comment again --- action.go | 18 +++++++++++++--- cache/cache.go | 25 ++++++++++++++++++++++ go.mod | 4 +++- go.sum | 4 ++++ internal/constant.go | 2 ++ role/db.go | 27 ++++++++++++++++++++++++ role/handle.go | 50 ++++++++++++++++++++++++++++++++++++++++++++ user/handle.go | 30 +++++++++++++------------- usermngmt.go | 8 +++++++ 9 files changed, 149 insertions(+), 19 deletions(-) create mode 100644 cache/cache.go diff --git a/action.go b/action.go index bba4ad7..fdeff9c 100644 --- a/action.go +++ b/action.go @@ -61,7 +61,11 @@ func (s Service) HasPermission(userID, permission string) bool { // CreateRole ... func (s Service) CreateRole(payload model.RoleCreateOptions) error { - return role.Create(payload) + err := role.Create(payload) + if err == nil { + role.CacheRoles() + } + return err } // UpdateRole ... @@ -82,12 +86,20 @@ func (s Service) GetAllRoles(query model.RoleAllQuery) model.RoleAll { // CreatePermission ... func (s Service) CreatePermission(payload model.PermissionCreateOptions) error { - return permission.Create(payload) + err := permission.Create(payload) + if err == nil { + role.CacheRoles() + } + return err } // UpdatePermission ... func (s Service) UpdatePermission(permissionID string, payload model.PermissionUpdateOptions) error { - return permission.Update(permissionID, payload) + err := permission.Update(permissionID, payload) + if err == nil { + role.CacheRoles() + } + return err } // GetAllPermissions ... diff --git a/cache/cache.go b/cache/cache.go new file mode 100644 index 0000000..25cdd03 --- /dev/null +++ b/cache/cache.go @@ -0,0 +1,25 @@ +package cache + +import ( + "log" + "time" + + "github.com/allegro/bigcache/v3" +) + +var cache *bigcache.BigCache + +// Init ... +func Init() { + // The time after which entries can be evicted is 5 years + c, err := bigcache.NewBigCache(bigcache.DefaultConfig(43800 * time.Hour)) + if err != nil { + log.Fatalf("Cannot init Cache %v", err) + } + cache = c +} + +// GetInstance ... +func GetInstance() *bigcache.BigCache { + return cache +} diff --git a/go.mod b/go.mod index 70aa30c..a2de3aa 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,10 @@ go 1.17 require ( github.com/Selly-Modules/logger v0.0.0-20210809034923-140a51f39ec9 github.com/Selly-Modules/mongodb v0.0.0-20211013094205-a8ab24a96c4c + github.com/allegro/bigcache/v3 v3.0.1 + github.com/thoas/go-funk v0.9.1 go.mongodb.org/mongo-driver v1.7.4 + golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 ) require ( @@ -32,7 +35,6 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.18.1 // indirect - golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 // indirect golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect golang.org/x/mod v0.3.0 // indirect golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect diff --git a/go.sum b/go.sum index 7fdc319..7bdbc2f 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/Selly-Modules/logger v0.0.0-20210809034923-140a51f39ec9 h1:AuJ/IIZ7yp github.com/Selly-Modules/logger v0.0.0-20210809034923-140a51f39ec9/go.mod h1:RWhSQ3F01an8KD00VjzRBZOMcE5eV2Cy0/l4ZkeieyU= github.com/Selly-Modules/mongodb v0.0.0-20211013094205-a8ab24a96c4c h1:1l6QmAl43maG9zFyUXrPQVUjyVt0vy/2Saz992UR+Sc= github.com/Selly-Modules/mongodb v0.0.0-20211013094205-a8ab24a96c4c/go.mod h1:C9O0Bgl9i6szjntMjBdEvaFSqG2UPOgHUspIWIJ93JQ= +github.com/allegro/bigcache/v3 v3.0.1 h1:Q4Xl3chywXuJNOw7NV+MeySd3zGQDj4KCpkCg0te8mc= +github.com/allegro/bigcache/v3 v3.0.1/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -91,6 +93,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= +github.com/thoas/go-funk v0.9.1/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= diff --git a/internal/constant.go b/internal/constant.go index c048f83..1a97219 100644 --- a/internal/constant.go +++ b/internal/constant.go @@ -7,4 +7,6 @@ const ( passwordHashingCost = 14 TablePrefixDefault = "usermngmt" + + RoleTypeAdmin = "admin" ) diff --git a/role/db.go b/role/db.go index 55209e0..c27883c 100644 --- a/role/db.go +++ b/role/db.go @@ -54,6 +54,33 @@ func updateOneByCondition(ctx context.Context, cond interface{}, payload interfa return err } +func permissionFindByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBPermission) { + var ( + col = database.GetPermissionCol() + ) + docs = make([]model.DBPermission, 0) + + cursor, err := col.Find(ctx, cond, opts...) + if err != nil { + logger.Error("usermngmt - Permission - Find", logger.LogData{ + "cond": cond, + "opts": opts, + "err": err.Error(), + }) + return + } + defer cursor.Close(ctx) + if err = cursor.All(ctx, &docs); err != nil { + logger.Error("usermngmt - Permission - Decode", logger.LogData{ + "cond": cond, + "opts": opts, + "err": err.Error(), + }) + return + } + return +} + func findByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBRole) { var ( col = database.GetRoleCol() diff --git a/role/handle.go b/role/handle.go index e4145a6..7ba14ee 100644 --- a/role/handle.go +++ b/role/handle.go @@ -3,11 +3,15 @@ package role import ( "context" "errors" + "strings" "sync" + "github.com/Selly-Modules/logger" "github.com/Selly-Modules/mongodb" + "github.com/Selly-Modules/usermngmt/cache" "github.com/Selly-Modules/usermngmt/internal" "github.com/Selly-Modules/usermngmt/model" + "github.com/thoas/go-funk" "go.mongodb.org/mongo-driver/bson" ) @@ -132,3 +136,49 @@ func getResponseList(roles []model.DBRole) []model.Role { return res } + +// CacheRoles ... +func CacheRoles() { + var ( + ctx = context.Background() + wg sync.WaitGroup + ) + + // Find + roles := findByCondition(ctx, bson.M{}) + + wg.Add(len(roles)) + for _, value := range roles { + go func(role model.DBRole) { + defer wg.Done() + + // Check and set role admin: admin + if role.IsAdmin { + if err := cache.GetInstance().Set(role.ID.Hex(), []byte(internal.RoleTypeAdmin)); err != nil { + logger.Error("usermngmt - CacheRole", logger.LogData{ + "err": err.Error(), + }) + return + } + } + + // Set role by permission with format: permissionCode,permissionCode,... + permissions := permissionFindByCondition(ctx, bson.M{ + "roleId": role.ID, + }) + permissionCodes := funk.Map(permissions, func(i model.DBPermission) string { + return i.Code + }).([]string) + permissionCodeString := strings.Join(permissionCodes, ",") + if err := cache.GetInstance().Set(role.ID.Hex(), []byte(permissionCodeString)); err != nil { + logger.Error("usermngmt - CacheRole", logger.LogData{ + "err": err.Error(), + }) + return + } + }(value) + } + + wg.Done() + return +} diff --git a/user/handle.go b/user/handle.go index 96ed3c0..ac98f98 100644 --- a/user/handle.go +++ b/user/handle.go @@ -3,12 +3,15 @@ package user import ( "context" "errors" + "strings" "sync" "github.com/Selly-Modules/logger" "github.com/Selly-Modules/mongodb" + "github.com/Selly-Modules/usermngmt/cache" "github.com/Selly-Modules/usermngmt/internal" "github.com/Selly-Modules/usermngmt/model" + "github.com/thoas/go-funk" "go.mongodb.org/mongo-driver/bson" ) @@ -328,7 +331,7 @@ func HasPermission(userID, permission string) (result bool) { // Validate userID, permission if userID == "" || permission == "" { - logger.Error("usermngmt - IsPermission: email or password cannot be empty", logger.LogData{ + logger.Error("usermngmt - HasPermission: email or password cannot be empty", logger.LogData{ "userID": userID, "permission": permission, }) @@ -336,7 +339,7 @@ func HasPermission(userID, permission string) (result bool) { } id, isValid := mongodb.NewIDFromString(userID) if !isValid { - logger.Error("usermngmt - IsPermission: invalid user id", logger.LogData{ + logger.Error("usermngmt - HasPermission: invalid user id", logger.LogData{ "userID": userID, "permission": permission, }) @@ -346,26 +349,23 @@ func HasPermission(userID, permission string) (result bool) { // Find user user, _ := findByID(ctx, id) if user.ID.IsZero() { - logger.Error("usermngmt - IsPermission: user not found", logger.LogData{ + logger.Error("usermngmt - HasPermission: user not found", logger.LogData{ "userID": userID, "permission": permission, }) return } - // Check isAdmin - if role, _ := roleFindByID(ctx, user.RoleID); role.IsAdmin { - result = true - return - } + // Get rolePermissions + // Role is saved with the value "admin" or "permissionCode,permissionCode,..." + entry, _ := cache.GetInstance().Get(user.RoleID.Hex()) + rolePermissions := strings.Split(string(entry), ",") - // Check permission - if total := permissionCountByCondition(ctx, bson.M{ - "roleId": user.RoleID, - "code": permission, - }); total > 0 { - result = true - return + // Check Permission + if _, isValid = funk.FindString(rolePermissions, func(s string) bool { + return s == permission || s == internal.RoleTypeAdmin + }); isValid { + return isValid } return diff --git a/usermngmt.go b/usermngmt.go index b2a2236..112a1a0 100644 --- a/usermngmt.go +++ b/usermngmt.go @@ -5,8 +5,10 @@ import ( "fmt" "github.com/Selly-Modules/mongodb" + "github.com/Selly-Modules/usermngmt/cache" "github.com/Selly-Modules/usermngmt/database" "github.com/Selly-Modules/usermngmt/internal" + "github.com/Selly-Modules/usermngmt/role" ) // MongoDBConfig ... @@ -54,6 +56,9 @@ func Init(config Config) (*Service, error) { return nil, err } + // Init cache + cache.Init() + // Set database database.Set(db, config.TablePrefix) @@ -61,6 +66,9 @@ func Init(config Config) (*Service, error) { config: config, } + // Cache role + role.CacheRoles() + return s, nil } From 8d19c4c09c45f7858aec5a0d46639f0f31e02ee2 Mon Sep 17 00:00:00 2001 From: Hoang Date: Thu, 11 Nov 2021 15:16:17 +0700 Subject: [PATCH 4/6] fix comment again --- action.go | 25 +++++++++--------- cache/cache.go | 8 ++++-- cache/db.go | 64 +++++++++++++++++++++++++++++++++++++++++++++ cache/model.go | 8 ++++++ cache/role.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ role/handle.go | 50 ------------------------------------ user/handle.go | 24 +++++++++-------- usermngmt.go | 4 --- 8 files changed, 175 insertions(+), 78 deletions(-) create mode 100644 cache/db.go create mode 100644 cache/model.go create mode 100644 cache/role.go diff --git a/action.go b/action.go index fdeff9c..3b33ee1 100644 --- a/action.go +++ b/action.go @@ -1,6 +1,7 @@ package usermngmt import ( + "github.com/Selly-Modules/usermngmt/cache" "github.com/Selly-Modules/usermngmt/model" "github.com/Selly-Modules/usermngmt/permission" "github.com/Selly-Modules/usermngmt/role" @@ -61,11 +62,11 @@ func (s Service) HasPermission(userID, permission string) bool { // CreateRole ... func (s Service) CreateRole(payload model.RoleCreateOptions) error { - err := role.Create(payload) - if err == nil { - role.CacheRoles() + if err := role.Create(payload); err != nil { + return err } - return err + cache.Roles() + return nil } // UpdateRole ... @@ -86,20 +87,20 @@ func (s Service) GetAllRoles(query model.RoleAllQuery) model.RoleAll { // CreatePermission ... func (s Service) CreatePermission(payload model.PermissionCreateOptions) error { - err := permission.Create(payload) - if err == nil { - role.CacheRoles() + if err := permission.Create(payload); err != nil { + return err } - return err + cache.Roles() + return nil } // UpdatePermission ... func (s Service) UpdatePermission(permissionID string, payload model.PermissionUpdateOptions) error { - err := permission.Update(permissionID, payload) - if err == nil { - role.CacheRoles() + if err := permission.Update(permissionID, payload); err != nil { + return err } - return err + cache.Roles() + return nil } // GetAllPermissions ... diff --git a/cache/cache.go b/cache/cache.go index 25cdd03..c487d03 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -11,12 +11,16 @@ var cache *bigcache.BigCache // Init ... func Init() { - // The time after which entries can be evicted is 5 years - c, err := bigcache.NewBigCache(bigcache.DefaultConfig(43800 * time.Hour)) + // The time after which entries can be evicted is 30 days + const cacheTime = 24 * 30 * time.Hour // 30 days + c, err := bigcache.NewBigCache(bigcache.DefaultConfig(cacheTime)) if err != nil { log.Fatalf("Cannot init Cache %v", err) } cache = c + + // Cache roles + Roles() } // GetInstance ... diff --git a/cache/db.go b/cache/db.go new file mode 100644 index 0000000..6d062cb --- /dev/null +++ b/cache/db.go @@ -0,0 +1,64 @@ +package cache + +import ( + "context" + + "github.com/Selly-Modules/logger" + "github.com/Selly-Modules/usermngmt/database" + "github.com/Selly-Modules/usermngmt/model" + "go.mongodb.org/mongo-driver/mongo/options" +) + +func roleFindByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBRole) { + var ( + col = database.GetRoleCol() + ) + docs = make([]model.DBRole, 0) + + cursor, err := col.Find(ctx, cond, opts...) + if err != nil { + logger.Error("usermngmt - Role - Find", logger.LogData{ + "cond": cond, + "opts": opts, + "err": err.Error(), + }) + return + } + defer cursor.Close(ctx) + if err = cursor.All(ctx, &docs); err != nil { + logger.Error("usermngmt - Role - Decode", logger.LogData{ + "cond": cond, + "opts": opts, + "err": err.Error(), + }) + return + } + return +} + +func permissionFindByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBPermission) { + var ( + col = database.GetPermissionCol() + ) + docs = make([]model.DBPermission, 0) + + cursor, err := col.Find(ctx, cond, opts...) + if err != nil { + logger.Error("usermngmt - Permission - Find", logger.LogData{ + "cond": cond, + "opts": opts, + "err": err.Error(), + }) + return + } + defer cursor.Close(ctx) + if err = cursor.All(ctx, &docs); err != nil { + logger.Error("usermngmt - Permission - Decode", logger.LogData{ + "cond": cond, + "opts": opts, + "err": err.Error(), + }) + return + } + return +} diff --git a/cache/model.go b/cache/model.go new file mode 100644 index 0000000..96b64cb --- /dev/null +++ b/cache/model.go @@ -0,0 +1,8 @@ +package cache + +// CachedRole ... +type CachedRole struct { + Role string `json:"role"` + IsAdmin bool `json:"isAdmin"` + Permissions []string `json:"permissions"` +} diff --git a/cache/role.go b/cache/role.go new file mode 100644 index 0000000..b4908d2 --- /dev/null +++ b/cache/role.go @@ -0,0 +1,70 @@ +package cache + +import ( + "context" + "encoding/json" + "sync" + + "github.com/Selly-Modules/logger" + "github.com/Selly-Modules/usermngmt/model" + "go.mongodb.org/mongo-driver/bson" +) + +// Roles ... +func Roles() { + var ( + ctx = context.Background() + wg sync.WaitGroup + cond = bson.M{} + ) + + // Find + roles := roleFindByCondition(ctx, cond) + permissions := permissionFindByCondition(ctx, cond) + + wg.Add(len(roles)) + for _, value := range roles { + go func(role model.DBRole) { + defer wg.Done() + rolePermissions := make([]string, 0) + // Get role permissions + for _, permission := range permissions { + if permission.RoleID == role.ID { + rolePermissions = append(rolePermissions, permission.Code) + } + } + + // Cache Role + entry, _ := json.Marshal(CachedRole{ + Role: role.Code, + IsAdmin: role.IsAdmin, + Permissions: rolePermissions, + }) + if err := cache.Set(role.ID.Hex(), entry); err != nil { + logger.Error("usermngmt - CacheRole", logger.LogData{ + "err": err.Error(), + }) + return + } + }(value) + } + + wg.Wait() + return +} + +// GetCachedRole ... +func GetCachedRole(key string) CachedRole { + entry, err := cache.Get(key) + if err != nil { + Roles() + entry, _ = cache.Get(key) + } + var cachedRole CachedRole + if err = json.Unmarshal(entry, &cachedRole); err != nil { + logger.Error("usermngmt - GetCachedRole - Unmarshal", logger.LogData{ + "err": err.Error(), + }) + } + return cachedRole +} diff --git a/role/handle.go b/role/handle.go index 7ba14ee..e4145a6 100644 --- a/role/handle.go +++ b/role/handle.go @@ -3,15 +3,11 @@ package role import ( "context" "errors" - "strings" "sync" - "github.com/Selly-Modules/logger" "github.com/Selly-Modules/mongodb" - "github.com/Selly-Modules/usermngmt/cache" "github.com/Selly-Modules/usermngmt/internal" "github.com/Selly-Modules/usermngmt/model" - "github.com/thoas/go-funk" "go.mongodb.org/mongo-driver/bson" ) @@ -136,49 +132,3 @@ func getResponseList(roles []model.DBRole) []model.Role { return res } - -// CacheRoles ... -func CacheRoles() { - var ( - ctx = context.Background() - wg sync.WaitGroup - ) - - // Find - roles := findByCondition(ctx, bson.M{}) - - wg.Add(len(roles)) - for _, value := range roles { - go func(role model.DBRole) { - defer wg.Done() - - // Check and set role admin: admin - if role.IsAdmin { - if err := cache.GetInstance().Set(role.ID.Hex(), []byte(internal.RoleTypeAdmin)); err != nil { - logger.Error("usermngmt - CacheRole", logger.LogData{ - "err": err.Error(), - }) - return - } - } - - // Set role by permission with format: permissionCode,permissionCode,... - permissions := permissionFindByCondition(ctx, bson.M{ - "roleId": role.ID, - }) - permissionCodes := funk.Map(permissions, func(i model.DBPermission) string { - return i.Code - }).([]string) - permissionCodeString := strings.Join(permissionCodes, ",") - if err := cache.GetInstance().Set(role.ID.Hex(), []byte(permissionCodeString)); err != nil { - logger.Error("usermngmt - CacheRole", logger.LogData{ - "err": err.Error(), - }) - return - } - }(value) - } - - wg.Done() - return -} diff --git a/user/handle.go b/user/handle.go index ac98f98..23864d4 100644 --- a/user/handle.go +++ b/user/handle.go @@ -3,7 +3,6 @@ package user import ( "context" "errors" - "strings" "sync" "github.com/Selly-Modules/logger" @@ -13,6 +12,7 @@ import ( "github.com/Selly-Modules/usermngmt/model" "github.com/thoas/go-funk" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" ) // Create ... @@ -356,17 +356,21 @@ func HasPermission(userID, permission string) (result bool) { return } - // Get rolePermissions - // Role is saved with the value "admin" or "permissionCode,permissionCode,..." - entry, _ := cache.GetInstance().Get(user.RoleID.Hex()) - rolePermissions := strings.Split(string(entry), ",") + return checkUserHasPermissionFromCache(user.RoleID, permission) +} - // Check Permission - if _, isValid = funk.FindString(rolePermissions, func(s string) bool { - return s == permission || s == internal.RoleTypeAdmin +func checkUserHasPermissionFromCache(roleID primitive.ObjectID, permission string) bool { + cachedRole := cache.GetCachedRole(roleID.Hex()) + + // Check permission + if cachedRole.IsAdmin { + return true + } + if _, isValid := funk.FindString(cachedRole.Permissions, func(s string) bool { + return s == permission }); isValid { - return isValid + return true } - return + return false } diff --git a/usermngmt.go b/usermngmt.go index 112a1a0..b0617e6 100644 --- a/usermngmt.go +++ b/usermngmt.go @@ -8,7 +8,6 @@ import ( "github.com/Selly-Modules/usermngmt/cache" "github.com/Selly-Modules/usermngmt/database" "github.com/Selly-Modules/usermngmt/internal" - "github.com/Selly-Modules/usermngmt/role" ) // MongoDBConfig ... @@ -66,9 +65,6 @@ func Init(config Config) (*Service, error) { config: config, } - // Cache role - role.CacheRoles() - return s, nil } From 4ee176b9e090bdc36445db89c17aaaf260852e06 Mon Sep 17 00:00:00 2001 From: Hoang Date: Thu, 11 Nov 2021 15:19:38 +0700 Subject: [PATCH 5/6] fix comment again --- role/db.go | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/role/db.go b/role/db.go index c27883c..9884664 100644 --- a/role/db.go +++ b/role/db.go @@ -7,20 +7,9 @@ import ( "github.com/Selly-Modules/logger" "github.com/Selly-Modules/usermngmt/database" "github.com/Selly-Modules/usermngmt/model" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo/options" ) -func findByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { - var ( - doc model.DBRole - col = database.GetRoleCol() - ) - err := col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) - return doc, err -} - func create(ctx context.Context, doc model.DBRole) error { var ( col = database.GetRoleCol() @@ -54,33 +43,6 @@ func updateOneByCondition(ctx context.Context, cond interface{}, payload interfa return err } -func permissionFindByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBPermission) { - var ( - col = database.GetPermissionCol() - ) - docs = make([]model.DBPermission, 0) - - cursor, err := col.Find(ctx, cond, opts...) - if err != nil { - logger.Error("usermngmt - Permission - Find", logger.LogData{ - "cond": cond, - "opts": opts, - "err": err.Error(), - }) - return - } - defer cursor.Close(ctx) - if err = cursor.All(ctx, &docs); err != nil { - logger.Error("usermngmt - Permission - Decode", logger.LogData{ - "cond": cond, - "opts": opts, - "err": err.Error(), - }) - return - } - return -} - func findByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBRole) { var ( col = database.GetRoleCol() From 45e9f71a3f9f5a8784e398d502cb884e6fc5a2b3 Mon Sep 17 00:00:00 2001 From: Hoang Date: Thu, 11 Nov 2021 16:58:44 +0700 Subject: [PATCH 6/6] fix comment again --- cache/cache.go | 6 +++--- cache/role.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cache/cache.go b/cache/cache.go index c487d03..5f51ac5 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -7,7 +7,7 @@ import ( "github.com/allegro/bigcache/v3" ) -var cache *bigcache.BigCache +var mc *bigcache.BigCache // Init ... func Init() { @@ -17,7 +17,7 @@ func Init() { if err != nil { log.Fatalf("Cannot init Cache %v", err) } - cache = c + mc = c // Cache roles Roles() @@ -25,5 +25,5 @@ func Init() { // GetInstance ... func GetInstance() *bigcache.BigCache { - return cache + return mc } diff --git a/cache/role.go b/cache/role.go index b4908d2..7f08d5e 100644 --- a/cache/role.go +++ b/cache/role.go @@ -40,7 +40,7 @@ func Roles() { IsAdmin: role.IsAdmin, Permissions: rolePermissions, }) - if err := cache.Set(role.ID.Hex(), entry); err != nil { + if err := mc.Set(role.ID.Hex(), entry); err != nil { logger.Error("usermngmt - CacheRole", logger.LogData{ "err": err.Error(), }) @@ -55,10 +55,10 @@ func Roles() { // GetCachedRole ... func GetCachedRole(key string) CachedRole { - entry, err := cache.Get(key) + entry, err := mc.Get(key) if err != nil { Roles() - entry, _ = cache.Get(key) + entry, _ = mc.Get(key) } var cachedRole CachedRole if err = json.Unmarshal(entry, &cachedRole); err != nil {