184 lines
4.9 KiB
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
|
|
}
|