mirror of https://github.com/veypi/OneAuth.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
3.1 KiB
Go
156 lines
3.1 KiB
Go
|
1 week ago
|
//
|
||
|
|
// Copyright (C) 2024 veypi <i@veypi.com>
|
||
|
|
// 2025-03-04 16:08:06
|
||
|
|
// Distributed under terms of the MIT license.
|
||
|
|
//
|
||
|
|
|
||
|
|
package middleware
|
||
|
|
|
||
|
|
import (
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"github.com/veypi/vbase/cfg"
|
||
|
|
"github.com/veypi/vbase/models"
|
||
|
|
"github.com/veypi/vigo"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Checker 权限检查器
|
||
|
|
type Checker struct {
|
||
|
|
userID string
|
||
|
|
orgID string
|
||
|
|
roles []string
|
||
|
|
org *models.Org
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewChecker 创建权限检查器
|
||
|
|
func NewChecker(x *vigo.X) *Checker {
|
||
|
|
c := &Checker{}
|
||
|
|
|
||
|
|
if uid, ok := x.Get("user_id").(string); ok {
|
||
|
|
c.userID = uid
|
||
|
|
}
|
||
|
|
if oid, ok := x.Get("org_id").(string); ok {
|
||
|
|
c.orgID = oid
|
||
|
|
}
|
||
|
|
if roles, ok := x.Get("org_roles").(string); ok && roles != "" {
|
||
|
|
c.roles = strings.Split(roles, ",")
|
||
|
|
}
|
||
|
|
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsOrgOwner 检查用户是否是组织所有者
|
||
|
|
func (c *Checker) IsOrgOwner() bool {
|
||
|
|
if c.orgID == "" || c.userID == "" {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
if c.org != nil {
|
||
|
|
return c.org.OwnerID == c.userID
|
||
|
|
}
|
||
|
|
|
||
|
|
var org models.Org
|
||
|
|
if err := cfg.DB().First(&org, "id = ?", c.orgID).Error; err != nil {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
c.org = &org
|
||
|
|
|
||
|
|
return org.OwnerID == c.userID
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsOrgAdmin 检查用户是否是组织管理员
|
||
|
|
func (c *Checker) IsOrgAdmin() bool {
|
||
|
|
if c.IsOrgOwner() {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, roleID := range c.roles {
|
||
|
|
var role models.Role
|
||
|
|
if err := cfg.DB().First(&role, "id = ?", roleID).Error; err != nil {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if role.Code == models.RoleCodeAdmin {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
// HasRole 检查用户是否有指定角色
|
||
|
|
func (c *Checker) HasRole(roleCode string) bool {
|
||
|
|
for _, roleID := range c.roles {
|
||
|
|
var role models.Role
|
||
|
|
if err := cfg.DB().First(&role, "id = ?", roleID).Error; err != nil {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if role.Code == roleCode {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
// RequireAdmin 要求管理员权限
|
||
|
|
func (c *Checker) RequireAdmin() error {
|
||
|
|
if !c.IsOrgAdmin() {
|
||
|
|
return vigo.ErrForbidden.WithString("admin permission required")
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// RequireOwner 要求所有者权限
|
||
|
|
func (c *Checker) RequireOwner() error {
|
||
|
|
if !c.IsOrgOwner() {
|
||
|
|
return vigo.ErrForbidden.WithString("owner permission required")
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// RequireOrg 要求必须在组织上下文中
|
||
|
|
func (c *Checker) RequireOrg() error {
|
||
|
|
if c.orgID == "" {
|
||
|
|
return vigo.ErrArgInvalid.WithString("organization context required")
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// UserID 获取用户ID
|
||
|
|
func (c *Checker) UserID() string {
|
||
|
|
return c.userID
|
||
|
|
}
|
||
|
|
|
||
|
|
// OrgID 获取组织ID
|
||
|
|
func (c *Checker) OrgID() string {
|
||
|
|
return c.orgID
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetUserRoles 获取用户角色列表
|
||
|
|
func (c *Checker) GetUserRoles() []string {
|
||
|
|
return c.roles
|
||
|
|
}
|
||
|
|
|
||
|
|
// RequireAdmin 中间件:要求管理员权限
|
||
|
|
func RequireAdmin() func(*vigo.X) error {
|
||
|
|
return func(x *vigo.X) error {
|
||
|
|
checker := NewChecker(x)
|
||
|
|
return checker.RequireAdmin()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// RequireOwner 中间件:要求组织所有者权限
|
||
|
|
func RequireOwner() func(*vigo.X) error {
|
||
|
|
return func(x *vigo.X) error {
|
||
|
|
checker := NewChecker(x)
|
||
|
|
return checker.RequireOwner()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// RequireOrgContext 中间件:要求必须在组织上下文中
|
||
|
|
func RequireOrgContext() func(*vigo.X) error {
|
||
|
|
return func(x *vigo.X) error {
|
||
|
|
checker := NewChecker(x)
|
||
|
|
return checker.RequireOrg()
|
||
|
|
}
|
||
|
|
}
|