diff --git a/cmd/server/main.go b/cmd/server/main.go
index e74734a..cf2ee58 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -1,6 +1,7 @@
package main
import (
+ "encoding/gob"
"log"
"net/http"
"time"
@@ -35,9 +36,9 @@ func setSubsonicRoutes(mux *http.ServeMux) {
DB: dbCon,
}
withWare := newChain(
- cont.LogConnection,
- cont.EnableCORS,
- cont.CheckParameters,
+ cont.WithLogging,
+ cont.WithCORS,
+ cont.WithValidSubsonicArgs,
)
mux.HandleFunc("/rest/ping", withWare(cont.Ping))
mux.HandleFunc("/rest/ping.view", withWare(cont.Ping))
@@ -66,20 +67,30 @@ func setAdminRoutes(mux *http.ServeMux) {
DB: dbCon,
SStore: gormstore.New(dbCon, []byte("saynothinboys")),
}
- withWare := newChain(
- cont.LogConnection,
- cont.EnableCORS,
+ withBaseWare := newChain(
+ cont.WithLogging,
+ )
+ withAuthWare := newChain(
+ withBaseWare,
+ cont.WithValidSession,
)
server := http.FileServer(http.Dir("static"))
mux.Handle("/admin/static/", http.StripPrefix("/admin/static/", server))
- mux.HandleFunc("/admin/login", withWare(cont.ServeLogin))
- mux.HandleFunc("/admin/authenticate", withWare(cont.ServeAuthenticate))
- mux.HandleFunc("/admin/home", withWare(cont.ServeHome))
- mux.HandleFunc("/admin/create_user", withWare(cont.ServeCreateUser))
- mux.HandleFunc("/admin/logout", withWare(cont.ServeLogout))
+ mux.HandleFunc("/admin/login", withBaseWare(cont.ServeLogin))
+ mux.HandleFunc("/admin/login_do", withBaseWare(cont.ServeLoginDo))
+ mux.HandleFunc("/admin/logout", withAuthWare(cont.ServeLogout))
+ mux.HandleFunc("/admin/home", withAuthWare(cont.ServeHome))
+ mux.HandleFunc("/admin/change_password", withAuthWare(cont.ServeChangePassword))
+ mux.HandleFunc("/admin/change_password_do", withBaseWare(cont.ServeChangePasswordDo))
+ mux.HandleFunc("/admin/create_user", withAuthWare(cont.ServeCreateUser))
+ mux.HandleFunc("/admin/create_user_do", withBaseWare(cont.ServeCreateUserDo))
}
func main() {
+ // init stuff. needed to store the current user in
+ // the gorilla session
+ gob.Register(&db.User{})
+ // setup the subsonic and admin routes
address := ":5000"
mux := http.NewServeMux()
setSubsonicRoutes(mux)
diff --git a/handler/admin.go b/handler/admin.go
index 8cb8774..7b40a0d 100644
--- a/handler/admin.go
+++ b/handler/admin.go
@@ -1,8 +1,10 @@
package handler
import (
+ "fmt"
"net/http"
+ "github.com/jinzhu/gorm"
"github.com/sentriz/gonic/db"
)
@@ -11,14 +13,14 @@ func (c *Controller) ServeLogin(w http.ResponseWriter, r *http.Request) {
renderTemplate(w, r, session, "login", &templateData{})
}
-func (c *Controller) ServeAuthenticate(w http.ResponseWriter, r *http.Request) {
+func (c *Controller) ServeLoginDo(w http.ResponseWriter, r *http.Request) {
session, _ := c.SStore.Get(r, "gonic")
username := r.FormValue("username")
password := r.FormValue("password")
if username == "" || password == "" {
session.AddFlash("please provide both a username and password")
session.Save(r, w)
- http.Redirect(w, r, "/admin/login", 303)
+ http.Redirect(w, r, r.Header.Get("Referer"), 302)
return
}
var user db.User
@@ -26,52 +28,107 @@ func (c *Controller) ServeAuthenticate(w http.ResponseWriter, r *http.Request) {
if !(username == user.Name && password == user.Password) {
session.AddFlash("invalid username / password")
session.Save(r, w)
- http.Redirect(w, r, "/admin/login", 303)
+ http.Redirect(w, r, r.Header.Get("Referer"), 302)
return
}
- session.Values["authenticated"] = true
- session.Values["user"] = user.ID
+ session.Values["user"] = user
session.Save(r, w)
http.Redirect(w, r, "/admin/home", 303)
}
-func (c *Controller) ServeHome(w http.ResponseWriter, r *http.Request) {
- session, _ := c.SStore.Get(r, "gonic")
- authed, _ := session.Values["authenticated"].(bool)
- if !authed {
- session.AddFlash("you are not authenticated")
- session.Save(r, w)
- http.Redirect(w, r, "/admin/login", 303)
- return
- }
- var data templateData
- var user db.User
- c.DB.First(&user, session.Values["user"])
- data.UserID = user.ID
- data.Username = user.Name
- c.DB.Table("album_artists").Count(&data.ArtistCount)
- c.DB.Table("albums").Count(&data.AlbumCount)
- c.DB.Table("tracks").Count(&data.TrackCount)
- c.DB.Find(&data.Users)
- renderTemplate(w, r, session, "home", &data)
-}
-
-func (c *Controller) ServeCreateUser(w http.ResponseWriter, r *http.Request) {
- session, _ := c.SStore.Get(r, "gonic")
- authed, _ := session.Values["authenticated"].(bool)
- if !authed {
- session.AddFlash("you are not authenticated")
- session.Save(r, w)
- http.Redirect(w, r, "/admin/login", 303)
- return
- }
- renderTemplate(w, r, session, "create_user", &templateData{})
-}
-
func (c *Controller) ServeLogout(w http.ResponseWriter, r *http.Request) {
session, _ := c.SStore.Get(r, "gonic")
- delete(session.Values, "authenticated")
delete(session.Values, "user")
session.Save(r, w)
http.Redirect(w, r, "/admin/login", 303)
}
+
+func (c *Controller) ServeHome(w http.ResponseWriter, r *http.Request) {
+ session, _ := c.SStore.Get(r, "gonic")
+ var data templateData
+ c.DB.Table("album_artists").Count(&data.ArtistCount)
+ c.DB.Table("albums").Count(&data.AlbumCount)
+ c.DB.Table("tracks").Count(&data.TrackCount)
+ c.DB.Find(&data.AllUsers)
+ renderTemplate(w, r, session, "home", &data)
+}
+
+func (c *Controller) ServeChangePassword(w http.ResponseWriter, r *http.Request) {
+ session, _ := c.SStore.Get(r, "gonic")
+ username := r.URL.Query().Get("user")
+ if username == "" {
+ http.Error(w, "please provide a username", 400)
+ return
+ }
+ var user db.User
+ err := c.DB.Where("name = ?", username).First(&user).Error
+ if gorm.IsRecordNotFoundError(err) {
+ http.Error(w, "couldn't find a user with that name", 400)
+ return
+ }
+ var data templateData
+ data.SelectedUser = &user
+ renderTemplate(w, r, session, "change_password", &data)
+}
+
+func (c *Controller) ServeChangePasswordDo(w http.ResponseWriter, r *http.Request) {
+ session, _ := c.SStore.Get(r, "gonic")
+ username := r.URL.Query().Get("user")
+ var user db.User
+ c.DB.Where("name = ?", username).First(&user)
+ password_one := r.FormValue("password_one")
+ password_two := r.FormValue("password_two")
+ if password_one == "" || password_two == "" {
+ session.AddFlash("please provide both passwords")
+ session.Save(r, w)
+ http.Redirect(w, r, r.Header.Get("Referer"), 302)
+ return
+ }
+ if !(password_one == password_two) {
+ session.AddFlash("the two passwords entered were not the same")
+ session.Save(r, w)
+ http.Redirect(w, r, r.Header.Get("Referer"), 302)
+ return
+ }
+ user.Password = password_one
+ c.DB.Save(&user)
+ http.Redirect(w, r, "/admin/home", 303)
+}
+
+func (c *Controller) ServeCreateUser(w http.ResponseWriter, r *http.Request) {
+ session, _ := c.SStore.Get(r, "gonic")
+ renderTemplate(w, r, session, "create_user", &templateData{})
+}
+
+func (c *Controller) ServeCreateUserDo(w http.ResponseWriter, r *http.Request) {
+ session, _ := c.SStore.Get(r, "gonic")
+ username := r.FormValue("username")
+ password_one := r.FormValue("password_one")
+ password_two := r.FormValue("password_two")
+ if username == "" || password_one == "" || password_two == "" {
+ session.AddFlash("please fill out all fields")
+ session.Save(r, w)
+ http.Redirect(w, r, r.Header.Get("Referer"), 302)
+ return
+ }
+ if !(password_one == password_two) {
+ session.AddFlash("the two passwords entered were not the same")
+ session.Save(r, w)
+ http.Redirect(w, r, r.Header.Get("Referer"), 302)
+ return
+ }
+ user := db.User{
+ Name: username,
+ Password: password_one,
+ }
+ err := c.DB.Create(&user).Error
+ if err != nil {
+ session.AddFlash(fmt.Sprintf(
+ "could not create user `%s`: %v", username, err,
+ ))
+ session.Save(r, w)
+ http.Redirect(w, r, r.Header.Get("Referer"), 302)
+ return
+ }
+ http.Redirect(w, r, "/admin/home", 303)
+}
diff --git a/handler/handler.go b/handler/handler.go
index 23dc730..cbc0bd9 100644
--- a/handler/handler.go
+++ b/handler/handler.go
@@ -25,17 +25,22 @@ var (
func init() {
templates["login"] = template.Must(template.ParseFiles(
filepath.Join("templates", "layout.tmpl"),
- filepath.Join("templates", "admin", "login.tmpl"),
+ filepath.Join("templates", "pages", "login.tmpl"),
))
templates["home"] = template.Must(template.ParseFiles(
filepath.Join("templates", "layout.tmpl"),
filepath.Join("templates", "user.tmpl"),
- filepath.Join("templates", "admin", "home.tmpl"),
+ filepath.Join("templates", "pages", "home.tmpl"),
))
templates["create_user"] = template.Must(template.ParseFiles(
filepath.Join("templates", "layout.tmpl"),
filepath.Join("templates", "user.tmpl"),
- filepath.Join("templates", "admin", "create_user.tmpl"),
+ filepath.Join("templates", "pages", "create_user.tmpl"),
+ ))
+ templates["change_password"] = template.Must(template.ParseFiles(
+ filepath.Join("templates", "layout.tmpl"),
+ filepath.Join("templates", "user.tmpl"),
+ filepath.Join("templates", "pages", "change_password.tmpl"),
))
}
@@ -46,13 +51,13 @@ type Controller struct {
}
type templateData struct {
- Flashes []interface{}
- UserID uint
- Username string
- ArtistCount uint
- AlbumCount uint
- TrackCount uint
- Users []*db.User
+ Flashes []interface{}
+ User *db.User
+ SelectedUser *db.User
+ AllUsers []*db.User
+ ArtistCount uint
+ AlbumCount uint
+ TrackCount uint
}
func getStrParam(r *http.Request, key string) string {
@@ -127,9 +132,15 @@ func respondError(w http.ResponseWriter, r *http.Request,
func renderTemplate(w http.ResponseWriter, r *http.Request,
s *sessions.Session, name string, data *templateData) {
- flashes := s.Flashes()
+ // take the flashes from the session and add to template
+ data.Flashes = s.Flashes()
s.Save(r, w)
- data.Flashes = flashes
+ // take the user gob from the session (if we're logged in and
+ // it's there) cast to a user and add to the template
+ userIntf := s.Values["user"]
+ if userIntf != nil {
+ data.User = s.Values["user"].(*db.User)
+ }
err := templates[name].ExecuteTemplate(w, "layout", data)
if err != nil {
http.Error(w, fmt.Sprintf("500 when executing: %v", err), 500)
diff --git a/handler/middleware.go b/handler/middleware.go
index 57b801a..734d0a7 100644
--- a/handler/middleware.go
+++ b/handler/middleware.go
@@ -30,14 +30,14 @@ func checkCredentialsBasic(password, givenPassword string) bool {
return password == givenPassword
}
-func (c *Controller) LogConnection(next http.HandlerFunc) http.HandlerFunc {
+func (c *Controller) WithLogging(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Printf("connection from `%s` for `%s`", r.RemoteAddr, r.URL)
next.ServeHTTP(w, r)
}
}
-func (c *Controller) CheckParameters(next http.HandlerFunc) http.HandlerFunc {
+func (c *Controller) WithValidSubsonicArgs(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
for _, req := range requiredParameters {
param := r.URL.Query().Get(req)
@@ -83,7 +83,7 @@ func (c *Controller) CheckParameters(next http.HandlerFunc) http.HandlerFunc {
}
}
-func (c *Controller) EnableCORS(next http.HandlerFunc) http.HandlerFunc {
+func (c *Controller) WithCORS(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods",
@@ -98,3 +98,17 @@ func (c *Controller) EnableCORS(next http.HandlerFunc) http.HandlerFunc {
next.ServeHTTP(w, r)
}
}
+
+func (c *Controller) WithValidSession(next http.HandlerFunc) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ session, _ := c.SStore.Get(r, "gonic")
+ user, _ := session.Values["user"]
+ if user == nil {
+ session.AddFlash("you are not authenticated")
+ session.Save(r, w)
+ http.Redirect(w, r, "/admin/login", 303)
+ return
+ }
+ next.ServeHTTP(w, r)
+ }
+}
diff --git a/static/stylesheets/main.css b/static/stylesheets/main.css
index a946a34..f1359e3 100644
--- a/static/stylesheets/main.css
+++ b/static/stylesheets/main.css
@@ -1,3 +1,16 @@
+/* reset from awsm */
+form input[type], form select, form textarea {
+ margin-bottom: 0;
+}
+
+/* reset from awsm */
+form {
+ max-width: 400px;
+ margin-left: auto;
+ margin-right: 0;
+}
+
+/* reset from awsm */
div {
margin: 0;
padding: 0;
@@ -12,12 +25,13 @@ body {
justify-content: space-between;
}
-form {
- max-width: unset;
+
+form input[type=password], form input[type=text] {
+ margin-bottom: 0.25rem;
}
#content > * {
- margin: 1rem 0;
+ margin: 2rem 0;
}
.right {
@@ -40,13 +54,15 @@ form {
background-color: #0000000a;
}
+.box-title {
+ margin-bottom: 0.5rem;
+}
+
.padded {
padding: 1rem;
}
#header {
- /* background-color: #fdc71b08; */
- background-image: linear-gradient(white, #fdad1b0d);
border-bottom: 1px solid;
padding-top: 3rem;
}
@@ -63,7 +79,7 @@ form {
}
#flashes {
- background-color: #fd1b1b29;
+ background-color: #fd1b1b1c;
}
#login-form {
diff --git a/templates/admin/create_user.tmpl b/templates/admin/create_user.tmpl
deleted file mode 100644
index 8afd6ff..0000000
--- a/templates/admin/create_user.tmpl
+++ /dev/null
@@ -1,12 +0,0 @@
-{{ define "title" }}home{{ end }}
-
-{{ define "user" }}
-
-
- create new user
-
-
- howdy
-
-
-{{ end }}
diff --git a/templates/admin/login.tmpl b/templates/admin/login.tmpl
deleted file mode 100644
index d5ad2b1..0000000
--- a/templates/admin/login.tmpl
+++ /dev/null
@@ -1,12 +0,0 @@
-{{ define "title" }}gonic{{ end }}
-
-{{ define "content" }}
-
- login
-
-
-{{ end }}
diff --git a/templates/layout.tmpl b/templates/layout.tmpl
index c85f443..6a38995 100644
--- a/templates/layout.tmpl
+++ b/templates/layout.tmpl
@@ -15,7 +15,7 @@
{{ if .Flashes }}
-
+
warning: {{ index .Flashes 0 }}
{{ end }}
diff --git a/templates/pages/change_password.tmpl b/templates/pages/change_password.tmpl
new file mode 100644
index 0000000..6169c5e
--- /dev/null
+++ b/templates/pages/change_password.tmpl
@@ -0,0 +1,14 @@
+{{ define "title" }}home{{ end }}
+
+{{ define "user" }}
+
+
+ changing {{ .SelectedUser.Name }}'s password
+
+
+
+{{ end }}
diff --git a/templates/pages/create_user.tmpl b/templates/pages/create_user.tmpl
new file mode 100644
index 0000000..17fd06c
--- /dev/null
+++ b/templates/pages/create_user.tmpl
@@ -0,0 +1,15 @@
+{{ define "title" }}home{{ end }}
+
+{{ define "user" }}
+
+
+ create new user
+
+
+
+{{ end }}
diff --git a/templates/admin/home.tmpl b/templates/pages/home.tmpl
similarity index 78%
rename from templates/admin/home.tmpl
rename to templates/pages/home.tmpl
index 84b83bb..c337ddd 100644
--- a/templates/admin/home.tmpl
+++ b/templates/pages/home.tmpl
@@ -2,7 +2,7 @@
{{ define "user" }}
-
+
stats
@@ -12,20 +12,20 @@
-
-
last.fm
+
+ last fm
unlinked
-
+
users
- {{ range $user := .Users }}
-
{{ $user.Name }} created {{ $user.CreatedAt.Format "Jan 02, 2006" }} change password
+ {{ range $user := .AllUsers }}
+
{{ $user.Name }} created {{ $user.CreatedAt.Format "Jan 02, 2006" }} change password
{{ end }}
create new
diff --git a/templates/pages/login.tmpl b/templates/pages/login.tmpl
new file mode 100644
index 0000000..b53f544
--- /dev/null
+++ b/templates/pages/login.tmpl
@@ -0,0 +1,14 @@
+{{ define "title" }}gonic{{ end }}
+
+{{ define "content" }}
+
+{{ end }}
diff --git a/templates/user.tmpl b/templates/user.tmpl
index ea3dd38..a14bd0f 100644
--- a/templates/user.tmpl
+++ b/templates/user.tmpl
@@ -1,8 +1,8 @@
{{ define "title" }}home{{ end }}
{{ define "content" }}
-
-
welcome {{ .Username }} | logout
-
- {{ template "user" . }}
+
+
welcome {{ .User.Name }} | logout
+
+{{ template "user" . }}
{{ end }}