Junie: fix token authentication
This commit is contained in:
174
data/auth.go
Normal file
174
data/auth.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
// Permission represents a system permission
|
||||
type Permission struct {
|
||||
ID string
|
||||
Resource string
|
||||
Action string
|
||||
Description string
|
||||
}
|
||||
|
||||
// AuthorizationService provides methods for checking user permissions
|
||||
type AuthorizationService struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
// NewAuthorizationService creates a new authorization service
|
||||
func NewAuthorizationService(db *sql.DB) *AuthorizationService {
|
||||
return &AuthorizationService{db: db}
|
||||
}
|
||||
|
||||
// UserHasPermission checks if a user has a specific permission for a resource and action
|
||||
func (a *AuthorizationService) UserHasPermission(userID, resource, action string) (bool, error) {
|
||||
query := `
|
||||
SELECT COUNT(*) FROM permissions p
|
||||
JOIN role_permissions rp ON p.id = rp.pid
|
||||
JOIN user_roles ur ON rp.rid = ur.rid
|
||||
WHERE ur.uid = ? AND p.resource = ? AND p.action = ?
|
||||
`
|
||||
|
||||
var count int
|
||||
err := a.db.QueryRow(query, userID, resource, action).Scan(&count)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to check user permission: %w", err)
|
||||
}
|
||||
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// GetUserPermissions returns all permissions for a user based on their roles
|
||||
func (a *AuthorizationService) GetUserPermissions(userID string) ([]Permission, error) {
|
||||
query := `
|
||||
SELECT DISTINCT p.id, p.resource, p.action, p.description FROM permissions p
|
||||
JOIN role_permissions rp ON p.id = rp.pid
|
||||
JOIN user_roles ur ON rp.rid = ur.rid
|
||||
WHERE ur.uid = ?
|
||||
`
|
||||
|
||||
rows, err := a.db.Query(query, userID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get user permissions: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var permissions []Permission
|
||||
for rows.Next() {
|
||||
var perm Permission
|
||||
if err := rows.Scan(&perm.ID, &perm.Resource, &perm.Action, &perm.Description); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan permission: %w", err)
|
||||
}
|
||||
permissions = append(permissions, perm)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error iterating permissions: %w", err)
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
// GetRolePermissions returns all permissions for a specific role
|
||||
func (a *AuthorizationService) GetRolePermissions(roleID string) ([]Permission, error) {
|
||||
query := `
|
||||
SELECT p.id, p.resource, p.action, p.description FROM permissions p
|
||||
JOIN role_permissions rp ON p.id = rp.pid
|
||||
WHERE rp.rid = ?
|
||||
`
|
||||
|
||||
rows, err := a.db.Query(query, roleID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get role permissions: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var permissions []Permission
|
||||
for rows.Next() {
|
||||
var perm Permission
|
||||
if err := rows.Scan(&perm.ID, &perm.Resource, &perm.Action, &perm.Description); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan permission: %w", err)
|
||||
}
|
||||
permissions = append(permissions, perm)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error iterating permissions: %w", err)
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
// GrantPermissionToRole grants a permission to a role
|
||||
func (a *AuthorizationService) GrantPermissionToRole(roleID, permissionID string) error {
|
||||
// Check if the role-permission relationship already exists
|
||||
checkQuery := `SELECT COUNT(*) FROM role_permissions WHERE rid = ? AND pid = ?`
|
||||
var count int
|
||||
err := a.db.QueryRow(checkQuery, roleID, permissionID).Scan(&count)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check role permission: %w", err)
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
return nil // Permission already granted
|
||||
}
|
||||
|
||||
// Generate a new ID for the role-permission relationship
|
||||
id := GenerateID()
|
||||
|
||||
// Insert the new role-permission relationship
|
||||
insertQuery := `INSERT INTO role_permissions (id, rid, pid) VALUES (?, ?, ?)`
|
||||
_, err = a.db.Exec(insertQuery, id, roleID, permissionID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to grant permission to role: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevokePermissionFromRole revokes a permission from a role
|
||||
func (a *AuthorizationService) RevokePermissionFromRole(roleID, permissionID string) error {
|
||||
query := `DELETE FROM role_permissions WHERE rid = ? AND pid = ?`
|
||||
_, err := a.db.Exec(query, roleID, permissionID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to revoke permission from role: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAllPermissions returns all permissions in the system
|
||||
func (a *AuthorizationService) GetAllPermissions() ([]Permission, error) {
|
||||
query := `SELECT id, resource, action, description FROM permissions`
|
||||
|
||||
rows, err := a.db.Query(query)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get permissions: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var permissions []Permission
|
||||
for rows.Next() {
|
||||
var perm Permission
|
||||
if err := rows.Scan(&perm.ID, &perm.Resource, &perm.Action, &perm.Description); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan permission: %w", err)
|
||||
}
|
||||
permissions = append(permissions, perm)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error iterating permissions: %w", err)
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
// GenerateID generates a unique ID for database records
|
||||
func GenerateID() string {
|
||||
return ulid.Make().String()
|
||||
}
|
||||
Reference in New Issue
Block a user