Files
oslstats/internal/rbac/checker.go
2026-02-05 00:10:10 +11:00

112 lines
2.6 KiB
Go

package rbac
import (
"context"
"git.haelnorr.com/h/golib/hws"
"git.haelnorr.com/h/oslstats/internal/contexts"
"git.haelnorr.com/h/oslstats/internal/db"
"git.haelnorr.com/h/oslstats/internal/permissions"
"git.haelnorr.com/h/oslstats/internal/roles"
"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 {
return nil, errors.New("conn cannot be nil")
}
if s == nil {
return nil, errors.New("server 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
}