Files
storage-appliance/internal/auth/rbac.go

184 lines
4.9 KiB
Go

package auth
import (
"context"
"database/sql"
)
type Permission struct {
ID string
Name string
Description string
}
type Role struct {
ID string
Name string
Description string
}
type RBACStore struct {
DB *sql.DB
}
func NewRBACStore(db *sql.DB) *RBACStore {
return &RBACStore{DB: db}
}
// GetUserRoles retrieves all roles for a user
func (s *RBACStore) GetUserRoles(ctx context.Context, userID string) ([]Role, error) {
rows, err := s.DB.QueryContext(ctx,
`SELECT r.id, r.name, r.description FROM roles r
INNER JOIN user_roles ur ON r.id = ur.role_id
WHERE ur.user_id = ?`,
userID)
if err != nil {
return nil, err
}
defer rows.Close()
var roles []Role
for rows.Next() {
var role Role
if err := rows.Scan(&role.ID, &role.Name, &role.Description); err != nil {
return nil, err
}
roles = append(roles, role)
}
return roles, rows.Err()
}
// GetRolePermissions retrieves all permissions for a role
func (s *RBACStore) GetRolePermissions(ctx context.Context, roleID string) ([]Permission, error) {
rows, err := s.DB.QueryContext(ctx,
`SELECT p.id, p.name, p.description FROM permissions p
INNER JOIN role_permissions rp ON p.id = rp.permission_id
WHERE rp.role_id = ?`,
roleID)
if err != nil {
return nil, err
}
defer rows.Close()
var permissions []Permission
for rows.Next() {
var perm Permission
if err := rows.Scan(&perm.ID, &perm.Name, &perm.Description); err != nil {
return nil, err
}
permissions = append(permissions, perm)
}
return permissions, rows.Err()
}
// GetUserPermissions retrieves all permissions for a user (through their roles)
func (s *RBACStore) GetUserPermissions(ctx context.Context, userID string) ([]Permission, error) {
rows, err := s.DB.QueryContext(ctx,
`SELECT DISTINCT p.id, p.name, p.description FROM permissions p
INNER JOIN role_permissions rp ON p.id = rp.permission_id
INNER JOIN user_roles ur ON rp.role_id = ur.role_id
WHERE ur.user_id = ?`,
userID)
if err != nil {
return nil, err
}
defer rows.Close()
var permissions []Permission
for rows.Next() {
var perm Permission
if err := rows.Scan(&perm.ID, &perm.Name, &perm.Description); err != nil {
return nil, err
}
permissions = append(permissions, perm)
}
return permissions, rows.Err()
}
// UserHasPermission checks if a user has a specific permission
func (s *RBACStore) UserHasPermission(ctx context.Context, userID, permission string) (bool, error) {
var count int
err := s.DB.QueryRowContext(ctx,
`SELECT COUNT(*) FROM permissions p
INNER JOIN role_permissions rp ON p.id = rp.permission_id
INNER JOIN user_roles ur ON rp.role_id = ur.role_id
WHERE ur.user_id = ? AND p.name = ?`,
userID, permission).Scan(&count)
if err != nil {
return false, err
}
return count > 0, nil
}
// AssignRoleToUser assigns a role to a user
func (s *RBACStore) AssignRoleToUser(ctx context.Context, userID, roleID string) error {
_, err := s.DB.ExecContext(ctx,
`INSERT OR IGNORE INTO user_roles (user_id, role_id) VALUES (?, ?)`,
userID, roleID)
return err
}
// RemoveRoleFromUser removes a role from a user
func (s *RBACStore) RemoveRoleFromUser(ctx context.Context, userID, roleID string) error {
_, err := s.DB.ExecContext(ctx,
`DELETE FROM user_roles WHERE user_id = ? AND role_id = ?`,
userID, roleID)
return err
}
// GetAllRoles retrieves all roles
func (s *RBACStore) GetAllRoles(ctx context.Context) ([]Role, error) {
rows, err := s.DB.QueryContext(ctx,
`SELECT id, name, description FROM roles ORDER BY name`)
if err != nil {
return nil, err
}
defer rows.Close()
var roles []Role
for rows.Next() {
var role Role
if err := rows.Scan(&role.ID, &role.Name, &role.Description); err != nil {
return nil, err
}
roles = append(roles, role)
}
return roles, rows.Err()
}
// GetAllPermissions retrieves all permissions
func (s *RBACStore) GetAllPermissions(ctx context.Context) ([]Permission, error) {
rows, err := s.DB.QueryContext(ctx,
`SELECT id, name, description FROM permissions ORDER BY name`)
if err != nil {
return nil, err
}
defer rows.Close()
var permissions []Permission
for rows.Next() {
var perm Permission
if err := rows.Scan(&perm.ID, &perm.Name, &perm.Description); err != nil {
return nil, err
}
permissions = append(permissions, perm)
}
return permissions, rows.Err()
}
// AssignPermissionToRole assigns a permission to a role
func (s *RBACStore) AssignPermissionToRole(ctx context.Context, roleID, permissionID string) error {
_, err := s.DB.ExecContext(ctx,
`INSERT OR IGNORE INTO role_permissions (role_id, permission_id) VALUES (?, ?)`,
roleID, permissionID)
return err
}
// RemovePermissionFromRole removes a permission from a role
func (s *RBACStore) RemovePermissionFromRole(ctx context.Context, roleID, permissionID string) error {
_, err := s.DB.ExecContext(ctx,
`DELETE FROM role_permissions WHERE role_id = ? AND permission_id = ?`,
roleID, permissionID)
return err
}