package auth import ( "RenewCMS/api/pkg/apperr" validator "RenewCMS/api/pkg/validator" "RenewCMS/internal/domain/invite" "RenewCMS/internal/domain/user" "RenewCMS/internal/infrastructure/useCases" "encoding/json" "errors" "net/http" "github.com/go-chi/jwtauth/v5" ) type AcceptInviteHandler struct { Token *jwtauth.JWTAuth GetInviteUseCase *useCases.GetInviteUseCase AcceptInviteUseCase *useCases.AcceptInviteUseCase IsProduction bool } type AcceptInviteRequest struct { Code string `json:"code" validate:"required"` Username string `json:"username" validate:"required,min=3,max=20"` Password string `json:"password" validate:"required,min=8"` } type inviteEmailResponse struct { Email string `json:"email"` } func NewAcceptInviteHandler(getInvite *useCases.GetInviteUseCase, acceptInvite *useCases.AcceptInviteUseCase, token *jwtauth.JWTAuth, isProduction bool) *AcceptInviteHandler { return &AcceptInviteHandler{ Token: token, GetInviteUseCase: getInvite, AcceptInviteUseCase: acceptInvite, IsProduction: isProduction, } } func (h *AcceptInviteHandler) GetInvite(w http.ResponseWriter, r *http.Request) { found, err := h.GetInviteUseCase.GetInvite(r.URL.Query().Get("c")) if err != nil { writeAcceptInviteError(w, err) return } body, err := json.Marshal(inviteEmailResponse{Email: found.Email}) if err != nil { http.Error(w, "Internal server error", http.StatusInternalServerError) return } w.Header().Set("Cache-Control", "no-store") _, _ = w.Write(body) } func (h *AcceptInviteHandler) AcceptInvite(w http.ResponseWriter, r *http.Request) { var request AcceptInviteRequest 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 } createdUser, err := h.AcceptInviteUseCase.AcceptInvite(useCases.AcceptInviteCommand{ Code: request.Code, Username: request.Username, Password: request.Password, }) if err != nil { writeAcceptInviteError(w, err) return } if err := setJwtCookie(w, h.Token, h.IsProduction, createdUser); err != nil { http.Error(w, "Internal server error", http.StatusInternalServerError) return } message, _ := json.Marshal(map[string]any{"message": "Invite accepted! HTTPonly jwt cookie created"}) _, _ = w.Write(message) } func writeAcceptInviteError(w http.ResponseWriter, err error) { switch { case errors.Is(err, invite.ErrInviteInvalid): http.Error(w, apperr.InviteInvalidErrorMessage, http.StatusNotFound) case errors.Is(err, invite.ErrInviteExpired): http.Error(w, apperr.InviteExpiredErrorMessage, http.StatusGone) case errors.Is(err, user.ErrUsernameTaken): http.Error(w, apperr.UsernameTakenErrorMessage, http.StatusConflict) case errors.Is(err, invite.ErrEmailHasAccount): http.Error(w, apperr.EmailHasAccountErrorMessage, http.StatusConflict) default: http.Error(w, "Internal server error", http.StatusInternalServerError) } }