structure: 确定基本结构(保持基本形式, 采用组合)
This commit is contained in:
110
pkg/rbac/create.go
Normal file
110
pkg/rbac/create.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package rbac
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/samber/lo"
|
||||
"strings"
|
||||
"uauth/model"
|
||||
)
|
||||
|
||||
func (u *RBAC) newScope(ctx context.Context, code, label, parent string) (*model.Scope, error) {
|
||||
s := &model.Scope{Code: code, Label: label, Parent: parent}
|
||||
if err := u.store.Session(ctx).Create(s).Error; err != nil {
|
||||
return s, err
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (u *RBAC) GetScopeGroup(ctx context.Context, name string) (*model.Scope, error) {
|
||||
scope := new(model.Scope)
|
||||
err := u.store.Session(ctx).Where("name = ?", name).Take(scope).Error
|
||||
|
||||
return scope, err
|
||||
}
|
||||
|
||||
func (u *RBAC) newRole(ctx context.Context, code, label, parent string, privileges ...*model.Privilege) (*model.Role, error) {
|
||||
ps := lo.FilterMap(
|
||||
privileges,
|
||||
func(p *model.Privilege, _ int) (string, bool) {
|
||||
if p == nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return p.Code, p.Code != ""
|
||||
},
|
||||
)
|
||||
|
||||
r := &model.Role{
|
||||
Code: code,
|
||||
Label: label,
|
||||
Parent: parent,
|
||||
PrivilegeCodes: ps,
|
||||
}
|
||||
|
||||
if err := u.store.Session(ctx).Create(r).Error; err != nil {
|
||||
return r, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (u *RBAC) GetRole(ctx context.Context, name string) (*model.Role, error) {
|
||||
var r model.Role
|
||||
if err := u.store.Session(ctx).Take(&r, "name = ?", name).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
func (u *RBAC) newPrivilege(ctx context.Context, code, label string, parent string, scope string) (*model.Privilege, error) {
|
||||
p := &model.Privilege{Code: code, Label: label, Parent: parent, Scope: scope}
|
||||
|
||||
codes := strings.SplitN(code, ":", 4)
|
||||
if len(codes) != 4 {
|
||||
return nil, fmt.Errorf("invalid code format")
|
||||
}
|
||||
|
||||
wailcard := false
|
||||
for _, item := range codes {
|
||||
if item == "*" {
|
||||
wailcard = true
|
||||
}
|
||||
|
||||
if wailcard && item != "*" {
|
||||
return nil, fmt.Errorf("invalid code format")
|
||||
}
|
||||
|
||||
if len(item) > 8 {
|
||||
return nil, fmt.Errorf("invalid code format: code snippet too long")
|
||||
}
|
||||
}
|
||||
|
||||
if codes[0] != "*" {
|
||||
if _, err := u.GetScopeGroup(ctx, codes[0]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := u.store.Session(ctx).Create(p).Error; err != nil {
|
||||
return p, err
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (u *RBAC) newUser(ctx context.Context, target *model.User) (*model.User, error) {
|
||||
result := u.store.Session(ctx).
|
||||
Create(target)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
if result.RowsAffected != 1 {
|
||||
return nil, fmt.Errorf("invalid rows affected")
|
||||
}
|
||||
|
||||
return target, nil
|
||||
}
|
||||
83
pkg/rbac/rbac.go
Normal file
83
pkg/rbac/rbac.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package rbac
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"uauth/model"
|
||||
"uauth/pkg/cache"
|
||||
"uauth/pkg/store"
|
||||
"uauth/tool"
|
||||
)
|
||||
|
||||
type RBAC struct {
|
||||
cache cache.Cache
|
||||
store store.Store
|
||||
}
|
||||
|
||||
var (
|
||||
Default *RBAC
|
||||
)
|
||||
|
||||
func New(store store.Store, cache cache.Cache) (*RBAC, error) {
|
||||
var (
|
||||
err error
|
||||
u = &RBAC{
|
||||
store: store,
|
||||
cache: cache,
|
||||
}
|
||||
rootPrivilege *model.Privilege
|
||||
rootRole *model.Role
|
||||
rootScope *model.Scope
|
||||
rootUser *model.User
|
||||
)
|
||||
|
||||
if err = u.store.Session(tool.Timeout()).AutoMigrate(
|
||||
&model.Scope{},
|
||||
&model.Privilege{},
|
||||
&model.Role{},
|
||||
&model.User{},
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("urbac migrate err: %w", err)
|
||||
}
|
||||
|
||||
if rootPrivilege, err = u.newPrivilege(tool.Timeout(), "*:*:*:*", "admin", "", "*"); err != nil {
|
||||
if !strings.Contains(strings.ToLower(err.Error()), "unique") {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if rootRole, err = u.newRole(tool.Timeout(), "admin", "管理员", "", rootPrivilege); err != nil {
|
||||
if !strings.Contains(strings.ToLower(err.Error()), "unique") {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if rootScope, err = u.newScope(tool.Timeout(), "*", "全部", ""); err != nil {
|
||||
if !strings.Contains(strings.ToLower(err.Error()), "unique") {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
rootUser = &model.User{
|
||||
Username: "admin",
|
||||
Password: tool.NewPassword("123456"),
|
||||
Status: model.StatusActive,
|
||||
Nickname: "管理员",
|
||||
RoleNames: []string{rootRole.Code},
|
||||
}
|
||||
|
||||
if _, err = u.newUser(tool.Timeout(3), rootUser); err != nil {
|
||||
if !strings.Contains(strings.ToLower(err.Error()), "unique") {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
_ = rootScope
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func Init(store store.Store, cache cache.Cache) (err error) {
|
||||
Default, err = New(store, cache)
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user