ref: 8ab5d39abc4297d008d438dde3adddd21575df36
parent: cceb70f7849948ee9a2972899ae4cfd1cb8daec5
author: Halfwit <halfwit@MacBook-Pro.hitronhub.home>
date: Thu Dec 12 12:07:17 PST 2019
Organize code a bit
--- a/router/forms.go
+++ b/router/forms.go
@@ -4,6 +4,7 @@
"fmt"
"net/http"
+ "github.com/olmaxmedical/olmax_go/session"
"golang.org/x/text/message"
)
@@ -46,4 +47,20 @@
}
}
return form, errors
+}
+
+func postform(p *Request, us session.Session, w http.ResponseWriter, r *http.Request) {
+ form, errors := parseform(p, w, r)
+ if len(errors) > 0 && errors[0] != "nil" {
+ // NOTE(halfwit) this stashes previous entries, but does not work
+ // on multipart forms (with file uploads)
+ us.Set("errors", errors)
+ // Maybe store form args instead here in session
+ url := fmt.Sprintf("%s?%s", r.URL.String(), r.Form.Encode())
+ http.Redirect(w, r, url, 302)
+ }
+ if form != nil {
+ us.Set("errors", []string{})
+ http.Redirect(w, r, form.Redirect, 302)
+ }
}
--- /dev/null
+++ b/router/handler.go
@@ -1,0 +1,121 @@
+package router
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/olmaxmedical/olmax_go/db"
+ "github.com/olmaxmedical/olmax_go/email"
+ "github.com/olmaxmedical/olmax_go/session"
+)
+
+// Handle specific endpoints
+
+type handler struct {
+ manager *session.Manager
+}
+
+func (d *handler) logout(w http.ResponseWriter, r *http.Request) {
+ d.manager.Destroy(w, r)
+ w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
+ http.Redirect(w, r, "/index.html", 302)
+}
+
+func (d *handler) normal(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
+ if r.URL.Path == "/" {
+ http.Redirect(w, r, "/index.html", 302)
+ return
+ }
+ user, status, us, role := getUser(d, w, r)
+ p := &Request{
+ printer: userLang(r),
+ status: status,
+ request: r,
+ user: user,
+ role: role,
+ session: us,
+ path: r.URL.Path[1:],
+ }
+
+ switch r.Method {
+ case "GET":
+ getpage(p, w)
+ case "POST":
+ postform(p, us, w, r)
+ }
+}
+
+// TODO: This will require actual client data from the database to populate the page
+func (d *handler) profile(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
+ user, status, us, role := getUser(d, w, r)
+ if status == "false" {
+ http.Redirect(w, r, "/login.html", 302)
+ return
+ }
+ if rd, ok := us.Get("redirect").(string); ok {
+ us.Delete("redirect")
+ http.Redirect(w, r, "/"+rd, 302)
+ return
+ }
+ p := &Request{
+ printer: userLang(r),
+ status: status,
+ session: us,
+ user: user,
+ role: role,
+ }
+ var data []byte
+ var err error
+ switch db.UserRole(user) {
+ case db.DoctorAuth:
+ if role != db.DoctorAuth {
+ http.Error(w, "Unauthorized", 401)
+ return
+ }
+ p.path = "doctor/profile.html"
+ data, err = getdata(p, "doctor")
+ case db.PatientAuth:
+ if role != db.PatientAuth {
+ http.Error(w, "Unauthorized", 401)
+ return
+ }
+ p.path = "patient/profile.html"
+ data, err = getdata(p, "patient")
+ default:
+ http.Error(w, "Forbidden", 403)
+ return
+ }
+ if err != nil {
+ http.Error(w, "Service Unavailable", 503)
+ return
+ }
+ fmt.Fprintf(w, "%s", data)
+}
+
+func (d *handler) activate(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
+ if len(r.URL.Path) != 46 && r.URL.Path[:9] != "/activate" {
+ http.Error(w, "Bad Request", 400)
+ return
+ }
+ email.ValidateSignupToken(w, r, r.URL.Path[10:])
+}
+
+func (d *handler) reset(w http.ResponseWriter, r *http.Request) {
+ if len(r.URL.Path) != 43 && r.URL.Path[:6] != "/reset" {
+ http.Error(w, "Bad Request", 400)
+ return
+ }
+ p := userLang(r)
+ user, _, us, _ := getUser(d, w, r)
+ token := email.NextResetToken(r.URL.Path[7:], user)
+ if token == "" {
+ us.Set("errors", [1]string{p.Sprint("Token expired")})
+ return
+ }
+ us.Set("token", token)
+ r.URL.Path = "/newpassword.html"
+ d.normal(w, r)
+}
--- a/router/pages.go
+++ b/router/pages.go
@@ -6,6 +6,7 @@
"errors"
"fmt"
"html/template"
+ "net/http"
"os"
"path"
"strings"
@@ -87,6 +88,29 @@
}
}
return errs
+}
+
+func getpage(p *Request, w http.ResponseWriter) {
+ var data []byte
+ var err error
+ switch db.UserRole(p.user) {
+ case db.DoctorAuth:
+ data, err = getdata(p, "doctor")
+ case db.PatientAuth:
+ data, err = getdata(p, "patient")
+ default:
+ data, err = getdata(p, "guest")
+ }
+ if err != nil && err.Error() == "Unauthorized" {
+ p.Session().Set("redirect", p.path)
+ http.Redirect(w, p.Request(), "/login.html", 302)
+ return
+ }
+ if err != nil {
+ http.Error(w, "Service Unavailable", 503)
+ return
+ }
+ fmt.Fprintf(w, "%s", data)
}
func getdata(p *Request, in string) ([]byte, error) {
--- a/router/run.go
+++ b/router/run.go
@@ -2,22 +2,16 @@
import (
"crypto/tls"
- "fmt"
"net/http"
"github.com/olmaxmedical/olmax_go/db"
- "github.com/olmaxmedical/olmax_go/email"
"github.com/olmaxmedical/olmax_go/session"
"golang.org/x/text/message"
)
-type handle struct {
- manager *session.Manager
-}
-
// Route - All requests pass through here first
func Route(manager *session.Manager) error {
- d := &handle{
+ d := &handler{
manager: manager,
}
css := http.FileServer(http.Dir("resources/css/"))
@@ -42,102 +36,7 @@
return srv.ListenAndServeTLS("cert.pem", "key.pem")
}
-func (d *handle) activate(w http.ResponseWriter, r *http.Request) {
- w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
- if len(r.URL.Path) != 46 && r.URL.Path[:9] != "/activate" {
- http.Error(w, "Bad Request", 400)
- return
- }
- email.ValidateSignupToken(w, r, r.URL.Path[10:])
-}
-
-func (d *handle) reset(w http.ResponseWriter, r *http.Request) {
- if len(r.URL.Path) != 43 && r.URL.Path[:6] != "/reset" {
- http.Error(w, "Bad Request", 400)
- return
- }
- p := userLang(r)
- user, _, us, _ := getUser(d, w, r)
- token := email.NextResetToken(r.URL.Path[7:], user)
- if token == "" {
- us.Set("errors", [1]string{p.Sprint("Token expired")})
- return
- }
- us.Set("token", token)
- r.URL.Path = "/newpassword.html"
- d.normal(w, r)
-}
-
-func (d *handle) normal(w http.ResponseWriter, r *http.Request) {
- w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
- if r.URL.Path == "/" {
- http.Redirect(w, r, "/index.html", 302)
- return
- }
- user, status, us, role := getUser(d, w, r)
- p := &Request{
- printer: userLang(r),
- status: status,
- request: r,
- user: user,
- role: role,
- session: us,
- path: r.URL.Path[1:],
- }
-
- switch r.Method {
- case "GET":
- get(p, w)
- case "POST":
- post(p, us, w, r)
- }
-}
-
-func (d *handle) logout(w http.ResponseWriter, r *http.Request) {
- d.manager.Destroy(w, r)
- w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
- http.Redirect(w, r, "/index.html", 302)
-}
-
-func post(p *Request, us session.Session, w http.ResponseWriter, r *http.Request) {
- form, errors := parseform(p, w, r)
- if len(errors) > 0 && errors[0] != "nil" {
- // NOTE(halfwit) this stashes previous entries, but does not work
- // on multipart forms (with file uploads)
- us.Set("errors", errors)
- // Maybe store form args instead here in session
- url := fmt.Sprintf("%s?%s", r.URL.String(), r.Form.Encode())
- http.Redirect(w, r, url, 302)
- }
- if form != nil {
- us.Set("errors", []string{})
- http.Redirect(w, r, form.Redirect, 302)
- }
-}
-
-func get(p *Request, w http.ResponseWriter) {
- var data []byte
- var err error
- switch db.UserRole(p.user) {
- case db.DoctorAuth:
- data, err = getdata(p, "doctor")
- case db.PatientAuth:
- data, err = getdata(p, "patient")
- default:
- data, err = getdata(p, "guest")
- }
- if err != nil && err.Error() == "Unauthorized" {
- p.Session().Set("redirect", p.path)
- http.Redirect(w, p.Request(), "/login.html", 302)
- return
- }
- if err != nil {
- http.Error(w, "Service Unavailable", 503)
- return
- }
- fmt.Fprintf(w, "%s", data)
-}
-
+// Some utility functions that are shared across pages and forms
func userLang(r *http.Request) *message.Printer {
accept := r.Header.Get("Accept-Language")
lang := r.FormValue("lang")
@@ -145,7 +44,7 @@
return message.NewPrinter(tag)
}
-func getUser(d *handle, w http.ResponseWriter, r *http.Request) (string, string, session.Session, db.Access) {
+func getUser(d *handler, w http.ResponseWriter, r *http.Request) (string, string, session.Session, db.Access) {
us := d.manager.Start(w, r)
user, ok1 := us.Get("username").(string)
status, ok2 := us.Get("login").(string)
@@ -160,52 +59,4 @@
us.Set("token", db.NewToken())
}
return user, status, us, role
-}
-
-// TODO: This will require actual client data from the database to populate the page
-func (d *handle) profile(w http.ResponseWriter, r *http.Request) {
- w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
- user, status, us, role := getUser(d, w, r)
- if status == "false" {
- http.Redirect(w, r, "/login.html", 302)
- return
- }
- if rd, ok := us.Get("redirect").(string); ok {
- us.Delete("redirect")
- http.Redirect(w, r, "/"+rd, 302)
- return
- }
- p := &Request{
- printer: userLang(r),
- status: status,
- session: us,
- user: user,
- role: role,
- }
- var data []byte
- var err error
- switch db.UserRole(user) {
- case db.DoctorAuth:
- if role != db.DoctorAuth {
- http.Error(w, "Unauthorized", 401)
- return
- }
- p.path = "doctor/profile.html"
- data, err = getdata(p, "doctor")
- case db.PatientAuth:
- if role != db.PatientAuth {
- http.Error(w, "Unauthorized", 401)
- return
- }
- p.path = "patient/profile.html"
- data, err = getdata(p, "patient")
- default:
- http.Error(w, "Forbidden", 403)
- return
- }
- if err != nil {
- http.Error(w, "Service Unavailable", 503)
- return
- }
- fmt.Fprintf(w, "%s", data)
}