Allow to register

This commit is contained in:
Sung Won Cho 2021-01-06 21:08:34 +11:00
commit 3d96f93d1f
6 changed files with 55 additions and 7 deletions

View file

@ -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"
)

View file

@ -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()

View file

@ -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

View file

@ -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

View file

@ -13,7 +13,7 @@
<div class="footer">
<div class="callout">Don&#39;t have an account?</div>
<a href="/register" class="cta">
<a href="/join" class="cta">
Create account
</a>
</div>

View file

@ -20,7 +20,7 @@
{{end}}
{{define "signupForm"}}
<form action="/register" method="POST">
<form action="/join" method="POST">
{{csrfField}}
<div class="form-group">