263 lines
8.4 KiB
Go
263 lines
8.4 KiB
Go
package controller
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"users_management/m/middleware"
|
|
"users_management/m/usecase"
|
|
"users_management/m/utils/common"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type UserRoleManagementController struct {
|
|
userUC usecase.UsersUsecase
|
|
rg *gin.RouterGroup
|
|
}
|
|
|
|
func NewUserRoleManagementController(userUC usecase.UsersUsecase, rg *gin.RouterGroup) *UserRoleManagementController {
|
|
return &UserRoleManagementController{
|
|
userUC: userUC,
|
|
rg: rg,
|
|
}
|
|
}
|
|
|
|
func (c *UserRoleManagementController) Route() {
|
|
userRole := c.rg.Group("/user-role-management")
|
|
userRole.Use(middleware.RequireAdminRole()) // Only Admin and Super Admin can access
|
|
{
|
|
userRole.PUT("/update/:id", c.updateUserRoleByID)
|
|
userRole.PUT("/update-by-username", c.updateUserRoleByUsername)
|
|
userRole.GET("/users", c.getAllUsersWithRoles)
|
|
userRole.GET("/available-roles", c.getAvailableRoles)
|
|
}
|
|
}
|
|
|
|
type UpdateUserRoleByIDRequest struct {
|
|
NewRole string `json:"new_role" binding:"required,oneof=Teknisi Admin"`
|
|
}
|
|
|
|
type UpdateUserRoleByUsernameRequest struct {
|
|
Username string `json:"username" binding:"required"`
|
|
NewRole string `json:"new_role" binding:"required,oneof=Teknisi Admin"`
|
|
}
|
|
|
|
func (c *UserRoleManagementController) updateUserRoleByID(ctx *gin.Context) {
|
|
// Get user ID from URL parameter
|
|
userIDStr := ctx.Param("id")
|
|
userID, err := uuid.Parse(userIDStr)
|
|
if err != nil {
|
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid user ID format")
|
|
return
|
|
}
|
|
|
|
var req UpdateUserRoleByIDRequest
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
common.ErrorResponses(ctx, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
|
|
// Get current user role to check permissions
|
|
currentUserRole, exists := ctx.Get("userRole")
|
|
if !exists {
|
|
common.ErrorResponses(ctx, http.StatusUnauthorized, "User role not found")
|
|
return
|
|
}
|
|
|
|
currentUserRoleStr, ok := currentUserRole.(string)
|
|
if !ok {
|
|
common.ErrorResponses(ctx, http.StatusUnauthorized, "Invalid user role format")
|
|
return
|
|
}
|
|
|
|
// Get target user to check current role and prevent invalid operations
|
|
targetUser, err := c.userUC.GetUserByID(userID)
|
|
if err != nil {
|
|
common.ErrorResponses(ctx, http.StatusNotFound, "User not found")
|
|
return
|
|
}
|
|
|
|
// Validate role change permissions
|
|
if err := c.validateRoleChange(currentUserRoleStr, targetUser.Role.Name, req.NewRole); err != nil {
|
|
common.ErrorResponses(ctx, http.StatusForbidden, err.Error())
|
|
return
|
|
}
|
|
|
|
// Update user role
|
|
err = c.userUC.UpdateUserRoleByID(userID, req.NewRole)
|
|
if err != nil {
|
|
common.ErrorResponses(ctx, http.StatusInternalServerError, "Failed to update user role: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// Get updated user info
|
|
updatedUser, err := c.userUC.GetUserByID(userID)
|
|
if err != nil {
|
|
// Role was updated but couldn't fetch updated info
|
|
common.SingleResponses(ctx, "User role updated successfully", gin.H{
|
|
"user_id": userID,
|
|
"new_role": req.NewRole,
|
|
})
|
|
return
|
|
}
|
|
|
|
response := gin.H{
|
|
"user_id": updatedUser.ID,
|
|
"username": updatedUser.Username,
|
|
"name": updatedUser.Name,
|
|
"previous_role": targetUser.Role.Name,
|
|
"new_role": updatedUser.Role.Name,
|
|
"updated_by": ctx.GetString("userName"),
|
|
}
|
|
|
|
common.SingleResponses(ctx, "User role updated successfully", response)
|
|
}
|
|
|
|
func (c *UserRoleManagementController) updateUserRoleByUsername(ctx *gin.Context) {
|
|
var req UpdateUserRoleByUsernameRequest
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
common.ErrorResponses(ctx, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
|
|
// Get current user role to check permissions
|
|
currentUserRole, exists := ctx.Get("userRole")
|
|
if !exists {
|
|
common.ErrorResponses(ctx, http.StatusUnauthorized, "User role not found")
|
|
return
|
|
}
|
|
|
|
currentUserRoleStr, ok := currentUserRole.(string)
|
|
if !ok {
|
|
common.ErrorResponses(ctx, http.StatusUnauthorized, "Invalid user role format")
|
|
return
|
|
}
|
|
|
|
// Get target user
|
|
targetUser, err := c.userUC.GetUserByUsernameWithStatus(req.Username)
|
|
if err != nil {
|
|
common.ErrorResponses(ctx, http.StatusNotFound, "User not found")
|
|
return
|
|
}
|
|
|
|
// Validate role change permissions
|
|
if err := c.validateRoleChange(currentUserRoleStr, targetUser.Role.Name, req.NewRole); err != nil {
|
|
common.ErrorResponses(ctx, http.StatusForbidden, err.Error())
|
|
return
|
|
}
|
|
|
|
// Update user role by username
|
|
err = c.userUC.UpdateUserRoleByUsername(req.Username, req.NewRole)
|
|
if err != nil {
|
|
common.ErrorResponses(ctx, http.StatusInternalServerError, "Failed to update user role: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// Get updated user info
|
|
updatedUser, err := c.userUC.GetUserByUsernameWithStatus(req.Username)
|
|
if err != nil {
|
|
// Role was updated but couldn't fetch updated info
|
|
common.SingleResponses(ctx, "User role updated successfully", gin.H{
|
|
"username": req.Username,
|
|
"new_role": req.NewRole,
|
|
})
|
|
return
|
|
}
|
|
|
|
response := gin.H{
|
|
"user_id": updatedUser.ID,
|
|
"username": updatedUser.Username,
|
|
"name": updatedUser.Name,
|
|
"previous_role": targetUser.Role.Name,
|
|
"new_role": updatedUser.Role.Name,
|
|
"updated_by": ctx.GetString("userName"),
|
|
}
|
|
|
|
common.SingleResponses(ctx, "User role updated successfully", response)
|
|
}
|
|
|
|
func (c *UserRoleManagementController) getAllUsersWithRoles(ctx *gin.Context) {
|
|
users, err := c.userUC.GetAllUsers()
|
|
if err != nil {
|
|
common.ErrorResponses(ctx, http.StatusInternalServerError, "Failed to get users: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// Filter and format response
|
|
var userList []gin.H
|
|
for _, user := range users {
|
|
// Only show approved users
|
|
if user.Status == "approved" {
|
|
userInfo := gin.H{
|
|
"id": user.ID,
|
|
"username": user.Username,
|
|
"name": user.Name,
|
|
"nomor_induk": user.NomorInduk,
|
|
"role": user.Role.Name,
|
|
"status": user.Status,
|
|
"created_at": user.CreatedAt,
|
|
"updated_at": user.UpdatedAt,
|
|
}
|
|
userList = append(userList, userInfo)
|
|
}
|
|
}
|
|
|
|
response := gin.H{
|
|
"users": userList,
|
|
"total": len(userList),
|
|
}
|
|
|
|
common.SingleResponses(ctx, "Users retrieved successfully", response)
|
|
}
|
|
|
|
func (c *UserRoleManagementController) getAvailableRoles(ctx *gin.Context) {
|
|
roles := []gin.H{
|
|
{
|
|
"name": "Teknisi",
|
|
"description": "Technical user with limited administrative access",
|
|
"can_be_assigned_by": []string{"Admin", "Super Admin"},
|
|
},
|
|
{
|
|
"name": "Admin",
|
|
"description": "Administrative user with full system access except user management",
|
|
"can_be_assigned_by": []string{"Admin", "Super Admin"},
|
|
},
|
|
}
|
|
|
|
currentUserRole := ctx.GetString("userRole")
|
|
|
|
response := gin.H{
|
|
"available_roles": roles,
|
|
"your_role": currentUserRole,
|
|
"note": "You can update users between Teknisi and Admin roles only",
|
|
}
|
|
|
|
common.SingleResponses(ctx, "Available roles for assignment", response)
|
|
}
|
|
|
|
// Helper function to validate role change permissions
|
|
func (c *UserRoleManagementController) validateRoleChange(currentUserRole, targetCurrentRole, newRole string) error {
|
|
// Super Admin can change any role to Teknisi or Admin
|
|
if currentUserRole == "Super Admin" {
|
|
return nil
|
|
}
|
|
|
|
// Admin can change roles but with some restrictions
|
|
if currentUserRole == "Admin" {
|
|
// Admin cannot change Super Admin roles
|
|
if targetCurrentRole == "Super Admin" {
|
|
return errors.New("cannot modify Super Admin users")
|
|
}
|
|
|
|
// Admin cannot assign Super Admin role
|
|
if newRole == "Super Admin" {
|
|
return errors.New("cannot assign Super Admin role")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Only Admin and Super Admin can change roles
|
|
return errors.New("insufficient permissions to change user roles")
|
|
} |