103 lines
3.1 KiB
Go
103 lines
3.1 KiB
Go
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(r.Context(), 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)
|
|
}
|
|
}
|