adding new feature for updating new roles
This commit is contained in:
parent
f84ec65fbb
commit
e35edf3172
|
|
@ -1,89 +1,263 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"users_management/m/middleware"
|
||||
"users_management/m/usecase"
|
||||
"users_management/m/utils/common"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"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 UserManagementController struct {
|
||||
type UserRoleManagementController struct {
|
||||
userUC usecase.UsersUsecase
|
||||
rg *gin.RouterGroup
|
||||
}
|
||||
|
||||
func NewUserManagementController(userUC usecase.UsersUsecase, rg *gin.RouterGroup) *UserManagementController {
|
||||
return &UserManagementController{
|
||||
func NewUserRoleManagementController(userUC usecase.UsersUsecase, rg *gin.RouterGroup) *UserRoleManagementController {
|
||||
return &UserRoleManagementController{
|
||||
userUC: userUC,
|
||||
rg: rg,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *UserManagementController) Route() {
|
||||
users := c.rg.Group("/user-management")
|
||||
func (c *UserRoleManagementController) Route() {
|
||||
userRole := c.rg.Group("/user-role-management")
|
||||
userRole.Use(middleware.RequireAdminRole()) // Only Admin and Super Admin can access
|
||||
{
|
||||
// Only superadmin can manage user roles
|
||||
users.PUT("/role", middleware.RequireSuperAdminRole(), c.updateUserRole)
|
||||
|
||||
// Admins and superadmins can view all users
|
||||
users.GET("/users", middleware.RequireAdminRole(), c.getAllUsers)
|
||||
|
||||
// Users can view their own profile
|
||||
users.GET("/profile", c.getMyProfile)
|
||||
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 UpdateRoleRequest struct {
|
||||
NomorInduk string `json:"nomor_induk" binding:"required"`
|
||||
RoleName string `json:"role_name" binding:"required"`
|
||||
type UpdateUserRoleByIDRequest struct {
|
||||
NewRole string `json:"new_role" binding:"required,oneof=Teknisi Admin"`
|
||||
}
|
||||
|
||||
func (c *UserManagementController) updateUserRole(ctx *gin.Context) {
|
||||
var req UpdateRoleRequest
|
||||
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
|
||||
}
|
||||
|
||||
err := c.userUC.UpdateUserRole(req.NomorInduk, req.RoleName)
|
||||
if err != nil {
|
||||
common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
common.SingleResponses(ctx, "User role updated successfully", nil)
|
||||
}
|
||||
|
||||
func (c *UserManagementController) getAllUsers(ctx *gin.Context) {
|
||||
users, err := c.userUC.GetAllUsers()
|
||||
if err != nil {
|
||||
common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
common.SingleResponses(ctx, "Users retrieved successfully", users)
|
||||
}
|
||||
|
||||
func (c *UserManagementController) getMyProfile(ctx *gin.Context) {
|
||||
userID, exists := ctx.Get("userID")
|
||||
// Get current user role to check permissions
|
||||
currentUserRole, exists := ctx.Get("userRole")
|
||||
if !exists {
|
||||
common.ErrorResponses(ctx, http.StatusUnauthorized, "User ID not found")
|
||||
common.ErrorResponses(ctx, http.StatusUnauthorized, "User role not found")
|
||||
return
|
||||
}
|
||||
|
||||
nomorInduk, ok := userID.(string)
|
||||
currentUserRoleStr, ok := currentUserRole.(string)
|
||||
if !ok {
|
||||
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid user ID")
|
||||
common.ErrorResponses(ctx, http.StatusUnauthorized, "Invalid user role format")
|
||||
return
|
||||
}
|
||||
|
||||
user, err := c.userUC.GetUserByNomorInduk(nomorInduk)
|
||||
// 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
|
||||
}
|
||||
|
||||
common.SingleResponses(ctx, "User profile retrieved successfully", user)
|
||||
// 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")
|
||||
}
|
||||
|
|
@ -78,6 +78,7 @@ func (s *Server) setupController() {
|
|||
protectedRegistration.PUT("/approve/:id", middleware.RequireAdminRole(), controller.NewUserRegistrationController(s.ucManager.NewUserUsecase(), protected).ApproveUser)
|
||||
protectedRegistration.PUT("/reject/:id", middleware.RequireAdminRole(), controller.NewUserRegistrationController(s.ucManager.NewUserUsecase(), protected).RejectUser)
|
||||
}
|
||||
controller.NewUserRoleManagementController(s.ucManager.NewUserUsecase(), protected).Route()
|
||||
controller.NewUsersController(s.ucManager.NewUserUsecase(), s.ucManager.NewAuthUsecase(), protected).Route()
|
||||
controller.NewCountAssetsController(s.ucManager.NewCountAssetsUsecase(), protected).Route()
|
||||
controller.NewDeviceController(s.ucManager.NewDeviceUsecase(), protected, s.cfg).Route()
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ type UsersRepo interface {
|
|||
GetUserByID(userID uuid.UUID) (entity.User, error)
|
||||
GetUserByUsernameWithStatus(username string) (entity.User, error)
|
||||
CreateSuperAdminBypass(user entity.User) error
|
||||
UpdateUserRoleByID(userID uuid.UUID, roleID uuid.UUID) error
|
||||
UpdateUserRoleByUsername(username string, roleID uuid.UUID) error
|
||||
}
|
||||
|
||||
type usersRepo struct {
|
||||
|
|
@ -33,6 +35,14 @@ func NewUsersRepo(db *gorm.DB) UsersRepo {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *usersRepo) UpdateUserRoleByID(userID uuid.UUID, roleID uuid.UUID) error {
|
||||
return r.db.Model(&entity.User{}).Where("id = ?", userID).Update("role_id", roleID).Error
|
||||
}
|
||||
|
||||
func (r *usersRepo) UpdateUserRoleByUsername(username string, roleID uuid.UUID) error {
|
||||
return r.db.Model(&entity.User{}).Where("username = ?", username).Update("role_id", roleID).Error
|
||||
}
|
||||
|
||||
func (r *usersRepo) CreateSuperAdminBypass(user entity.User) error {
|
||||
return r.db.Create(&user).Error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ type UsersUsecase interface {
|
|||
RejectUser(userID uuid.UUID) error
|
||||
GetUserByUsernameWithStatus(username string) (entity.User, error)
|
||||
CreateSuperAdminBypass(user entity.User) error
|
||||
UpdateUserRoleByID(userID uuid.UUID, newRoleName string) error
|
||||
UpdateUserRoleByUsername(username, newRoleName string) error
|
||||
GetUserByID(userID uuid.UUID) (entity.User, error)
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -45,6 +48,45 @@ func (u *usersUsecase) CreateSuperAdminBypass(user entity.User) error {
|
|||
return u.userRepo.CreateSuperAdminBypass(user)
|
||||
}
|
||||
|
||||
// Add these implementations to the usersUsecase struct
|
||||
func (u *usersUsecase) UpdateUserRoleByID(userID uuid.UUID, newRoleName string) error {
|
||||
// Get the new role ID
|
||||
newRoleID, err := u.GetRoleByDepartment(newRoleName)
|
||||
if err != nil {
|
||||
return errors.New("invalid role name: " + err.Error())
|
||||
}
|
||||
|
||||
// Check if user exists
|
||||
_, err = u.userRepo.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return errors.New("user not found")
|
||||
}
|
||||
|
||||
// Update user role
|
||||
return u.userRepo.UpdateUserRoleByID(userID, newRoleID)
|
||||
}
|
||||
|
||||
func (u *usersUsecase) UpdateUserRoleByUsername(username, newRoleName string) error {
|
||||
// Get the new role ID
|
||||
newRoleID, err := u.GetRoleByDepartment(newRoleName)
|
||||
if err != nil {
|
||||
return errors.New("invalid role name: " + err.Error())
|
||||
}
|
||||
|
||||
// Check if user exists
|
||||
_, err = u.userRepo.GetUserByUsernameWithStatus(username)
|
||||
if err != nil {
|
||||
return errors.New("user not found")
|
||||
}
|
||||
|
||||
// Update user role by username
|
||||
return u.userRepo.UpdateUserRoleByUsername(username, newRoleID)
|
||||
}
|
||||
|
||||
func (u *usersUsecase) GetUserByID(userID uuid.UUID) (entity.User, error) {
|
||||
return u.userRepo.GetUserByID(userID)
|
||||
}
|
||||
|
||||
func (u *usersUsecase) RegisterUser(registerDTO dto.UserRegisterDTO) error {
|
||||
// Validate input
|
||||
if err := u.validate.Struct(registerDTO); err != nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue