From 3d96f93d1fcefb54c3a4ca0cc7cb6500470ed80f Mon Sep 17 00:00:00 2001 From: Sung Won Cho Date: Wed, 6 Jan 2021 21:08:34 +1100 Subject: [PATCH] Allow to register --- pkg/server/app/errors.go | 3 +++ pkg/server/app/users.go | 8 +++++++ pkg/server/controllers/users.go | 37 ++++++++++++++++++++++++++--- pkg/server/routes/routes.go | 10 ++++++-- pkg/server/views/users/login.gohtml | 2 +- pkg/server/views/users/new.gohtml | 2 +- 6 files changed, 55 insertions(+), 7 deletions(-) diff --git a/pkg/server/app/errors.go b/pkg/server/app/errors.go index 1afd842c..c7c469a7 100644 --- a/pkg/server/app/errors.go +++ b/pkg/server/app/errors.go @@ -15,4 +15,7 @@ var ( ErrNotFound appError = "not found" // ErrLoginInvalid is an error for invalid login ErrLoginInvalid appError = "invalid login" + + // ErrDuplicateEmail is an error for duplicat email + ErrDuplicateEmail appError = "duplicate email" ) diff --git a/pkg/server/app/users.go b/pkg/server/app/users.go index 0b6f46fe..1d3c9456 100644 --- a/pkg/server/app/users.go +++ b/pkg/server/app/users.go @@ -52,6 +52,14 @@ func createEmailPreference(user database.User, tx *gorm.DB) error { func (a *App) CreateUser(email, password string) (database.User, error) { tx := a.DB.Begin() + var count int + if err := tx.Model(database.Account{}).Where("email = ?", email).Count(&count).Error; err != nil { + return database.User{}, errors.Wrap(err, "counting user") + } + if count > 0 { + return database.User{}, ErrDuplicateEmail + } + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { tx.Rollback() diff --git a/pkg/server/controllers/users.go b/pkg/server/controllers/users.go index cf158a35..8479df18 100644 --- a/pkg/server/controllers/users.go +++ b/pkg/server/controllers/users.go @@ -5,6 +5,7 @@ import ( "github.com/dnote/dnote/pkg/server/app" "github.com/dnote/dnote/pkg/server/config" + "github.com/dnote/dnote/pkg/server/log" "github.com/dnote/dnote/pkg/server/views" ) @@ -14,7 +15,6 @@ func NewUsers(cfg config.Config, app *app.App) *Users { return &Users{ NewView: views.NewView(cfg.PageTemplateDir, views.Config{Title: "Join", Layout: "base"}, "users/new"), LoginView: views.NewView(cfg.PageTemplateDir, views.Config{Title: "Login", Layout: "base"}, "users/login"), - onPremise: cfg.OnPremise, app: app, } } @@ -24,10 +24,9 @@ type Users struct { NewView *views.View LoginView *views.View app *app.App - onPremise bool } -// New handles GET /register +// New renders user registration page func (u *Users) New(w http.ResponseWriter, r *http.Request) { var form RegistrationForm parseURLParams(r, &form) @@ -40,12 +39,43 @@ type RegistrationForm struct { Password string `schema:"password"` } +// Create handles register +func (u *Users) Create(w http.ResponseWriter, r *http.Request) { + vd := views.Data{} + var form RegistrationForm + if err := parseForm(r, &form); err != nil { + vd.SetAlert(err) + u.NewView.Render(w, r, vd) + return + } + + user, err := u.app.CreateUser(form.Email, form.Password) + if err != nil { + handleHTMLError(w, r, err, "creating user", u.NewView, &vd) + return + } + + session, err := u.app.SignIn(&user) + if err != nil { + handleHTMLError(w, r, err, "signing in a user", u.LoginView, &vd) + return + } + + setSessionCookie(w, session.Key, session.ExpiresAt) + http.Redirect(w, r, "/", http.StatusFound) + + if err := u.app.SendWelcomeEmail(form.Email); err != nil { + log.ErrorWrap(err, "sending welcome email") + } +} + // LoginForm is the form data for log in type LoginForm struct { Email string `schema:"email" json:"email"` Password string `schema:"password" json:"password"` } +// Login handles login func (u *Users) Login(w http.ResponseWriter, r *http.Request) { vd := views.Data{} @@ -71,6 +101,7 @@ func (u *Users) Login(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/", http.StatusFound) } +// Logout handles logout func (u *Users) Logout(w http.ResponseWriter, r *http.Request) { var vd views.Data diff --git a/pkg/server/routes/routes.go b/pkg/server/routes/routes.go index df8110b7..a773695a 100644 --- a/pkg/server/routes/routes.go +++ b/pkg/server/routes/routes.go @@ -28,13 +28,19 @@ func registerRoutes(router *mux.Router, mw middleware, app *app.App, routes []Ro // NewWebRoutes returns a new web routes func NewWebRoutes(app *app.App, c *controllers.Controllers) []Route { - return []Route{ + ret := []Route{ {"GET", "/", Auth(app, http.HandlerFunc(c.Notes.Index), &AuthParams{RedirectGuestsToLogin: true}), true}, - {"GET", "/new", http.HandlerFunc(c.Users.New), true}, {"GET", "/login", c.Users.LoginView, true}, {"POST", "/login", http.HandlerFunc(c.Users.Login), true}, {"POST", "/logout", http.HandlerFunc(c.Users.Logout), true}, } + + if !app.Config.DisableRegistration { + ret = append(ret, Route{"GET", "/join", http.HandlerFunc(c.Users.New), true}) + ret = append(ret, Route{"POST", "/join", http.HandlerFunc(c.Users.Create), true}) + } + + return ret } // NewAPIRoutes returns a new api routes diff --git a/pkg/server/views/users/login.gohtml b/pkg/server/views/users/login.gohtml index cad8debc..51f75521 100644 --- a/pkg/server/views/users/login.gohtml +++ b/pkg/server/views/users/login.gohtml @@ -13,7 +13,7 @@ diff --git a/pkg/server/views/users/new.gohtml b/pkg/server/views/users/new.gohtml index b99b6497..8273ea41 100644 --- a/pkg/server/views/users/new.gohtml +++ b/pkg/server/views/users/new.gohtml @@ -20,7 +20,7 @@ {{end}} {{define "signupForm"}} -
+ {{csrfField}}