aboutsummaryrefslogtreecommitdiff
path: root/cmd/server/middleware.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/server/middleware.go')
-rw-r--r--cmd/server/middleware.go142
1 files changed, 142 insertions, 0 deletions
diff --git a/cmd/server/middleware.go b/cmd/server/middleware.go
new file mode 100644
index 0000000..5e4bf26
--- /dev/null
+++ b/cmd/server/middleware.go
@@ -0,0 +1,142 @@
+package main
+
+import (
+ "log"
+ "net/http"
+ "time"
+
+ jwt "github.com/dgrijalva/jwt-go"
+ "riedstra.dev/mitch/go-website/page"
+ "riedstra.dev/mitch/go-website/users"
+)
+
+func (a *App) Err5xx(w http.ResponseWriter, r *http.Request,
+ statusCode int, title, desc string) {
+ page.Render5xx(w, r, map[string]interface{}{
+ "Error": title,
+ "Description": desc,
+ }, statusCode)
+}
+
+func (a *App) Err500Default(w http.ResponseWriter, r *http.Request) {
+ a.Err5xx(w, r, http.StatusInternalServerError, "Internal server error",
+ "Internal server error.")
+}
+
+func (a *App) LogoutHandler(w http.ResponseWriter, r *http.Request) {
+ http.SetCookie(w, &http.Cookie{
+ Name: "Auth",
+ HttpOnly: a.auth.HTTPOnly,
+ SameSite: a.auth.SameSiteStrict,
+ Secure: a.auth.Secure,
+ Value: "logout",
+ Expires: time.Now().Add(time.Second * 15), //nolint
+ })
+
+ http.Redirect(w, r, "/", http.StatusFound)
+}
+
+func (a *App) LoginHandler(w http.ResponseWriter, r *http.Request) { //nolint
+ if r.Method == "GET" {
+ page.RenderForPath(w, r, "login")
+
+ return
+ }
+
+ if r.Method != "POST" {
+ a.Err500Default(w, r)
+
+ return
+ }
+
+ log.Printf("made it")
+
+ username := r.FormValue("username")
+ password := r.FormValue("password")
+
+ var (
+ err error = nil
+ u *users.SiteUser
+ found = false
+ )
+
+ for _, u = range a.auth.Users {
+ if u.Username == username {
+ err = u.CheckPassword(password)
+ found = true
+ }
+ }
+
+ if err != nil || !found {
+ page.Render(w, r, "login", map[string]interface{}{
+ "Error": "Invalid username or password",
+ "Username": username,
+ }, http.StatusUnauthorized)
+
+ return
+ }
+
+ token := jwt.NewWithClaims(jwt.SigningMethodHS512, &jwt.StandardClaims{
+ ExpiresAt: time.Now().Add(
+ time.Hour * time.Duration(a.auth.LoginHours)).Unix(),
+ Id: u.Username,
+ })
+
+ ss, err := token.SignedString([]byte(a.auth.TokenKey))
+ if err != nil {
+ log.Println("login: encountered while setting up JWT: ", err)
+ a.Err500Default(w, r)
+
+ return
+ }
+
+ log.Println(ss)
+
+ http.SetCookie(w, &http.Cookie{
+ Name: "Auth",
+ HttpOnly: a.auth.HTTPOnly,
+ SameSite: a.auth.SameSiteStrict,
+ Secure: a.auth.Secure,
+ Value: ss,
+ })
+
+ http.Redirect(w, r, "/login", http.StatusFound)
+}
+
+func (a *App) RequiresLogin(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ mustLoginResp := func() {
+ page.Render(w, r, "login", map[string]interface{}{
+ "Error": "You must login to view this page",
+ }, http.StatusUnauthorized)
+ }
+
+ c, err := r.Cookie("Auth")
+ if err != nil {
+ mustLoginResp()
+
+ return
+ }
+
+ token, err := jwt.Parse(c.Value,
+ func(token *jwt.Token) (interface{}, error) {
+ return []byte(a.auth.TokenKey), nil
+ },
+ )
+
+ if err != nil {
+ log.Printf("Unauthorized request %s %s", r.Method, r.URL.Path)
+ mustLoginResp()
+
+ return
+ }
+
+ if !token.Valid {
+ mustLoginResp()
+
+ return
+ }
+
+ next.ServeHTTP(w, r)
+ })
+}