add isPermissionMethod #8
25
action.go
|
@ -1,6 +1,7 @@
|
||||||
package usermngmt
|
package usermngmt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/Selly-Modules/usermngmt/cache"
|
||||||
"github.com/Selly-Modules/usermngmt/model"
|
"github.com/Selly-Modules/usermngmt/model"
|
||||||
"github.com/Selly-Modules/usermngmt/permission"
|
"github.com/Selly-Modules/usermngmt/permission"
|
||||||
"github.com/Selly-Modules/usermngmt/role"
|
"github.com/Selly-Modules/usermngmt/role"
|
||||||
|
@ -61,11 +62,11 @@ func (s Service) HasPermission(userID, permission string) bool {
|
||||||
|
|
||||||
// CreateRole ...
|
// CreateRole ...
|
||||||
func (s Service) CreateRole(payload model.RoleCreateOptions) error {
|
func (s Service) CreateRole(payload model.RoleCreateOptions) error {
|
||||||
err := role.Create(payload)
|
if err := role.Create(payload); err != nil {
|
||||||
if err == nil {
|
|
||||||
role.CacheRoles()
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
cache.Roles()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateRole ...
|
// UpdateRole ...
|
||||||
|
@ -86,20 +87,20 @@ func (s Service) GetAllRoles(query model.RoleAllQuery) model.RoleAll {
|
||||||
|
|
||||||
// CreatePermission ...
|
// CreatePermission ...
|
||||||
func (s Service) CreatePermission(payload model.PermissionCreateOptions) error {
|
func (s Service) CreatePermission(payload model.PermissionCreateOptions) error {
|
||||||
err := permission.Create(payload)
|
if err := permission.Create(payload); err != nil {
|
||||||
if err == nil {
|
|
||||||
role.CacheRoles()
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
cache.Roles()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePermission ...
|
// UpdatePermission ...
|
||||||
func (s Service) UpdatePermission(permissionID string, payload model.PermissionUpdateOptions) error {
|
func (s Service) UpdatePermission(permissionID string, payload model.PermissionUpdateOptions) error {
|
||||||
err := permission.Update(permissionID, payload)
|
if err := permission.Update(permissionID, payload); err != nil {
|
||||||
if err == nil {
|
|
||||||
role.CacheRoles()
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
cache.Roles()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllPermissions ...
|
// GetAllPermissions ...
|
||||||
|
|
|
@ -11,12 +11,16 @@ var cache *bigcache.BigCache
|
||||||
|
|||||||
|
|
||||||
// Init ...
|
// Init ...
|
||||||
func Init() {
|
func Init() {
|
||||||
// The time after which entries can be evicted is 5 years
|
// The time after which entries can be evicted is 30 days
|
||||||
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
done done
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
done done
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
done done
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
done done
|
|||||||
c, err := bigcache.NewBigCache(bigcache.DefaultConfig(43800 * time.Hour))
|
const cacheTime = 24 * 30 * time.Hour // 30 days
|
||||||
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
done done
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
done done
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
done done
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
done done
|
|||||||
|
c, err := bigcache.NewBigCache(bigcache.DefaultConfig(cacheTime))
|
||||||
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
done done
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
done done
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Cannot init Cache %v", err)
|
log.Fatalf("Cannot init Cache %v", err)
|
||||||
}
|
}
|
||||||
cache = c
|
cache = c
|
||||||
|
|
||||||
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
done done
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
done done
|
|||||||
|
// Cache roles
|
||||||
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
done done
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
done done
|
|||||||
|
Roles()
|
||||||
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
done done
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
done done
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetInstance ...
|
// GetInstance ...
|
||||||
|
|
||||||
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
đặt constant phía trên luôn
đặt constant phía trên luôn
```go
const cacheTime = 24 * 30 * time.Hour // 30 days
```
done done
done done
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
đặt tên biến lại chớ trùng với tên package rồi, đặt tên biến lại chớ trùng với tên package rồi, `mc` (mem-cache)
done done
done done
|
|
@ -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
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
// CachedRole ...
|
||||||
|
type CachedRole struct {
|
||||||
|
Role string `json:"role"`
|
||||||
|
IsAdmin bool `json:"isAdmin"`
|
||||||
|
Permissions []string `json:"permissions"`
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -3,15 +3,11 @@ package role
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/Selly-Modules/logger"
|
|
||||||
"github.com/Selly-Modules/mongodb"
|
"github.com/Selly-Modules/mongodb"
|
||||||
"github.com/Selly-Modules/usermngmt/cache"
|
|
||||||
"github.com/Selly-Modules/usermngmt/internal"
|
"github.com/Selly-Modules/usermngmt/internal"
|
||||||
"github.com/Selly-Modules/usermngmt/model"
|
"github.com/Selly-Modules/usermngmt/model"
|
||||||
"github.com/thoas/go-funk"
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -136,49 +132,3 @@ func getResponseList(roles []model.DBRole) []model.Role {
|
||||||
|
|
||||||
return res
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package user
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/Selly-Modules/logger"
|
"github.com/Selly-Modules/logger"
|
||||||
|
@ -13,6 +12,7 @@ import (
|
||||||
"github.com/Selly-Modules/usermngmt/model"
|
"github.com/Selly-Modules/usermngmt/model"
|
||||||
"github.com/thoas/go-funk"
|
"github.com/thoas/go-funk"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create ...
|
// Create ...
|
||||||
|
@ -356,17 +356,21 @@ func HasPermission(userID, permission string) (result bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rolePermissions
|
return checkUserHasPermissionFromCache(user.RoleID, permission)
|
||||||
// Role is saved with the value "admin" or "permissionCode,permissionCode,..."
|
}
|
||||||
entry, _ := cache.GetInstance().Get(user.RoleID.Hex())
|
|
||||||
rolePermissions := strings.Split(string(entry), ",")
|
|
||||||
|
|
||||||
// Check Permission
|
func checkUserHasPermissionFromCache(roleID primitive.ObjectID, permission string) bool {
|
||||||
if _, isValid = funk.FindString(rolePermissions, func(s string) bool {
|
cachedRole := cache.GetCachedRole(roleID.Hex())
|
||||||
return s == permission || s == internal.RoleTypeAdmin
|
|
||||||
|
// Check permission
|
||||||
|
if cachedRole.IsAdmin {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if _, isValid := funk.FindString(cachedRole.Permissions, func(s string) bool {
|
||||||
|
return s == permission
|
||||||
}); isValid {
|
}); isValid {
|
||||||
chỗ này thiếu
2 bước 2,3 nên đưa ra 1 func chỗ này thiếu
1. trong package ` cache` phải có 1 hàm `GetCachedRoles` trả về `CachedRoles`, trong hàm đó nếu check `cachedRoles = nil` thì phải call hàm `Roles` để tạo cache mới
2. ở chỗ này gọi hàm `GetCachedRoles`
3. dựa vào user.RoleID để pick ra data của role đó, sau đó check mảng permission
----
2 bước 2,3 nên đưa ra 1 func `checkUserHasPermissionFromCache` để làm cho gọn code
done done
|
|||||||
return isValid
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"github.com/Selly-Modules/usermngmt/cache"
|
"github.com/Selly-Modules/usermngmt/cache"
|
||||||
"github.com/Selly-Modules/usermngmt/database"
|
"github.com/Selly-Modules/usermngmt/database"
|
||||||
"github.com/Selly-Modules/usermngmt/internal"
|
"github.com/Selly-Modules/usermngmt/internal"
|
||||||
"github.com/Selly-Modules/usermngmt/role"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MongoDBConfig ...
|
// MongoDBConfig ...
|
||||||
|
@ -66,9 +65,6 @@ func Init(config Config) (*Service, error) {
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache role
|
|
||||||
role.CacheRoles()
|
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
đặt constant phía trên luôn
đặt constant phía trên luôn
done
done
đặt tên biến lại chớ trùng với tên package rồi,
mc
(mem-cache)đặt tên biến lại chớ trùng với tên package rồi,
mc
(mem-cache)done
done