New registration flow
This commit is contained in:
parent
1c6d2a04c3
commit
44b2dfc6d1
22 changed files with 374 additions and 82 deletions
|
|
@ -86,4 +86,8 @@ dd {
|
|||
.radio { display: inline-block }
|
||||
.field { margin-bottom: 1rem; max-width: 500px; }
|
||||
.field > label { margin-bottom: .25rem; }
|
||||
.field > * { display: block; width: 100%; box-sizing: border-box; }
|
||||
.field > * { display: block; width: 100%; box-sizing: border-box; }
|
||||
|
||||
.info {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
|
@ -4,12 +4,16 @@ import "os"
|
|||
|
||||
type (
|
||||
Config struct {
|
||||
DatabaseURL string
|
||||
SessionKey string
|
||||
Env string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
AssetsDir string
|
||||
DatabaseURL string
|
||||
SessionKey string
|
||||
Env string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
AssetsDir string
|
||||
EmailUsername string
|
||||
EmailPassword string
|
||||
EmailHost string
|
||||
EmailHostAddr string
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,15 +8,17 @@ import (
|
|||
)
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Password string
|
||||
Hash []byte
|
||||
Homepage string
|
||||
About string
|
||||
Style string
|
||||
Picture string
|
||||
Email string
|
||||
CreatedAt time.Time
|
||||
Name string
|
||||
Password string
|
||||
Hash []byte
|
||||
Homepage string
|
||||
About string
|
||||
Picture string
|
||||
Email string
|
||||
SignupEmail string
|
||||
SignupMsg string
|
||||
Active bool
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (u User) Validate() error {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
const schemaVersion = 9
|
||||
const schemaVersion = 11
|
||||
|
||||
func Migrate(db *sql.DB) {
|
||||
var currentVersion int
|
||||
|
|
|
|||
|
|
@ -25,6 +25,15 @@ create table statuses
|
|||
created_at timestamp with time zone DEFAULT now()
|
||||
);
|
||||
`,
|
||||
"schema_version_10": `alter table users
|
||||
add column signup_email TEXT not null DEFAULT '',
|
||||
add column signup_msg TEXT not null DEFAULT '',
|
||||
add column active bool default false;
|
||||
|
||||
-- All existing users are active
|
||||
update users set active=true;`,
|
||||
"schema_version_11": `ALTER TABLE statuses
|
||||
ALTER COLUMN face TYPE VARCHAR(2);`,
|
||||
"schema_version_2": `alter table users
|
||||
add column status_id int references statuses(id);
|
||||
`,
|
||||
|
|
|
|||
7
storage/sql/schema_version_10.sql
Normal file
7
storage/sql/schema_version_10.sql
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
alter table users
|
||||
add column signup_email TEXT not null DEFAULT '',
|
||||
add column signup_msg TEXT not null DEFAULT '',
|
||||
add column active bool default false;
|
||||
|
||||
-- All existing users are active
|
||||
update users set active=true;
|
||||
2
storage/sql/schema_version_11.sql
Normal file
2
storage/sql/schema_version_11.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE statuses
|
||||
ALTER COLUMN face TYPE VARCHAR(2);
|
||||
|
|
@ -94,6 +94,24 @@ func (s *Storage) StatusByUsername(user string, perPage int, page int64) ([]mode
|
|||
return statuses, false, err
|
||||
}
|
||||
|
||||
func (s *Storage) StatusFeed() ([]model.Status, error) {
|
||||
rows, err := s.db.Query(statusQueryBuilder{
|
||||
limit: strconv.Itoa(20),
|
||||
}.build())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var statuses []model.Status
|
||||
for rows.Next() {
|
||||
post, err := s.populateStatus(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
statuses = append(statuses, post)
|
||||
}
|
||||
return statuses, err
|
||||
}
|
||||
|
||||
func (s *Storage) Statuses(page int64, perPage int) ([]model.Status, bool, error) {
|
||||
rows, err := s.db.Query(statusQueryBuilder{
|
||||
limit: strconv.Itoa(perPage + 1),
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"status/model"
|
||||
)
|
||||
|
||||
const queryFindName = `SELECT name, hash, created_at, homepage, about, picture, email FROM users WHERE name=lower($1);`
|
||||
const queryFindName = `SELECT name, hash, created_at, homepage, about, picture, email, active, signup_email FROM users WHERE name=lower($1);`
|
||||
|
||||
func (s *Storage) queryUser(q string, params ...interface{}) (user model.User, err error) {
|
||||
err = s.db.QueryRow(q, params...).Scan(&user.Name, &user.Hash, &user.CreatedAt, &user.Homepage, &user.About, &user.Picture, &user.Email)
|
||||
err = s.db.QueryRow(q, params...).Scan(&user.Name, &user.Hash, &user.CreatedAt, &user.Homepage, &user.About, &user.Picture, &user.Email, &user.Active, &user.SignupEmail)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -17,7 +18,10 @@ func (s *Storage) VerifyUser(user model.User) (model.User, error) {
|
|||
return u, err
|
||||
}
|
||||
if err := user.CompareHashToPassword(u.Hash); err != nil {
|
||||
return u, err
|
||||
return u, errors.New("incorrect password")
|
||||
}
|
||||
if !u.Active {
|
||||
return u, errors.New("user not active")
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
|
@ -37,12 +41,12 @@ func (s *Storage) CreateUser(user model.User) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
insertUser := `INSERT INTO users (name, hash) VALUES (lower($1), $2)`
|
||||
insertUser := `INSERT INTO users (name, hash, email, signup_email, signup_msg) VALUES (lower($1), $2, $3, $4, $5)`
|
||||
statement, err := s.db.Prepare(insertUser)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = statement.Exec(user.Name, hash)
|
||||
_, err = statement.Exec(user.Name, hash, user.Email, user.SignupEmail, user.SignupMsg)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -63,13 +67,34 @@ func (s *Storage) Users() ([]string, error) {
|
|||
return users, nil
|
||||
}
|
||||
|
||||
func (s *Storage) DeleteUser(username string) error {
|
||||
stmt, err := s.db.Prepare(`DELETE from status WHERE author = $1;`)
|
||||
func (s *Storage) InactiveUsers() ([]model.User, error) {
|
||||
rows, err := s.db.Query("select name, signup_email, signup_msg from users where active is false")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var users []model.User
|
||||
for rows.Next() {
|
||||
var user model.User
|
||||
err := rows.Scan(&user.Name, &user.SignupEmail, &user.SignupMsg)
|
||||
if err != nil {
|
||||
return users, err
|
||||
}
|
||||
users = append(users, user)
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (s *Storage) ActivateUser(name string) error {
|
||||
stmt, err := s.db.Prepare(`UPDATE users SET active = true WHERE name = $1;`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = stmt.Exec(username)
|
||||
stmt, err = s.db.Prepare(`DELETE from users WHERE name = $1;`)
|
||||
_, err = stmt.Exec(name)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Storage) DeleteUser(username string) error {
|
||||
stmt, err := s.db.Prepare(`DELETE from users WHERE name = $1;`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
75
web/handler/admin_show.go
Normal file
75
web/handler/admin_show.go
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (h *Handler) showAdminView(w http.ResponseWriter, r *http.Request) {
|
||||
protectClickJacking(w)
|
||||
username, err := h.getUser(r)
|
||||
if err != nil {
|
||||
unauthorized(w)
|
||||
return
|
||||
}
|
||||
if username != "m15o" {
|
||||
unauthorized(w)
|
||||
return
|
||||
}
|
||||
users, err := h.storage.InactiveUsers()
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
h.renderLayout(w, "admin", map[string]interface{}{
|
||||
"inactive": users,
|
||||
}, username)
|
||||
}
|
||||
|
||||
func (h *Handler) activateUser(w http.ResponseWriter, r *http.Request) {
|
||||
protectClickJacking(w)
|
||||
username, err := h.getUser(r)
|
||||
if err != nil {
|
||||
unauthorized(w)
|
||||
return
|
||||
}
|
||||
if username != "m15o" {
|
||||
unauthorized(w)
|
||||
return
|
||||
}
|
||||
name := r.URL.Query().Get("name")
|
||||
if err := h.storage.ActivateUser(name); err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, fmt.Sprintf("/admin"), http.StatusFound)
|
||||
}
|
||||
|
||||
func (h *Handler) deleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
protectClickJacking(w)
|
||||
username, err := h.getUser(r)
|
||||
if err != nil {
|
||||
unauthorized(w)
|
||||
return
|
||||
}
|
||||
if username != "m15o" {
|
||||
unauthorized(w)
|
||||
return
|
||||
}
|
||||
name := r.URL.Query().Get("name")
|
||||
user, err := h.storage.UserByName(name)
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
if user.Active {
|
||||
serverError(w, errors.New("user is active"))
|
||||
return
|
||||
}
|
||||
if err := h.storage.DeleteUser(name); err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, fmt.Sprintf("/admin"), http.StatusFound)
|
||||
}
|
||||
47
web/handler/feed_show.go
Normal file
47
web/handler/feed_show.go
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gorilla/feeds"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (h *Handler) showFeedView(w http.ResponseWriter, r *http.Request) {
|
||||
now := time.Now()
|
||||
feed := &feeds.Feed{
|
||||
Title: "status.cafe",
|
||||
Link: &feeds.Link{Href: "https://status.cafe/"},
|
||||
Author: &feeds.Author{Name: "status.cafe"},
|
||||
Created: now,
|
||||
}
|
||||
|
||||
statuses, err := h.storage.StatusFeed()
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, status := range statuses {
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
feed.Items = append(feed.Items, &feeds.Item{
|
||||
Title: fmt.Sprintf("%s %s %s", status.User, status.Face, truncate(status.Content, 50)),
|
||||
Link: &feeds.Link{Href: fmt.Sprintf("https://status.cafe/users/%s/%d", status.User, status.Id)},
|
||||
Author: &feeds.Author{Name: status.User},
|
||||
Content: status.Content,
|
||||
Created: status.CreatedAt,
|
||||
})
|
||||
}
|
||||
atom, err := feed.ToAtom()
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Content-Type", "application/atom+xml")
|
||||
w.Write([]byte(atom))
|
||||
}
|
||||
|
|
@ -7,11 +7,14 @@ import (
|
|||
)
|
||||
|
||||
type RegisterForm struct {
|
||||
Username string
|
||||
Password string
|
||||
Confirm string
|
||||
Key string
|
||||
Error string
|
||||
Username string
|
||||
Password string
|
||||
Email string
|
||||
ShowEmail bool
|
||||
Answer string
|
||||
Confirm string
|
||||
Key string
|
||||
Error string
|
||||
}
|
||||
|
||||
func (f *RegisterForm) Validate() error {
|
||||
|
|
@ -33,9 +36,12 @@ func (f *RegisterForm) Validate() error {
|
|||
|
||||
func NewRegisterForm(r *http.Request) *RegisterForm {
|
||||
return &RegisterForm{
|
||||
Username: r.FormValue("name"),
|
||||
Password: r.FormValue("password"),
|
||||
Confirm: r.FormValue("password-confirm"),
|
||||
Key: r.FormValue("key"),
|
||||
Username: r.FormValue("name"),
|
||||
Password: r.FormValue("password"),
|
||||
Confirm: r.FormValue("password-confirm"),
|
||||
Email: r.FormValue("email"),
|
||||
ShowEmail: r.FormValue("show-email") == "1",
|
||||
Answer: r.FormValue("answer"),
|
||||
Key: r.FormValue("key"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,11 +52,17 @@ func New(cfg *config.Config, sess *session.Session, data *storage.Storage) (http
|
|||
sess: sess,
|
||||
}
|
||||
h.initTpl()
|
||||
|
||||
router.HandleFunc("/", h.showIndexView).Methods(http.MethodGet)
|
||||
router.HandleFunc("/login", h.showLoginView).Methods(http.MethodGet)
|
||||
router.HandleFunc("/check-login", h.checkLogin).Methods(http.MethodPost)
|
||||
router.HandleFunc("/register", h.handleRegister)
|
||||
router.HandleFunc("/logout", h.logout).Methods(http.MethodGet)
|
||||
router.HandleFunc("/feed.atom", h.showFeedView).Methods(http.MethodGet)
|
||||
|
||||
router.HandleFunc("/admin", h.showAdminView).Methods(http.MethodGet)
|
||||
router.HandleFunc("/activate-user", h.activateUser).Methods(http.MethodGet)
|
||||
router.HandleFunc("/delete-user", h.deleteUser).Methods(http.MethodGet)
|
||||
|
||||
router.HandleFunc("/settings", h.showSettingsView).Methods(http.MethodGet)
|
||||
router.HandleFunc("/settings-update", h.updateSettings).Methods(http.MethodPost)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,17 @@
|
|||
package handler
|
||||
|
||||
var TplMap = map[string]string{
|
||||
"admin": `{{ define "content" }}
|
||||
<section>
|
||||
<h1>Admin</h1>
|
||||
{{ range .inactive }}
|
||||
<div>
|
||||
<div><b>{{ .Name }}</b> ({{ .SignupEmail }}) <a href="/activate-user?name={{ .Name }}">Activate</a> | <a href="/delete-user?name={{ .Name }}">Delete</a></div>
|
||||
<p>{{ .SignupMsg }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
{{ end }}`,
|
||||
"confirm_remove_status": `{{ define "content" }}
|
||||
<section>
|
||||
Are you sure you you want to delete the following status?
|
||||
|
|
@ -149,6 +160,7 @@ var TplMap = map[string]string{
|
|||
<li><a href="/about/status-updater">status updater</a> bookmarklet</li>
|
||||
<li><a href="/current-status">status widget</a> for your homepage</li>
|
||||
</ul>
|
||||
<p><a href="/feed.atom">Subscribe via Atom</a></p>
|
||||
{{ else }}
|
||||
<h2>Welcome!</h2>
|
||||
<p>status.cafe is a place to share your current status.</p>
|
||||
|
|
@ -246,26 +258,54 @@ var TplMap = map[string]string{
|
|||
{{ end }}`,
|
||||
"register": `{{ define "content" }}
|
||||
<section>
|
||||
<h1>Register</h1>
|
||||
{{ if .form.Error }}
|
||||
<p>{{ .form.Error }}</p>
|
||||
{{ end }}
|
||||
<form action="/register" method="post" class="auth-form">
|
||||
<div class="field">
|
||||
<label for="name">Username</label>
|
||||
<input type="text" id="name" name="name" autocomplete="off" required autofocus/>
|
||||
<div class="cols">
|
||||
<div>
|
||||
<h1>Register</h1>
|
||||
<div class="info">
|
||||
<p>Registrations are manually approved to prevent spam and keep this little cafe a cool place to hang out.</p>
|
||||
<p>You should receive a confirmation within a few hours at the email you have provided. Make sure to enter a valid address!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" required/>
|
||||
<div>
|
||||
{{ if .form.Error }}
|
||||
<p>{{ .form.Error }}</p>
|
||||
{{ end }}
|
||||
<form action="/register" method="post" class="auth-form">
|
||||
<div class="field">
|
||||
<label for="name">Username</label>
|
||||
<input type="text" id="name" name="name" autocomplete="off" required autofocus/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" autocomplete="off" required autofocus/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="show-email">Show e-mail</label>
|
||||
<input type="checkbox" name="show-email" value="1" id="show-email" style="width: inherit;">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" required/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password-confirm">Confirm password</label>
|
||||
<input type="password" id="password-confirm" name="password-confirm" required/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="answer">How did you discover status.cafe?</label>
|
||||
<textarea id="answer" name="answer" required></textarea>
|
||||
</div>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password-confirm">Confirm password</label>
|
||||
<input type="password" id="password-confirm" name="password-confirm" required/>
|
||||
</div>
|
||||
<br>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}`,
|
||||
"register-success": `{{ define "content" }}
|
||||
<section>
|
||||
<h1>Thank you!</h1>
|
||||
<p>Thanks for registering, {{ .name }}!</p>
|
||||
<p>You should receive a confirmation email on {{ .email }} as soon as your account is activated.</p>
|
||||
</section>
|
||||
{{ end }}`,
|
||||
"settings": `{{ define "content" }}
|
||||
|
|
|
|||
11
web/handler/html/admin.html
Normal file
11
web/handler/html/admin.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{{ define "content" }}
|
||||
<section>
|
||||
<h1>Admin</h1>
|
||||
{{ range .inactive }}
|
||||
<div>
|
||||
<div><b>{{ .Name }}</b> ({{ .SignupEmail }}) <a href="/activate-user?name={{ .Name }}">Activate</a> | <a href="/delete-user?name={{ .Name }}">Delete</a></div>
|
||||
<p>{{ .SignupMsg }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
<li><a href="/about/status-updater">status updater</a> bookmarklet</li>
|
||||
<li><a href="/current-status">status widget</a> for your homepage</li>
|
||||
</ul>
|
||||
<p><a href="/feed.atom">Subscribe via Atom</a></p>
|
||||
{{ else }}
|
||||
<h2>Welcome!</h2>
|
||||
<p>status.cafe is a place to share your current status.</p>
|
||||
|
|
|
|||
7
web/handler/html/register-success.html
Normal file
7
web/handler/html/register-success.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{{ define "content" }}
|
||||
<section>
|
||||
<h1>Thank you!</h1>
|
||||
<p>Thanks for registering, {{ .name }}!</p>
|
||||
<p>You should receive a confirmation email on {{ .email }} as soon as your account is activated.</p>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
@ -1,24 +1,45 @@
|
|||
{{ define "content" }}
|
||||
<section>
|
||||
<h1>Register</h1>
|
||||
{{ if .form.Error }}
|
||||
<p>{{ .form.Error }}</p>
|
||||
{{ end }}
|
||||
<form action="/register" method="post" class="auth-form">
|
||||
<div class="field">
|
||||
<label for="name">Username</label>
|
||||
<input type="text" id="name" name="name" autocomplete="off" required autofocus/>
|
||||
<div class="cols">
|
||||
<div>
|
||||
<h1>Register</h1>
|
||||
<div class="info">
|
||||
<p>Registrations are manually approved to prevent spam and keep this little cafe a cool place to hang out.</p>
|
||||
<p>You should receive a confirmation within a few hours at the email you have provided. Make sure to enter a valid address!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" required/>
|
||||
<div>
|
||||
{{ if .form.Error }}
|
||||
<p>{{ .form.Error }}</p>
|
||||
{{ end }}
|
||||
<form action="/register" method="post" class="auth-form">
|
||||
<div class="field">
|
||||
<label for="name">Username</label>
|
||||
<input type="text" id="name" name="name" autocomplete="off" required autofocus/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" autocomplete="off" required autofocus/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="show-email">Show e-mail</label>
|
||||
<input type="checkbox" name="show-email" value="1" id="show-email" style="width: inherit;">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" required/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password-confirm">Confirm password</label>
|
||||
<input type="password" id="password-confirm" name="password-confirm" required/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="answer">How did you discover status.cafe?</label>
|
||||
<textarea id="answer" name="answer" required></textarea>
|
||||
</div>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password-confirm">Confirm password</label>
|
||||
<input type="password" id="password-confirm" name="password-confirm" required/>
|
||||
</div>
|
||||
<br>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
@ -13,7 +13,7 @@ func (h *Handler) checkLogin(w http.ResponseWriter, r *http.Request) {
|
|||
Password: f.Password,
|
||||
})
|
||||
if err != nil {
|
||||
f.Error = "incorrect password"
|
||||
f.Error = err.Error()
|
||||
h.renderLayout(w, "login", map[string]interface{}{
|
||||
"form": f,
|
||||
}, "")
|
||||
|
|
|
|||
|
|
@ -93,8 +93,13 @@ func (h *Handler) register(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
user := model.User{
|
||||
Name: f.Username,
|
||||
Password: f.Password,
|
||||
Name: f.Username,
|
||||
Password: f.Password,
|
||||
SignupEmail: f.Email,
|
||||
SignupMsg: f.Answer,
|
||||
}
|
||||
if f.ShowEmail {
|
||||
user.Email = f.Email
|
||||
}
|
||||
if err := user.Validate(); err != nil {
|
||||
showError(err)
|
||||
|
|
@ -108,10 +113,9 @@ func (h *Handler) register(w http.ResponseWriter, r *http.Request) {
|
|||
showError(err)
|
||||
return
|
||||
}
|
||||
if err := h.sess.Save(r, w, r.FormValue("name")); err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
h.renderLayout(w, "register-success", map[string]interface{}{
|
||||
"name": user.Name,
|
||||
"email": user.SignupEmail,
|
||||
}, "")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ func (h *Handler) showUserView(w http.ResponseWriter, r *http.Request) {
|
|||
"about": template.HTML(user.About),
|
||||
"picture": user.Picture,
|
||||
"email": user.Email,
|
||||
"style": template.CSS(user.Style),
|
||||
"showMore": showMore,
|
||||
"page": page,
|
||||
"next_page": page + 1,
|
||||
|
|
|
|||
|
|
@ -52,8 +52,12 @@ func (s *Session) Get(r *http.Request) (string, error) {
|
|||
if name == "" || !ok {
|
||||
return "", errors.New("error extracting session")
|
||||
}
|
||||
if ok := s.Storage.UserExists(name); !ok {
|
||||
return "", errors.New("user doesn't exit")
|
||||
u, err := s.Storage.UserByName(name)
|
||||
if err != nil {
|
||||
return "", errors.New("error getting user")
|
||||
}
|
||||
if !u.Active {
|
||||
return "", errors.New("user not active")
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue