split up admin / sub handler
This commit is contained in:
35
handler/controller.go
Normal file
35
handler/controller.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/wader/gormstore"
|
||||||
|
|
||||||
|
"github.com/sentriz/gonic/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Controller struct {
|
||||||
|
DB *gorm.DB // common
|
||||||
|
SStore *gormstore.Store // admin
|
||||||
|
Templates map[string]*template.Template // admin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) GetSetting(key string) string {
|
||||||
|
var setting db.Setting
|
||||||
|
c.DB.Where("key = ?", key).First(&setting)
|
||||||
|
return setting.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) SetSetting(key, value string) {
|
||||||
|
c.DB.
|
||||||
|
Where(db.Setting{Key: key}).
|
||||||
|
Assign(db.Setting{Value: value}).
|
||||||
|
FirstOrCreate(&db.Setting{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) GetUserFromName(name string) *db.User {
|
||||||
|
var user db.User
|
||||||
|
c.DB.Where("name = ?", name).First(&user)
|
||||||
|
return &user
|
||||||
|
}
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
package handler
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"html/template"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/gorilla/sessions"
|
|
||||||
"github.com/jinzhu/gorm"
|
|
||||||
"github.com/wader/gormstore"
|
|
||||||
|
|
||||||
"github.com/sentriz/gonic/db"
|
|
||||||
"github.com/sentriz/gonic/subsonic"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Controller struct {
|
|
||||||
DB *gorm.DB
|
|
||||||
SStore *gormstore.Store
|
|
||||||
Templates map[string]*template.Template
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) GetSetting(key string) string {
|
|
||||||
var setting db.Setting
|
|
||||||
c.DB.Where("key = ?", key).First(&setting)
|
|
||||||
return setting.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) SetSetting(key, value string) {
|
|
||||||
c.DB.
|
|
||||||
Where(db.Setting{Key: key}).
|
|
||||||
Assign(db.Setting{Value: value}).
|
|
||||||
FirstOrCreate(&db.Setting{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) GetUserFromName(name string) *db.User {
|
|
||||||
var user db.User
|
|
||||||
c.DB.Where("name = ?", name).First(&user)
|
|
||||||
return &user
|
|
||||||
}
|
|
||||||
|
|
||||||
type templateData struct {
|
|
||||||
Flashes []interface{}
|
|
||||||
User *db.User
|
|
||||||
SelectedUser *db.User
|
|
||||||
AllUsers []*db.User
|
|
||||||
ArtistCount int
|
|
||||||
AlbumCount int
|
|
||||||
TrackCount int
|
|
||||||
CurrentLastFMAPIKey string
|
|
||||||
CurrentLastFMAPISecret string
|
|
||||||
RequestRoot string
|
|
||||||
}
|
|
||||||
|
|
||||||
func getStrParam(r *http.Request, key string) string {
|
|
||||||
return r.URL.Query().Get(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getStrParamOr(r *http.Request, key, or string) string {
|
|
||||||
val := getStrParam(r, key)
|
|
||||||
if val == "" {
|
|
||||||
return or
|
|
||||||
}
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIntParam(r *http.Request, key string) (int, error) {
|
|
||||||
strVal := r.URL.Query().Get(key)
|
|
||||||
if strVal == "" {
|
|
||||||
return 0, fmt.Errorf("no param with key `%s`", key)
|
|
||||||
}
|
|
||||||
val, err := strconv.Atoi(strVal)
|
|
||||||
if err != nil {
|
|
||||||
return 0, fmt.Errorf("not an int `%s`", strVal)
|
|
||||||
}
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIntParamOr(r *http.Request, key string, or int) int {
|
|
||||||
val, err := getIntParam(r, key)
|
|
||||||
if err != nil {
|
|
||||||
return or
|
|
||||||
}
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
func respondRaw(w http.ResponseWriter, r *http.Request,
|
|
||||||
code int, sub *subsonic.Response) {
|
|
||||||
res := subsonic.MetaResponse{
|
|
||||||
Response: sub,
|
|
||||||
}
|
|
||||||
switch r.URL.Query().Get("f") {
|
|
||||||
case "json":
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
data, err := json.Marshal(res)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("could not marshall to json: %v\n", err)
|
|
||||||
}
|
|
||||||
w.Write(data)
|
|
||||||
case "jsonp":
|
|
||||||
w.Header().Set("Content-Type", "application/javascript")
|
|
||||||
data, err := json.Marshal(res)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("could not marshall to json: %v\n", err)
|
|
||||||
}
|
|
||||||
callback := r.URL.Query().Get("callback")
|
|
||||||
w.Write([]byte(callback))
|
|
||||||
w.Write([]byte("("))
|
|
||||||
w.Write(data)
|
|
||||||
w.Write([]byte(");"))
|
|
||||||
default:
|
|
||||||
w.Header().Set("Content-Type", "application/xml")
|
|
||||||
data, err := xml.Marshal(res)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("could not marshall to xml: %v\n", err)
|
|
||||||
}
|
|
||||||
w.Write(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func respond(w http.ResponseWriter, r *http.Request,
|
|
||||||
sub *subsonic.Response) {
|
|
||||||
respondRaw(w, r, http.StatusOK, sub)
|
|
||||||
}
|
|
||||||
|
|
||||||
func respondError(w http.ResponseWriter, r *http.Request,
|
|
||||||
code int, message string) {
|
|
||||||
respondRaw(w, r, http.StatusBadRequest, subsonic.NewError(
|
|
||||||
code, message,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
func renderTemplate(w http.ResponseWriter, r *http.Request,
|
|
||||||
tmpl *template.Template, data *templateData) {
|
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
|
||||||
if data == nil {
|
|
||||||
data = &templateData{}
|
|
||||||
}
|
|
||||||
data.Flashes = session.Flashes()
|
|
||||||
session.Save(r, w)
|
|
||||||
user, ok := r.Context().Value("user").(*db.User)
|
|
||||||
if ok {
|
|
||||||
data.User = user
|
|
||||||
}
|
|
||||||
err := tmpl.Execute(w, data)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, fmt.Sprintf("500 when executing: %v", err), 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
|
||||||
"github.com/sentriz/gonic/db"
|
"github.com/sentriz/gonic/db"
|
||||||
"github.com/sentriz/gonic/handler/utilities"
|
|
||||||
"github.com/sentriz/gonic/lastfm"
|
"github.com/sentriz/gonic/lastfm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,7 +16,7 @@ func (c *Controller) ServeLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeLoginDo(w http.ResponseWriter, r *http.Request) {
|
func (c *Controller) ServeLoginDo(w http.ResponseWriter, r *http.Request) {
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
username := r.FormValue("username")
|
username := r.FormValue("username")
|
||||||
password := r.FormValue("password")
|
password := r.FormValue("password")
|
||||||
if username == "" || password == "" {
|
if username == "" || password == "" {
|
||||||
@@ -42,7 +41,7 @@ func (c *Controller) ServeLoginDo(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeLogout(w http.ResponseWriter, r *http.Request) {
|
func (c *Controller) ServeLogout(w http.ResponseWriter, r *http.Request) {
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
session.Options.MaxAge = -1
|
session.Options.MaxAge = -1
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
||||||
@@ -55,13 +54,13 @@ func (c *Controller) ServeHome(w http.ResponseWriter, r *http.Request) {
|
|||||||
c.DB.Table("tracks").Count(&data.TrackCount)
|
c.DB.Table("tracks").Count(&data.TrackCount)
|
||||||
c.DB.Find(&data.AllUsers)
|
c.DB.Find(&data.AllUsers)
|
||||||
data.CurrentLastFMAPIKey = c.GetSetting("lastfm_api_key")
|
data.CurrentLastFMAPIKey = c.GetSetting("lastfm_api_key")
|
||||||
scheme := utilities.FirstExisting(
|
scheme := firstExisting(
|
||||||
"http", // fallback
|
"http", // fallback
|
||||||
r.Header.Get("X-Forwarded-Proto"),
|
r.Header.Get("X-Forwarded-Proto"),
|
||||||
r.Header.Get("X-Forwarded-Scheme"),
|
r.Header.Get("X-Forwarded-Scheme"),
|
||||||
r.URL.Scheme,
|
r.URL.Scheme,
|
||||||
)
|
)
|
||||||
host := utilities.FirstExisting(
|
host := firstExisting(
|
||||||
"localhost:7373", // fallback
|
"localhost:7373", // fallback
|
||||||
r.Header.Get("X-Forwarded-Host"),
|
r.Header.Get("X-Forwarded-Host"),
|
||||||
r.Host,
|
r.Host,
|
||||||
@@ -75,17 +74,17 @@ func (c *Controller) ServeChangeOwnPassword(w http.ResponseWriter, r *http.Reque
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeChangeOwnPasswordDo(w http.ResponseWriter, r *http.Request) {
|
func (c *Controller) ServeChangeOwnPasswordDo(w http.ResponseWriter, r *http.Request) {
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
passwordOne := r.FormValue("password_one")
|
passwordOne := r.FormValue("password_one")
|
||||||
passwordTwo := r.FormValue("password_two")
|
passwordTwo := r.FormValue("password_two")
|
||||||
err := utilities.ValidatePasswords(passwordOne, passwordTwo)
|
err := validatePasswords(passwordOne, passwordTwo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.AddFlash(err.Error())
|
session.AddFlash(err.Error())
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := r.Context().Value("user").(*db.User)
|
user := r.Context().Value(contextUserKey).(*db.User)
|
||||||
user.Password = passwordOne
|
user.Password = passwordOne
|
||||||
c.DB.Save(user)
|
c.DB.Save(user)
|
||||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||||
@@ -102,21 +101,21 @@ func (c *Controller) ServeLinkLastFMDo(w http.ResponseWriter, r *http.Request) {
|
|||||||
c.GetSetting("lastfm_secret"),
|
c.GetSetting("lastfm_secret"),
|
||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.AddFlash(err.Error())
|
session.AddFlash(err.Error())
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := r.Context().Value("user").(*db.User)
|
user := r.Context().Value(contextUserKey).(*db.User)
|
||||||
user.LastFMSession = sessionKey
|
user.LastFMSession = sessionKey
|
||||||
c.DB.Save(&user)
|
c.DB.Save(&user)
|
||||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeUnlinkLastFMDo(w http.ResponseWriter, r *http.Request) {
|
func (c *Controller) ServeUnlinkLastFMDo(w http.ResponseWriter, r *http.Request) {
|
||||||
user := r.Context().Value("user").(*db.User)
|
user := r.Context().Value(contextUserKey).(*db.User)
|
||||||
user.LastFMSession = ""
|
user.LastFMSession = ""
|
||||||
c.DB.Save(&user)
|
c.DB.Save(&user)
|
||||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||||
@@ -140,13 +139,13 @@ func (c *Controller) ServeChangePassword(w http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeChangePasswordDo(w http.ResponseWriter, r *http.Request) {
|
func (c *Controller) ServeChangePasswordDo(w http.ResponseWriter, r *http.Request) {
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
username := r.URL.Query().Get("user")
|
username := r.URL.Query().Get("user")
|
||||||
var user db.User
|
var user db.User
|
||||||
c.DB.Where("name = ?", username).First(&user)
|
c.DB.Where("name = ?", username).First(&user)
|
||||||
passwordOne := r.FormValue("password_one")
|
passwordOne := r.FormValue("password_one")
|
||||||
passwordTwo := r.FormValue("password_two")
|
passwordTwo := r.FormValue("password_two")
|
||||||
err := utilities.ValidatePasswords(passwordOne, passwordTwo)
|
err := validatePasswords(passwordOne, passwordTwo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.AddFlash(err.Error())
|
session.AddFlash(err.Error())
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
@@ -188,9 +187,9 @@ func (c *Controller) ServeCreateUser(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeCreateUserDo(w http.ResponseWriter, r *http.Request) {
|
func (c *Controller) ServeCreateUserDo(w http.ResponseWriter, r *http.Request) {
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
username := r.FormValue("username")
|
username := r.FormValue("username")
|
||||||
err := utilities.ValidateUsername(username)
|
err := validateUsername(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.AddFlash(err.Error())
|
session.AddFlash(err.Error())
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
@@ -199,7 +198,7 @@ func (c *Controller) ServeCreateUserDo(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
passwordOne := r.FormValue("password_one")
|
passwordOne := r.FormValue("password_one")
|
||||||
passwordTwo := r.FormValue("password_two")
|
passwordTwo := r.FormValue("password_two")
|
||||||
err = utilities.ValidatePasswords(passwordOne, passwordTwo)
|
err = validatePasswords(passwordOne, passwordTwo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.AddFlash(err.Error())
|
session.AddFlash(err.Error())
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
@@ -230,10 +229,10 @@ func (c *Controller) ServeUpdateLastFMAPIKey(w http.ResponseWriter, r *http.Requ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeUpdateLastFMAPIKeyDo(w http.ResponseWriter, r *http.Request) {
|
func (c *Controller) ServeUpdateLastFMAPIKeyDo(w http.ResponseWriter, r *http.Request) {
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
apiKey := r.FormValue("api_key")
|
apiKey := r.FormValue("api_key")
|
||||||
secret := r.FormValue("secret")
|
secret := r.FormValue("secret")
|
||||||
err := utilities.ValidateAPIKey(apiKey, secret)
|
err := validateAPIKey(apiKey, secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.AddFlash(err.Error())
|
session.AddFlash(err.Error())
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
8
handler/handler_admin_const.go
Normal file
8
handler/handler_admin_const.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
type contextKey int
|
||||||
|
|
||||||
|
const (
|
||||||
|
contextUserKey contextKey = iota
|
||||||
|
contextSessionKey
|
||||||
|
)
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
package utilities
|
package handler
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func ValidateUsername(username string) error {
|
func validateUsername(username string) error {
|
||||||
if username == "" {
|
if username == "" {
|
||||||
return fmt.Errorf("please enter the username")
|
return fmt.Errorf("please enter the username")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidatePasswords(pOne, pTwo string) error {
|
func validatePasswords(pOne, pTwo string) error {
|
||||||
if pOne == "" || pTwo == "" {
|
if pOne == "" || pTwo == "" {
|
||||||
return fmt.Errorf("please enter the password twice")
|
return fmt.Errorf("please enter the password twice")
|
||||||
}
|
}
|
||||||
@@ -19,14 +19,14 @@ func ValidatePasswords(pOne, pTwo string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateAPIKey(apiKey, secret string) error {
|
func validateAPIKey(apiKey, secret string) error {
|
||||||
if apiKey == "" || secret == "" {
|
if apiKey == "" || secret == "" {
|
||||||
return fmt.Errorf("please enter both the api key and secret")
|
return fmt.Errorf("please enter both the api key and secret")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func FirstExisting(or string, strings ...string) string {
|
func firstExisting(or string, strings ...string) string {
|
||||||
current := ""
|
current := ""
|
||||||
for _, s := range strings {
|
for _, s := range strings {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
// func (c *Controller) GetIndexes(w http.ResponseWriter, r *http.Request) {
|
// func (c *Controller) GetIndexes(w http.ResponseWriter, r *http.Request) {
|
||||||
// var artists []*db.Artist
|
// var artists []*db.Artist
|
||||||
// c.DB.Find(&artists)
|
// c.DB.Find(&artists)
|
||||||
59
handler/middleware_admin.go
Normal file
59
handler/middleware_admin.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
|
|
||||||
|
"github.com/sentriz/gonic/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Controller) WithSession(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, _ := c.SStore.Get(r, "gonic")
|
||||||
|
withSession := context.WithValue(r.Context(), contextSessionKey, session)
|
||||||
|
next.ServeHTTP(w, r.WithContext(withSession))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) WithUserSession(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// session exists at this point
|
||||||
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
|
username, ok := session.Values["user"].(string)
|
||||||
|
if !ok {
|
||||||
|
session.AddFlash("you are not authenticated")
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// take username from sesion and add the user row to the context
|
||||||
|
user := c.GetUserFromName(username)
|
||||||
|
if user.ID == 0 {
|
||||||
|
// the username in the client's session no longer relates to a
|
||||||
|
// user in the database (maybe the user was deleted)
|
||||||
|
session.Options.MaxAge = -1
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
withUser := context.WithValue(r.Context(), contextUserKey, user)
|
||||||
|
next.ServeHTTP(w, r.WithContext(withUser))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) WithAdminSession(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// session and user exist at this point
|
||||||
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
|
user := r.Context().Value(contextUserKey).(*db.User)
|
||||||
|
if !user.IsAdmin {
|
||||||
|
session.AddFlash("you are not an admin")
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
handler/middleware_common.go
Normal file
13
handler/middleware_common.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,21 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/sessions"
|
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
|
||||||
"github.com/sentriz/gonic/db"
|
"github.com/sentriz/gonic/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
var requiredParameters = []string{
|
var (
|
||||||
"u", "v", "c",
|
requiredParameters = []string{
|
||||||
}
|
"u", "v", "c",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func checkCredentialsToken(password, token, salt string) bool {
|
func checkCredentialsToken(password, token, salt string) bool {
|
||||||
toHash := fmt.Sprintf("%s%s", password, salt)
|
toHash := fmt.Sprintf("%s%s", password, salt)
|
||||||
@@ -33,13 +32,6 @@ func checkCredentialsBasic(password, givenPassword string) bool {
|
|||||||
return password == givenPassword
|
return password == givenPassword
|
||||||
}
|
}
|
||||||
|
|
||||||
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) WithValidSubsonicArgs(next http.HandlerFunc) http.HandlerFunc {
|
func (c *Controller) WithValidSubsonicArgs(next http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
for _, req := range requiredParameters {
|
for _, req := range requiredParameters {
|
||||||
@@ -101,52 +93,3 @@ func (c *Controller) WithCORS(next http.HandlerFunc) http.HandlerFunc {
|
|||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) WithSession(next http.HandlerFunc) http.HandlerFunc {
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
session, _ := c.SStore.Get(r, "gonic")
|
|
||||||
withSession := context.WithValue(r.Context(), "session", session)
|
|
||||||
next.ServeHTTP(w, r.WithContext(withSession))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) WithUserSession(next http.HandlerFunc) http.HandlerFunc {
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// session exists at this point
|
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
|
||||||
username, ok := session.Values["user"].(string)
|
|
||||||
if !ok {
|
|
||||||
session.AddFlash("you are not authenticated")
|
|
||||||
session.Save(r, w)
|
|
||||||
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// take username from sesion and add the user row to the context
|
|
||||||
user := c.GetUserFromName(username)
|
|
||||||
if user.ID == 0 {
|
|
||||||
// the username in the client's session no longer relates to a
|
|
||||||
// user in the database (maybe the user was deleted)
|
|
||||||
session.Options.MaxAge = -1
|
|
||||||
session.Save(r, w)
|
|
||||||
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
withUser := context.WithValue(r.Context(), "user", user)
|
|
||||||
next.ServeHTTP(w, r.WithContext(withUser))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) WithAdminSession(next http.HandlerFunc) http.HandlerFunc {
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// session and user exist at this point
|
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
|
||||||
user := r.Context().Value("user").(*db.User)
|
|
||||||
if !user.IsAdmin {
|
|
||||||
session.AddFlash("you are not an admin")
|
|
||||||
session.Save(r, w)
|
|
||||||
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
39
handler/parse.go
Normal file
39
handler/parse.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getStrParam(r *http.Request, key string) string {
|
||||||
|
return r.URL.Query().Get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStrParamOr(r *http.Request, key, or string) string {
|
||||||
|
val := getStrParam(r, key)
|
||||||
|
if val == "" {
|
||||||
|
return or
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIntParam(r *http.Request, key string) (int, error) {
|
||||||
|
strVal := r.URL.Query().Get(key)
|
||||||
|
if strVal == "" {
|
||||||
|
return 0, fmt.Errorf("no param with key `%s`", key)
|
||||||
|
}
|
||||||
|
val, err := strconv.Atoi(strVal)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("not an int `%s`", strVal)
|
||||||
|
}
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIntParamOr(r *http.Request, key string, or int) int {
|
||||||
|
val, err := getIntParam(r, key)
|
||||||
|
if err != nil {
|
||||||
|
return or
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
43
handler/respond_admin.go
Normal file
43
handler/respond_admin.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
|
|
||||||
|
"github.com/sentriz/gonic/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
type templateData struct {
|
||||||
|
Flashes []interface{}
|
||||||
|
User *db.User
|
||||||
|
SelectedUser *db.User
|
||||||
|
AllUsers []*db.User
|
||||||
|
ArtistCount int
|
||||||
|
AlbumCount int
|
||||||
|
TrackCount int
|
||||||
|
CurrentLastFMAPIKey string
|
||||||
|
CurrentLastFMAPISecret string
|
||||||
|
RequestRoot string
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderTemplate(w http.ResponseWriter, r *http.Request,
|
||||||
|
tmpl *template.Template, data *templateData) {
|
||||||
|
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||||
|
if data == nil {
|
||||||
|
data = &templateData{}
|
||||||
|
}
|
||||||
|
data.Flashes = session.Flashes()
|
||||||
|
session.Save(r, w)
|
||||||
|
user, ok := r.Context().Value(contextUserKey).(*db.User)
|
||||||
|
if ok {
|
||||||
|
data.User = user
|
||||||
|
}
|
||||||
|
err := tmpl.Execute(w, data)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("500 when executing: %v", err), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
56
handler/respond_sub.go
Normal file
56
handler/respond_sub.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/sentriz/gonic/subsonic"
|
||||||
|
)
|
||||||
|
|
||||||
|
func respondRaw(w http.ResponseWriter, r *http.Request,
|
||||||
|
code int, sub *subsonic.Response) {
|
||||||
|
res := subsonic.MetaResponse{
|
||||||
|
Response: sub,
|
||||||
|
}
|
||||||
|
switch r.URL.Query().Get("f") {
|
||||||
|
case "json":
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
data, err := json.Marshal(res)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("could not marshall to json: %v\n", err)
|
||||||
|
}
|
||||||
|
w.Write(data)
|
||||||
|
case "jsonp":
|
||||||
|
w.Header().Set("Content-Type", "application/javascript")
|
||||||
|
data, err := json.Marshal(res)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("could not marshall to json: %v\n", err)
|
||||||
|
}
|
||||||
|
callback := r.URL.Query().Get("callback")
|
||||||
|
w.Write([]byte(callback))
|
||||||
|
w.Write([]byte("("))
|
||||||
|
w.Write(data)
|
||||||
|
w.Write([]byte(");"))
|
||||||
|
default:
|
||||||
|
w.Header().Set("Content-Type", "application/xml")
|
||||||
|
data, err := xml.Marshal(res)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("could not marshall to xml: %v\n", err)
|
||||||
|
}
|
||||||
|
w.Write(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func respond(w http.ResponseWriter, r *http.Request,
|
||||||
|
sub *subsonic.Response) {
|
||||||
|
respondRaw(w, r, http.StatusOK, sub)
|
||||||
|
}
|
||||||
|
|
||||||
|
func respondError(w http.ResponseWriter, r *http.Request,
|
||||||
|
code int, message string) {
|
||||||
|
respondRaw(w, r, http.StatusBadRequest, subsonic.NewError(
|
||||||
|
code, message,
|
||||||
|
))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user