package handlers import ( "errors" "net/http" "strings" "shop/internal/auth" ) type AuthHandler struct { pages *Pages auth *auth.Service } func NewAuthHandler(pages *Pages, authSvc *auth.Service) *AuthHandler { return &AuthHandler{pages: pages, auth: authSvc} } type authPageData struct { Layout Email string Name string Next string } func (h *AuthHandler) Register(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: h.showRegister(w, r, "", "") case http.MethodPost: h.postRegister(w, r) default: http.Error(w, "method not allowed", http.StatusMethodNotAllowed) } } func (h *AuthHandler) showRegister(w http.ResponseWriter, r *http.Request, errMsg string, email string) { data := authPageData{ Layout: h.pages.layout(r, "Регистрация", "register"), Email: email, } data.Error = errMsg if msg := flashMsg(r, "ok"); msg != "" { data.Success = msg } h.pages.render(w, "register.html", data) } func (h *AuthHandler) postRegister(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { h.showRegister(w, r, "Неверные данные формы", "") return } email := r.FormValue("email") name := r.FormValue("name") password := r.FormValue("password") password2 := r.FormValue("password_confirm") if password != password2 { h.showRegister(w, r, "Пароли не совпадают", email) return } _, err := h.auth.Register(r.Context(), email, password, name) if err != nil { h.showRegister(w, r, err.Error(), email) return } http.Redirect(w, r, "/login?ok=registered", http.StatusSeeOther) } func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: h.showLogin(w, r, "", "") case http.MethodPost: h.postLogin(w, r) default: http.Error(w, "method not allowed", http.StatusMethodNotAllowed) } } func (h *AuthHandler) showLogin(w http.ResponseWriter, r *http.Request, errMsg, email string) { data := authPageData{ Layout: h.pages.layout(r, "Вход", "login"), Email: email, Next: safeNext(r.URL.Query().Get("next")), } data.Error = errMsg data.Success = flashMsg(r, "ok") if data.Layout.User != nil { http.Redirect(w, r, "/account", http.StatusSeeOther) return } h.pages.render(w, "login.html", data) } func (h *AuthHandler) postLogin(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { h.showLogin(w, r, "Неверные данные формы", "") return } email := r.FormValue("email") password := r.FormValue("password") if err := h.auth.Login(r.Context(), w, email, password); err != nil { msg := err.Error() if errors.Is(err, auth.ErrInvalidCredentials) { msg = "Неверный email или пароль" } h.showLogin(w, r, msg, email) return } next := safeNext(r.FormValue("next")) http.Redirect(w, r, next+"?ok=login", http.StatusSeeOther) } func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } h.auth.Logout(r.Context(), w, r) http.Redirect(w, r, "/?ok=logout", http.StatusSeeOther) } func safeNext(next string) string { next = strings.TrimSpace(next) if next == "" || !strings.HasPrefix(next, "/") || strings.HasPrefix(next, "//") { return "/account" } return next }