add isPermissionMethod #8
25
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 ...
|
||||
|
|
|
@ -11,12 +11,16 @@ var cache *bigcache.BigCache
|
|||
|
||||
|
||||
// Init ...
|
||||
func Init() {
|
||||
// The time after which entries can be evicted is 5 years
|
||||
đặ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))
|
||||
đặ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
|
||||
// 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
|
||||
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
|
||||
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 {
|
||||
log.Fatalf("Cannot init Cache %v", err)
|
||||
}
|
||||
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 ...
|
||||
|
|
|||
đặ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 (
|
||||
"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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
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/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
|
||||
}
|
||||
|
||||
|
|
đặ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