package handler import ( "database/sql" "net/http" "time" "github.com/google/uuid" "github.com/zhang2092/go-url-shortener/internal/db" "github.com/zhang2092/go-url-shortener/internal/middleware" "github.com/zhang2092/go-url-shortener/internal/pkg/cookie" pwd "github.com/zhang2092/go-url-shortener/internal/pkg/password" "github.com/zhang2092/go-url-shortener/internal/templ" "github.com/zhang2092/go-url-shortener/internal/templ/models" ) func RegisterView(w http.ResponseWriter, r *http.Request) { templ.Register(w, r, &models.RegisterPageData{}) } func Register(store db.Store) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } email := r.PostFormValue("email") username := r.PostFormValue("username") password := r.PostFormValue("password") resp, ok := viladatorRegister(email, username, password) if !ok { templ.Register(w, r, resp) return } hashedPassword, err := pwd.BcryptHashPassword(password) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } arg := &db.CreateUserParams{ ID: uuid.Must(uuid.NewRandom()).String(), Username: username, HashedPassword: hashedPassword, Email: email, } _, err = store.CreateUser(r.Context(), arg) if err != nil { if store.IsUniqueViolation(err) { resp.Summary = "邮箱或名称已经存在" templ.Register(w, r, resp) return } resp.Summary = "请求网络错误,请刷新重试" templ.Register(w, r, resp) return } http.Redirect(w, r, "/login", http.StatusFound) } } func LoginView(w http.ResponseWriter, r *http.Request) { templ.Login(w, r, &models.LoginPageData{}) } func Login(store db.Store) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() if err := r.ParseForm(); err != nil { templ.Login(w, r, &models.LoginPageData{Summary: "请求网络错误,请刷新重试"}) return } email := r.PostFormValue("email") password := r.PostFormValue("password") resp, ok := viladatorLogin(email, password) if !ok { templ.Login(w, r, resp) return } ctx := r.Context() user, err := store.GetUserByEmail(ctx, email) if err != nil { if store.IsNoRows(sql.ErrNoRows) { resp.Summary = "邮箱或密码错误" templ.Login(w, r, resp) return } resp.Summary = "请求网络错误,请刷新重试" templ.Login(w, r, resp) return } err = pwd.BcryptComparePassword(user.HashedPassword, password) if err != nil { resp.Summary = "邮箱或密码错误" templ.Login(w, r, resp) return } encoded, err := middleware.Encode(middleware.AuthorizeCookie, &middleware.Authorize{ID: user.ID, Name: user.Username}) if err != nil { resp.Summary = "请求网络错误,请刷新重试(cookie)" templ.Login(w, r, resp) return } c := cookie.NewCookie(cookie.AuthorizeName, encoded, time.Now().Add(time.Duration(7200)*time.Second)) http.SetCookie(w, c) http.Redirect(w, r, "/", http.StatusFound) } } func Logout() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { cookie.DeleteCookie(w, cookie.AuthorizeName) http.Redirect(w, r, "/login", http.StatusFound) } } func viladatorRegister(email, username, password string) (*models.RegisterPageData, bool) { ok := true resp := &models.RegisterPageData{ Email: email, Username: username, Password: password, } if !ValidateRxEmail(email) { resp.EmailMsg = "请填写正确的邮箱地址" ok = false } if !ValidateRxUsername(username) { resp.UsernameMsg = "名称(6-20,字母,数字)" ok = false } if !ValidatePassword(password) { resp.PasswordMsg = "密码(8-20位)" ok = false } return resp, ok } func viladatorLogin(email, password string) (*models.LoginPageData, bool) { ok := true errs := &models.LoginPageData{ Email: email, Password: password, } if !ValidateRxEmail(email) { errs.EmailMsg = "请填写正确的邮箱地址" ok = false } if len(password) == 0 { errs.PasswordMsg = "请填写正确的密码" ok = false } return errs, ok }