Compare commits

...

2 Commits

3 changed files with 50 additions and 4 deletions

View File

@ -105,6 +105,7 @@ var AllPermissions = []domain.PermissionSeed{
{Key: "users.update_self", Name: "Update Own Profile", Description: "Update own user profile", GroupName: "Users"},
{Key: "users.update_status", Name: "Update User Status", Description: "Activate/deactivate users", GroupName: "Users"},
{Key: "users.delete", Name: "Delete User", Description: "Delete a user", GroupName: "Users"},
{Key: "users.delete_self", Name: "Delete Own Account", Description: "Delete own user account", GroupName: "Users"},
{Key: "users.search", Name: "Search Users", Description: "Search users by name or phone", GroupName: "Users"},
{Key: "users.profile_completed", Name: "Check Profile Completed", Description: "Check if user profile is completed", GroupName: "Users"},
{Key: "users.upload_profile_picture", Name: "Upload Profile Picture", Description: "Upload user profile picture", GroupName: "Users"},
@ -250,7 +251,7 @@ var DefaultRolePermissions = map[string][]string{
"payments.direct_initiate", "payments.direct_verify_otp",
// Users (full access)
"users.list", "users.get", "users.update_self", "users.update_status", "users.delete", "users.search",
"users.list", "users.get", "users.update_self", "users.update_status", "users.delete", "users.delete_self", "users.search",
"users.profile_completed", "users.upload_profile_picture", "users.admin_profile", "users.user_profile",
// Admin management
@ -325,7 +326,7 @@ var DefaultRolePermissions = map[string][]string{
"payments.direct_initiate", "payments.direct_verify_otp",
// User (self-service)
"users.update_self", "users.profile_completed", "users.upload_profile_picture", "users.user_profile",
"users.update_self", "users.delete_self", "users.profile_completed", "users.upload_profile_picture", "users.user_profile",
// Notifications (own)
"notifications.ws_connect", "notifications.list_mine", "notifications.list_all",
@ -373,7 +374,7 @@ var DefaultRolePermissions = map[string][]string{
"payments.direct_initiate", "payments.direct_verify_otp",
// User (self-service)
"users.update_self", "users.profile_completed", "users.upload_profile_picture", "users.user_profile",
"users.update_self", "users.delete_self", "users.profile_completed", "users.upload_profile_picture", "users.user_profile",
// Notifications (own)
"notifications.ws_connect", "notifications.list_mine", "notifications.list_all",
@ -415,7 +416,7 @@ var DefaultRolePermissions = map[string][]string{
"question_set_personas.list",
// Users (view + search for support)
"users.list", "users.get", "users.search", "users.update_self", "users.profile_completed",
"users.list", "users.get", "users.search", "users.update_self", "users.delete_self", "users.profile_completed",
"users.upload_profile_picture", "users.user_profile",
// Notifications (own)

View File

@ -1714,6 +1714,50 @@ func (h *Handler) DeleteUser(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusOK, "User deleted successfully", nil, nil)
}
// DeleteMyUserAccount godoc
// @Summary Delete my user account
// @Description Deletes the authenticated learner's own account
// @Tags user
// @Produce json
// @Success 200 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 403 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security Bearer
// @Router /api/v1/user/me [delete]
func (h *Handler) DeleteMyUserAccount(c *fiber.Ctx) error {
userID, ok := c.Locals("user_id").(int64)
if !ok || userID <= 0 {
return fiber.NewError(fiber.StatusUnauthorized, "Invalid authenticated user")
}
role, ok := c.Locals("role").(domain.Role)
if !ok {
return fiber.NewError(fiber.StatusUnauthorized, "Invalid authenticated role")
}
if role != domain.RoleStudent {
return fiber.NewError(fiber.StatusForbidden, "Only learners can delete their own account using this endpoint")
}
if err := h.userSvc.DeleteUser(c.Context(), userID); err != nil {
h.mongoLoggerSvc.Error("Failed to self-delete user account",
zap.Int64("userID", userID),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete account:"+err.Error())
}
actorRole := string(role)
ip := c.IP()
ua := c.Get("User-Agent")
meta, _ := json.Marshal(map[string]interface{}{"deleted_user_id": userID, "self_delete": true})
go h.activityLogSvc.RecordAction(context.Background(), &userID, &actorRole, domain.ActionUserDeleted, domain.ResourceUser, &userID, fmt.Sprintf("Self-deleted user account ID: %d", userID), meta, &ip, &ua)
return response.WriteJSON(c, fiber.StatusOK, "Account deleted successfully", nil, nil)
}
type UpdateUserSuspendReq struct {
UserID int64 `json:"user_id" validate:"required" example:"123"`
Suspended bool `json:"suspended" example:"true"`

View File

@ -233,6 +233,7 @@ func (a *App) initAppRoutes() {
groupV1.Post("/user/checkPhoneEmailExist", h.CheckPhoneEmailExist)
groupV1.Get("/user/admin-profile", a.authMiddleware, a.RequirePermission("users.admin_profile"), h.AdminProfile)
groupV1.Get("/user/user-profile", a.authMiddleware, a.RequirePermission("users.user_profile"), h.GetUserProfile)
groupV1.Delete("/user/me", a.authMiddleware, a.RequirePermission("users.delete_self"), h.DeleteMyUserAccount)
groupV1.Get("/user/single/:id", a.authMiddleware, a.RequirePermission("users.get"), h.GetUserByID)
groupV1.Delete("/user/delete/:id", a.authMiddleware, a.RequirePermission("users.delete"), h.DeleteUser)
groupV1.Post("/user/search", a.authMiddleware, a.RequirePermission("users.search"), h.SearchUserByNameOrPhone)