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 || 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 }