structure: 确定基本结构(保持基本形式, 采用组合)

This commit is contained in:
loveuer
2024-11-01 17:47:33 +08:00
parent 9e8a47a7c6
commit 56cfd42bb9
52 changed files with 1003 additions and 176 deletions

110
pkg/rbac/create.go Normal file
View 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
View 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
}