rbac system first stage
This commit is contained in:
108
internal/rbac/checker.go
Normal file
108
internal/rbac/checker.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package rbac
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.haelnorr.com/h/golib/hws"
|
||||
"git.haelnorr.com/h/oslstats/internal/db"
|
||||
"git.haelnorr.com/h/oslstats/internal/permissions"
|
||||
"git.haelnorr.com/h/oslstats/internal/roles"
|
||||
"git.haelnorr.com/h/oslstats/pkg/contexts"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type Checker struct {
|
||||
conn *bun.DB
|
||||
s *hws.Server
|
||||
}
|
||||
|
||||
func NewChecker(conn *bun.DB, s *hws.Server) (*Checker, error) {
|
||||
if conn == nil || s == nil {
|
||||
return nil, errors.New("arguments cannot be nil")
|
||||
}
|
||||
return &Checker{conn: conn, s: s}, nil
|
||||
}
|
||||
|
||||
// UserHasPermission checks if user has a specific permission (uses cache)
|
||||
func (c *Checker) UserHasPermission(ctx context.Context, user *db.User, permission permissions.Permission) (bool, error) {
|
||||
if user == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Try cache first
|
||||
cache := contexts.Permissions(ctx)
|
||||
if cache != nil {
|
||||
if cache.HasWildcard {
|
||||
return true, nil
|
||||
}
|
||||
if has, exists := cache.Permissions[permission]; exists {
|
||||
return has, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to database
|
||||
tx, err := c.conn.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "conn.BeginTx")
|
||||
}
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
has, err := user.HasPermission(ctx, tx, permission)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return has, nil
|
||||
}
|
||||
|
||||
// UserHasRole checks if user has a specific role (uses cache)
|
||||
func (c *Checker) UserHasRole(ctx context.Context, user *db.User, role roles.Role) (bool, error) {
|
||||
if user == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
cache := contexts.Permissions(ctx)
|
||||
if cache != nil {
|
||||
if has, exists := cache.Roles[role]; exists {
|
||||
return has, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to database
|
||||
tx, err := c.conn.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "conn.BeginTx")
|
||||
}
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
return user.HasRole(ctx, tx, role)
|
||||
}
|
||||
|
||||
// UserHasAnyPermission checks if user has ANY of the given permissions
|
||||
func (c *Checker) UserHasAnyPermission(ctx context.Context, user *db.User, permissions ...permissions.Permission) (bool, error) {
|
||||
for _, perm := range permissions {
|
||||
has, err := c.UserHasPermission(ctx, user, perm)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if has {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// UserHasAllPermissions checks if user has ALL of the given permissions
|
||||
func (c *Checker) UserHasAllPermissions(ctx context.Context, user *db.User, permissions ...permissions.Permission) (bool, error) {
|
||||
for _, perm := range permissions {
|
||||
has, err := c.UserHasPermission(ctx, user, perm)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !has {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
Reference in New Issue
Block a user