82 lines
2.6 KiB
Go
82 lines
2.6 KiB
Go
package user
|
|
|
|
import (
|
|
"RenewCMS/api/pkg/apperr"
|
|
"RenewCMS/api/pkg/authtoken"
|
|
"RenewCMS/api/pkg/claims"
|
|
validator "RenewCMS/api/pkg/validator"
|
|
domain "RenewCMS/internal/domain/user"
|
|
"RenewCMS/internal/infrastructure/useCases"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type DeleteAccountHandler struct {
|
|
DeleteUseCase *useCases.DeleteOwnAccountUseCase
|
|
IsProduction bool
|
|
}
|
|
|
|
type DeleteAccountRequest struct {
|
|
CurrentPassword string `json:"current_password" validate:"required"`
|
|
Confirmation string `json:"confirmation" validate:"required,eq=DELETE"`
|
|
}
|
|
|
|
func NewDeleteAccountHandler(deleteAccount *useCases.DeleteOwnAccountUseCase, isProduction bool) *DeleteAccountHandler {
|
|
return &DeleteAccountHandler{DeleteUseCase: deleteAccount, IsProduction: isProduction}
|
|
}
|
|
|
|
func (h *DeleteAccountHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
|
var request DeleteAccountRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
|
http.Error(w, apperr.BodyErrorMessage, http.StatusBadRequest)
|
|
return
|
|
}
|
|
if err := validator.Validate.Struct(request); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
userId, ok := claims.UserId(r)
|
|
if !ok {
|
|
http.Error(w, apperr.UnauthorizedErrorMessage, http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
command := useCases.DeleteOwnAccountCommand{UserID: userId, CurrentPassword: request.CurrentPassword}
|
|
command.SessionID, command.SessionExpiresAt = sessionOf(r)
|
|
if err := h.DeleteUseCase.Delete(r.Context(), command); err != nil {
|
|
writeDeleteAccountError(w, err)
|
|
return
|
|
}
|
|
http.SetCookie(w, authtoken.ExpiredCookie(h.IsProduction))
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
func sessionOf(r *http.Request) (string, time.Time) {
|
|
tokenClaims, err := authtoken.FromContext(r.Context())
|
|
if err != nil {
|
|
return "", time.Time{}
|
|
}
|
|
id, _ := tokenClaims["jti"].(string)
|
|
expiry, _ := tokenClaims["exp"].(float64)
|
|
return id, time.Unix(int64(expiry), 0)
|
|
}
|
|
|
|
func writeDeleteAccountError(w http.ResponseWriter, err error) {
|
|
var lastAdmin domain.LastAdminError
|
|
switch {
|
|
case errors.Is(err, domain.ErrUserNotFound):
|
|
http.Error(w, apperr.UnauthorizedErrorMessage, http.StatusUnauthorized)
|
|
case errors.Is(err, domain.ErrWrongPassword):
|
|
http.Error(w, apperr.WrongPasswordErrorCode, http.StatusForbidden)
|
|
case errors.As(err, &lastAdmin):
|
|
w.Header().Set(apperr.LastRoleHeader, lastAdmin.Role)
|
|
http.Error(w, apperr.LastAdminErrorCode, http.StatusConflict)
|
|
case errors.Is(err, domain.ErrAccountNotDeletable):
|
|
http.Error(w, apperr.AccountNotDeletableErrorCode, http.StatusConflict)
|
|
default:
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
}
|
|
}
|