Return 404 errors for missing resources.

Update login and register forms to return the right errors when the user
info can't be found.
This commit is contained in:
Victor Vrantchan
2021-02-20 17:48:04 -05:00
parent 524f9384f5
commit 7fd2c8b33f
7 changed files with 41 additions and 9 deletions

View File

@@ -129,11 +129,38 @@ func create(username, email, password string) (*User, error) {
type Error struct {
invalid map[string]string
// missingEmail gets set when the user tries to log in without a real email.
// This causes the frontend to respond with an "Invalid email or password" message.
// Might want to change this implementation later, just needed something quick.
missingEmail string
missingHash string
}
func (err Error) Invalid() map[string]string { return err.invalid }
func (err Error) Invalid() map[string]string {
switch {
case err.missingHash != "":
return map[string]string{
"confirmation_hash": "Confirmation token unknown or already used.",
}
case err.missingEmail != "":
return map[string]string{
"email": "Invalid email or password.",
"password": "Invalid email or password.",
}
default:
return err.invalid
}
}
func (err Error) Error() string {
switch {
case err.missingEmail != "":
return fmt.Sprintf("user with email %q not found", err.missingEmail)
case err.missingHash != "":
return fmt.Sprintf("user confirmation hash %q", err.missingHash)
}
switch len(err.invalid) {
case 0:
return "user validation failed"

View File

@@ -56,7 +56,7 @@ func (d *Postgres) ConfirmUser(ctx context.Context, confirmation string) error {
if tag, err := d.db.Exec(ctx, q, confirmation); err != nil {
return fmt.Errorf("set postgres confirmation_hash to NULL: %w", err)
} else if tag.RowsAffected() == 0 {
return errors.New("unknown confirmation_hash in postgres")
return Error{missingHash: confirmation}
}
return nil
@@ -79,7 +79,7 @@ func (d *Postgres) FindUserByEmail(ctx context.Context, email string) (*User, er
&u.CreatedAt,
&u.UpdatedAt,
); err == pgx.ErrNoRows {
return nil, fmt.Errorf("user (email %q) not found in postgres", email)
return nil, Error{missingEmail: email}
} else if err != nil {
return nil, err
}

View File

@@ -82,7 +82,7 @@ func (d *SQLite) ConfirmUser(ctx context.Context, confirmation string) error {
}
if conn.Changes() == 0 {
return errors.New("unknown confirmation_hash in sqlite")
return Error{missingHash: confirmation}
}
return nil
@@ -105,7 +105,7 @@ func (d *SQLite) FindUserByEmail(ctx context.Context, email string) (*User, erro
if found, err := stmt.Step(); err != nil {
return nil, err
} else if !found {
return nil, fmt.Errorf("user (email %q) not found in sqlite", email)
return nil, Error{missingEmail: email}
}
usr, err := sqliteUser(stmt)

View File

@@ -37,12 +37,12 @@ func (srv server) loginForm(w http.ResponseWriter, r *http.Request) {
usr, err := srv.userdb.FindUserByEmail(ctx, email)
if err != nil {
srv.http.Fail(ctx, w, err, "msg", "find user for auth")
srv.http.Fail(ctx, w, err, "login.tmpl", "msg", "find user for auth")
return
}
if err := usr.ValidatePassword(password); err != nil {
srv.http.Fail(ctx, w, err, "msg", "auth user")
srv.http.Fail(ctx, w, err, "login.tmpl", "msg", "auth user")
return
}

View File

@@ -70,7 +70,7 @@ func (srv server) registerConfirm(w http.ResponseWriter, r *http.Request) {
}
if err := srv.userdb.ConfirmUser(ctx, confirmation); err != nil {
srv.http.Fail(ctx, w, err, "msg", "confirm user", "confirmation_hash", confirmation)
srv.http.Fail(ctx, w, err, "msg", "register-confirmed.tmpl", "confirm user", "confirmation_hash", confirmation)
return
}

View File

@@ -182,6 +182,7 @@ func (srv *Server) Fail(ctx context.Context, w http.ResponseWriter, err error, k
return
}
tpl = "500.tmpl" // set back to Internal Server Error
srv.RenderTemplate(ctx, w, tpl, Data{}.
WithLog(err, keyvals...).
WithCode(http.StatusInternalServerError),

View File

@@ -6,8 +6,12 @@
<h3>Thank you for signing up</h3>
<div class="msg">
<p>
We confirmed your account. You can now use the site.
{{- if .errors -}}
<div class="invalid-input">{{ .errors.confirmation_hash }}</div>
{{ else }}
<a href="/login">Sign In</a>
We confirmed your account. You can now use the site.
{{ end }}
</p>
</div>
</div>