diff --git a/storage/user.go b/storage/user.go index 70865de..e6eca0f 100644 --- a/storage/user.go +++ b/storage/user.go @@ -12,6 +12,17 @@ func (s *Storage) queryUser(q string, params ...interface{}) (user model.User, e 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 { var rv bool 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) return err } - diff --git a/web/handler/handler.go b/web/handler/handler.go index eadaa39..07635f7 100644 --- a/web/handler/handler.go +++ b/web/handler/handler.go @@ -58,11 +58,11 @@ func New(cfg *config.Config, sess *session.Session, data *storage.Storage) (http // Index 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("/login", h.showLoginView).Methods(http.MethodGet) + router.HandleFunc("/check-login", h.checkLogin).Methods(http.MethodPost) //router.HandleFunc("/help", h.showHelpView).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("/upload", h.upload) //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("/rename", h.handleRename) //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))) return router, nil diff --git a/web/handler/html.go b/web/handler/html.go index 1c50033..4820b29 100644 --- a/web/handler/html.go +++ b/web/handler/html.go @@ -5,5 +5,45 @@ package handler var TplMap = map[string]string{ "index": `{{ define "content" }}

This is the index

+{{ end }}`, + "login": `{{ define "content" }} +

Login

+{{ if .form.Error }} +

{{ .form.Error }}

+{{ end }} +
+
+ + +
+
+ + +
+
+ +
+{{ end }}`, + "register": `{{ define "content" }} +

Register

+{{ if .form.Error }} +

{{ .form.Error }}

+{{ end }} +
+
+ + +
+
+ + +
+
+ + +
+
+ +
{{ end }}`, } diff --git a/web/handler/html/login.html b/web/handler/html/login.html new file mode 100644 index 0000000..8254cfa --- /dev/null +++ b/web/handler/html/login.html @@ -0,0 +1,18 @@ +{{ define "content" }} +

Login

+{{ if .form.Error }} +

{{ .form.Error }}

+{{ end }} +
+
+ + +
+
+ + +
+
+ +
+{{ end }} \ No newline at end of file diff --git a/web/handler/html/register.html b/web/handler/html/register.html new file mode 100644 index 0000000..76bb101 --- /dev/null +++ b/web/handler/html/register.html @@ -0,0 +1,22 @@ +{{ define "content" }} +

Register

+{{ if .form.Error }} +

{{ .form.Error }}

+{{ end }} +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+{{ end }} \ No newline at end of file diff --git a/web/handler/index_show.go b/web/handler/index_show.go index 317ff4c..dd6e4d1 100644 --- a/web/handler/index_show.go +++ b/web/handler/index_show.go @@ -18,5 +18,5 @@ func (h *Handler) showIndexView(w http.ResponseWriter, r *http.Request) { // "News": news, //}, user) - h.renderLayout(w, "index", map[string]interface{}{}, "") + h.renderLayout(w, "index", nil, "") } diff --git a/web/handler/login_check.go b/web/handler/login_check.go new file mode 100644 index 0000000..81f9167 --- /dev/null +++ b/web/handler/login_check.go @@ -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) +} diff --git a/web/handler/login_show.go b/web/handler/login_show.go new file mode 100644 index 0000000..6e2143e --- /dev/null +++ b/web/handler/login_show.go @@ -0,0 +1,9 @@ +package handler + +import ( + "net/http" +) + +func (h *Handler) showLoginView(w http.ResponseWriter, r *http.Request) { + h.renderLayout(w, "login", nil, "") +} diff --git a/web/handler/logout.go b/web/handler/logout.go new file mode 100644 index 0000000..03c3784 --- /dev/null +++ b/web/handler/logout.go @@ -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) +} diff --git a/web/handler/register.go b/web/handler/register.go new file mode 100644 index 0000000..7d270c3 --- /dev/null +++ b/web/handler/register.go @@ -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) + } +}