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 }