mirror of
https://github.com/StarFleetCPTN/GoMFT.git
synced 2026-09-08 15:41:20 +02:00
144 lines
4.0 KiB
Go
144 lines
4.0 KiB
Go
package db
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// --- Role Store Methods ---
|
|
|
|
// CreateRole creates a new role record
|
|
func (db *DB) CreateRole(role *Role) error {
|
|
return db.Create(role).Error
|
|
}
|
|
|
|
// GetRole retrieves a role by ID, preloading permissions
|
|
func (db *DB) GetRole(id uint) (*Role, error) {
|
|
var role Role
|
|
// Assuming Permissions are handled correctly by GORM or custom type
|
|
err := db.First(&role, id).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &role, nil
|
|
}
|
|
|
|
// GetRoleByName retrieves a role by name, preloading permissions
|
|
func (db *DB) GetRoleByName(name string) (*Role, error) {
|
|
var role Role
|
|
err := db.Where("name = ?", name).First(&role).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &role, nil
|
|
}
|
|
|
|
// UpdateRole updates an existing role record
|
|
func (db *DB) UpdateRole(role *Role) error {
|
|
// Use Omit Users to prevent GORM from trying to update the many2many relationship directly here
|
|
return db.Omit("Users").Save(role).Error
|
|
}
|
|
|
|
// DeleteRole deletes a role after checking dependencies and removing assignments
|
|
func (db *DB) DeleteRole(id uint) error {
|
|
var role Role
|
|
if err := db.First(&role, id).Error; err != nil {
|
|
return fmt.Errorf("role not found: %w", err)
|
|
}
|
|
|
|
if role.IsSystemRole() {
|
|
return errors.New("cannot delete system role")
|
|
}
|
|
|
|
// Start transaction
|
|
tx := db.Begin()
|
|
if err := tx.Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// Manually delete role assignments from the join table
|
|
if err := tx.Exec("DELETE FROM user_roles WHERE role_id = ?", id).Error; err != nil {
|
|
tx.Rollback()
|
|
return fmt.Errorf("failed to delete role assignments: %w", err)
|
|
}
|
|
|
|
// Delete the role itself
|
|
if err := tx.Delete(&role).Error; err != nil {
|
|
tx.Rollback()
|
|
return fmt.Errorf("failed to delete role: %w", err)
|
|
}
|
|
|
|
// Commit transaction
|
|
return tx.Commit().Error
|
|
}
|
|
|
|
// ListRoles retrieves all roles
|
|
func (db *DB) ListRoles() ([]Role, error) {
|
|
var roles []Role
|
|
err := db.Find(&roles).Error
|
|
return roles, err
|
|
}
|
|
|
|
// GetUserRoles retrieves all roles assigned to a specific user ID
|
|
func (db *DB) GetUserRoles(userID uint) ([]Role, error) {
|
|
var user User
|
|
// Preload the Roles association
|
|
if err := db.Preload("Roles").First(&user, userID).Error; err != nil {
|
|
// Handle case where user might not be found vs. other errors
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, fmt.Errorf("user with ID %d not found", userID)
|
|
}
|
|
return nil, fmt.Errorf("failed to get user %d roles: %w", userID, err)
|
|
}
|
|
return user.Roles, nil
|
|
}
|
|
|
|
// AssignRoleToUser assigns a role to a user, handling the join table
|
|
func (db *DB) AssignRoleToUser(roleID, userID, assignedByID uint) error {
|
|
var role Role
|
|
if err := db.First(&role, roleID).Error; err != nil {
|
|
return fmt.Errorf("role with ID %d not found: %w", roleID, err)
|
|
}
|
|
var user User
|
|
if err := db.First(&user, userID).Error; err != nil {
|
|
return fmt.Errorf("user with ID %d not found: %w", userID, err)
|
|
}
|
|
|
|
// Use GORM's Association API for many2many
|
|
err := db.Model(&user).Association("Roles").Append(&role)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to assign role %d to user %d: %w", roleID, userID, err)
|
|
}
|
|
|
|
// Optionally, log the assignment (consider moving audit logging to a dedicated service/hook)
|
|
// db.Create(&AuditLog{...})
|
|
|
|
return nil
|
|
}
|
|
|
|
// UnassignRoleFromUser removes a role from a user, handling the join table
|
|
func (db *DB) UnassignRoleFromUser(roleID, userID, unassignedByID uint) error {
|
|
var role Role
|
|
if err := db.First(&role, roleID).Error; err != nil {
|
|
return fmt.Errorf("role with ID %d not found: %w", roleID, err)
|
|
}
|
|
var user User
|
|
// Need to preload roles to check if the association exists before deleting
|
|
if err := db.Preload("Roles").First(&user, userID).Error; err != nil {
|
|
return fmt.Errorf("user with ID %d not found: %w", userID, err)
|
|
}
|
|
|
|
// Use GORM's Association API for many2many deletion
|
|
err := db.Model(&user).Association("Roles").Delete(&role)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to unassign role %d from user %d: %w", roleID, userID, err)
|
|
}
|
|
|
|
// Optionally, log the unassignment
|
|
// db.Create(&AuditLog{...})
|
|
|
|
return nil
|
|
}
|