Add registration/login/logout
This commit is contained in:
parent
8b054e454a
commit
9425061964
10 changed files with 260 additions and 6 deletions
|
|
@ -12,6 +12,17 @@ func (s *Storage) queryUser(q string, params ...interface{}) (user model.User, e
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Storage) VerifyUser(user model.User) (model.User, error) {
|
||||||
|
u, err := s.queryUser(queryFindName, user.Name)
|
||||||
|
if err != nil {
|
||||||
|
return u, err
|
||||||
|
}
|
||||||
|
if err := user.CompareHashToPassword(u.Hash); err != nil {
|
||||||
|
return u, err
|
||||||
|
}
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Storage) UserExists(name string) bool {
|
func (s *Storage) UserExists(name string) bool {
|
||||||
var rv bool
|
var rv bool
|
||||||
s.db.QueryRow(`SELECT true FROM users WHERE name=lower($1)`, name).Scan(&rv)
|
s.db.QueryRow(`SELECT true FROM users WHERE name=lower($1)`, name).Scan(&rv)
|
||||||
|
|
@ -66,4 +77,3 @@ func (s *Storage) DeleteUser(username string) error {
|
||||||
_, err = stmt.Exec(username)
|
_, err = stmt.Exec(username)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,11 +58,11 @@ func New(cfg *config.Config, sess *session.Session, data *storage.Storage) (http
|
||||||
|
|
||||||
// Index
|
// Index
|
||||||
router.HandleFunc("/", h.showIndexView).Methods(http.MethodGet)
|
router.HandleFunc("/", h.showIndexView).Methods(http.MethodGet)
|
||||||
//router.HandleFunc("/login", h.showLoginView).Methods(http.MethodGet)
|
router.HandleFunc("/login", h.showLoginView).Methods(http.MethodGet)
|
||||||
//router.HandleFunc("/check-login", h.checkLogin).Methods(http.MethodPost)
|
router.HandleFunc("/check-login", h.checkLogin).Methods(http.MethodPost)
|
||||||
//router.HandleFunc("/help", h.showHelpView).Methods(http.MethodGet)
|
//router.HandleFunc("/help", h.showHelpView).Methods(http.MethodGet)
|
||||||
//router.HandleFunc("/profile/{username}", h.showProfileView).Methods(http.MethodGet)
|
//router.HandleFunc("/profile/{username}", h.showProfileView).Methods(http.MethodGet)
|
||||||
//router.HandleFunc("/register", h.handleRegister)
|
router.HandleFunc("/register", h.handleRegister)
|
||||||
//router.HandleFunc("/editor", h.handleEditor)
|
//router.HandleFunc("/editor", h.handleEditor)
|
||||||
//router.HandleFunc("/upload", h.upload)
|
//router.HandleFunc("/upload", h.upload)
|
||||||
//router.HandleFunc("/files", h.handleFiles)
|
//router.HandleFunc("/files", h.handleFiles)
|
||||||
|
|
@ -71,7 +71,7 @@ func New(cfg *config.Config, sess *session.Session, data *storage.Storage) (http
|
||||||
//router.HandleFunc("/homepages", h.showHomepagesView).Methods(http.MethodGet)
|
//router.HandleFunc("/homepages", h.showHomepagesView).Methods(http.MethodGet)
|
||||||
//router.HandleFunc("/rename", h.handleRename)
|
//router.HandleFunc("/rename", h.handleRename)
|
||||||
//router.HandleFunc("/delete", h.handleDelete).Methods(http.MethodPost)
|
//router.HandleFunc("/delete", h.handleDelete).Methods(http.MethodPost)
|
||||||
//router.HandleFunc("/logout", h.logout).Methods(http.MethodGet)
|
router.HandleFunc("/logout", h.logout).Methods(http.MethodGet)
|
||||||
//router.PathPrefix("/").Handler(http.FileServer(http.Dir(cfg.AssetsDir)))
|
//router.PathPrefix("/").Handler(http.FileServer(http.Dir(cfg.AssetsDir)))
|
||||||
|
|
||||||
return router, nil
|
return router, nil
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,45 @@ package handler
|
||||||
var TplMap = map[string]string{
|
var TplMap = map[string]string{
|
||||||
"index": `{{ define "content" }}
|
"index": `{{ define "content" }}
|
||||||
<p>This is the index</p>
|
<p>This is the index</p>
|
||||||
|
{{ end }}`,
|
||||||
|
"login": `{{ define "content" }}
|
||||||
|
<h1>Login</h1>
|
||||||
|
{{ if .form.Error }}
|
||||||
|
<p>{{ .form.Error }}</p>
|
||||||
|
{{ end }}
|
||||||
|
<form action="/check-login" 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="password">Password</label>
|
||||||
|
<input type="password" id="password" name="password" required/>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
{{ end }}`,
|
||||||
|
"register": `{{ define "content" }}
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
{{ end }}`,
|
{{ end }}`,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
web/handler/html/login.html
Normal file
18
web/handler/html/login.html
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{{ define "content" }}
|
||||||
|
<h1>Login</h1>
|
||||||
|
{{ if .form.Error }}
|
||||||
|
<p>{{ .form.Error }}</p>
|
||||||
|
{{ end }}
|
||||||
|
<form action="/check-login" 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="password">Password</label>
|
||||||
|
<input type="password" id="password" name="password" required/>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
{{ end }}
|
||||||
22
web/handler/html/register.html
Normal file
22
web/handler/html/register.html
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{{ define "content" }}
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
{{ end }}
|
||||||
|
|
@ -18,5 +18,5 @@ func (h *Handler) showIndexView(w http.ResponseWriter, r *http.Request) {
|
||||||
// "News": news,
|
// "News": news,
|
||||||
//}, user)
|
//}, user)
|
||||||
|
|
||||||
h.renderLayout(w, "index", map[string]interface{}{}, "")
|
h.renderLayout(w, "index", nil, "")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
web/handler/login_check.go
Normal file
27
web/handler/login_check.go
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"status/model"
|
||||||
|
"status/web/handler/form"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *Handler) checkLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
f := form.NewLoginForm(r)
|
||||||
|
user, err := h.storage.VerifyUser(model.User{
|
||||||
|
Name: f.Username,
|
||||||
|
Password: f.Password,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
f.Error = "incorrect password"
|
||||||
|
h.renderLayout(w, "login", map[string]interface{}{
|
||||||
|
"form": f,
|
||||||
|
}, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := h.sess.Save(r, w, user.Name); err != nil {
|
||||||
|
serverError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
|
}
|
||||||
9
web/handler/login_show.go
Normal file
9
web/handler/login_show.go
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *Handler) showLoginView(w http.ResponseWriter, r *http.Request) {
|
||||||
|
h.renderLayout(w, "login", nil, "")
|
||||||
|
}
|
||||||
11
web/handler/logout.go
Normal file
11
web/handler/logout.go
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
func (h *Handler) logout(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if err := h.sess.Delete(w, r); err != nil {
|
||||||
|
serverError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
|
}
|
||||||
117
web/handler/register.go
Normal file
117
web/handler/register.go
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"html/template"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"status/model"
|
||||||
|
"status/web/handler/form"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *Handler) handleRegister(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case "GET":
|
||||||
|
h.showRegisterView(w, r)
|
||||||
|
case "POST":
|
||||||
|
h.register(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) showRegisterView(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case "GET":
|
||||||
|
h.renderLayout(w, "register", nil, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type keyStatus struct {
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Uses int `json:"uses"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//func verifyKey(key string) error {
|
||||||
|
// hc := http.Client{}
|
||||||
|
//
|
||||||
|
// f := url.Values{}
|
||||||
|
// f.Add("product_permalink", "YccHL")
|
||||||
|
// f.Add("license_key", key)
|
||||||
|
// req, err := http.NewRequest("POST", "https://api.gumroad.com/v2/licenses/verify", strings.NewReader(f.Encode()))
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
//
|
||||||
|
// resp, err := hc.Do(req)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if resp.Body != nil {
|
||||||
|
// defer resp.Body.Close()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// body, readErr := ioutil.ReadAll(resp.Body)
|
||||||
|
// if readErr != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ks := keyStatus{}
|
||||||
|
// jsonErr := json.Unmarshal(body, &ks)
|
||||||
|
// if jsonErr != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ks.Success != true || ks.Uses > 1 {
|
||||||
|
// return errors.New("invalid license key")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return nil
|
||||||
|
//}
|
||||||
|
|
||||||
|
func buildIndex(t *template.Template, name string) []byte {
|
||||||
|
html := bytes.NewBufferString("")
|
||||||
|
err := t.Execute(html, name)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return html.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) register(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
f := form.NewHomepageForm(r)
|
||||||
|
showError := func(err error) {
|
||||||
|
f.Error = err.Error()
|
||||||
|
h.renderLayout(w, "register", map[string]interface{}{"form": *f}, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := f.Validate(); err != nil {
|
||||||
|
showError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user := model.User{
|
||||||
|
Name: f.Username,
|
||||||
|
Password: f.Password,
|
||||||
|
}
|
||||||
|
if err := user.Validate(); err != nil {
|
||||||
|
showError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if h.storage.UserExists(user.Name) {
|
||||||
|
showError(errors.New("username already exists"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := h.storage.CreateUser(user); err != nil {
|
||||||
|
showError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := h.sess.Save(r, w, r.FormValue("name")); err != nil {
|
||||||
|
serverError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.renderLayout(w, "index", nil, user.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue