mirror of
https://github.com/gmemstr/pogo.git
synced 2024-09-20 01:31:09 +01:00
2c1fbe460a
Added and tested edit route. Also removed Godep folder (at least for now) to see how it impacts installation.
236 lines
5.7 KiB
Go
236 lines
5.7 KiB
Go
package router
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/gorilla/mux"
|
|
"github.com/gmemstr/pogo/admin"
|
|
"github.com/gmemstr/pogo/auth"
|
|
"github.com/gmemstr/pogo/common"
|
|
)
|
|
|
|
type NewConfig struct {
|
|
Name string
|
|
Host string
|
|
Email string
|
|
Description string
|
|
Image string
|
|
PodcastURL string
|
|
}
|
|
|
|
// Handle takes multiple Handler and executes them in a serial order starting from first to last.
|
|
// In case, Any middle ware returns an error, The error is logged to console and sent to the user, Middlewares further up in chain are not executed.
|
|
func Handle(handlers ...common.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
rc := &common.RouterContext{}
|
|
for _, handler := range handlers {
|
|
err := handler(rc, w, r)
|
|
if err != nil {
|
|
log.Printf("%v", err)
|
|
|
|
w.Write([]byte(http.StatusText(err.StatusCode)))
|
|
|
|
return
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func Init() *mux.Router {
|
|
|
|
r := mux.NewRouter()
|
|
|
|
// "Static" paths
|
|
r.PathPrefix("/assets/").Handler(http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/web/static"))))
|
|
r.PathPrefix("/download/").Handler(http.StripPrefix("/download/", http.FileServer(http.Dir("podcasts"))))
|
|
|
|
// Paths that require specific handlers
|
|
r.Handle("/", Handle(
|
|
rootHandler(),
|
|
)).Methods("GET")
|
|
|
|
r.Handle("/rss", Handle(
|
|
rootHandler(),
|
|
)).Methods("GET")
|
|
|
|
r.Handle("/json", Handle(
|
|
rootHandler(),
|
|
)).Methods("GET")
|
|
|
|
// Authenticated endpoints should be passed to BasicAuth()
|
|
// first
|
|
r.Handle("/admin", Handle(
|
|
auth.RequireAuthorization(),
|
|
adminHandler(),
|
|
)).Methods("GET", "POST")
|
|
|
|
r.Handle("/login", Handle(
|
|
loginHandler(),
|
|
)).Methods("GET", "POST")
|
|
|
|
r.Handle("/admin/publish", Handle(
|
|
auth.RequireAuthorization(),
|
|
admin.CreateEpisode(),
|
|
)).Methods("POST")
|
|
|
|
r.Handle("/admin/edit", Handle(
|
|
auth.RequireAuthorization(),
|
|
admin.EditEpisode(),
|
|
)).Methods("POST")
|
|
|
|
r.Handle("/admin/delete", Handle(
|
|
auth.RequireAuthorization(),
|
|
admin.RemoveEpisode(),
|
|
)).Methods("GET")
|
|
|
|
r.Handle("/admin/css", Handle(
|
|
auth.RequireAuthorization(),
|
|
admin.CustomCss(),
|
|
)).Methods("GET", "POST")
|
|
|
|
r.Handle("/setup", Handle(
|
|
serveSetup(),
|
|
)).Methods("GET", "POST")
|
|
|
|
return r
|
|
}
|
|
|
|
func loginHandler() common.Handler {
|
|
return func(rc *common.RouterContext, w http.ResponseWriter, r *http.Request) *common.HTTPError {
|
|
|
|
if _, err := auth.DecryptCookie(r); err == nil {
|
|
http.Redirect(w, r, "/admin", http.StatusTemporaryRedirect)
|
|
return nil
|
|
}
|
|
|
|
if r.Method == "GET" {
|
|
w.Header().Set("Content-Type", "text/html")
|
|
return common.ReadAndServeFile("assets/web/login.html", w)
|
|
}
|
|
|
|
d, err := ioutil.ReadFile("assets/config/users.json")
|
|
if err != nil {
|
|
|
|
return &common.HTTPError{
|
|
Message: fmt.Sprintf("error in reading users.json: %v", err),
|
|
StatusCode: http.StatusInternalServerError,
|
|
}
|
|
}
|
|
|
|
err = r.ParseForm()
|
|
|
|
if err != nil {
|
|
return &common.HTTPError{
|
|
Message: fmt.Sprintf("error in parsing form: %v", err),
|
|
StatusCode: http.StatusBadRequest,
|
|
}
|
|
}
|
|
|
|
username := r.Form.Get("username")
|
|
password := r.Form.Get("password")
|
|
if username == "" || password == "" {
|
|
return &common.HTTPError{
|
|
Message: "username or password is empty",
|
|
StatusCode: http.StatusBadRequest,
|
|
}
|
|
}
|
|
|
|
var u map[string]string
|
|
err = json.Unmarshal(d, &u) // Unmarshal into interface
|
|
|
|
// Iterate through map until we find matching username
|
|
for k, v := range u {
|
|
if k == username && v == password {
|
|
// Create a cookie here because the credentials are correct
|
|
c, err := auth.CreateSession(&common.User{
|
|
Username: k,
|
|
})
|
|
if err != nil {
|
|
return &common.HTTPError{
|
|
Message: err.Error(),
|
|
StatusCode: http.StatusInternalServerError,
|
|
}
|
|
}
|
|
|
|
// r.AddCookie(c)
|
|
w.Header().Add("Set-Cookie", c.String())
|
|
// And now redirect the user to admin page
|
|
http.Redirect(w, r, "/admin", http.StatusTemporaryRedirect)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return &common.HTTPError{
|
|
Message: "Invalid credentials!",
|
|
StatusCode: http.StatusUnauthorized,
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handles /, /feed and /json endpoints
|
|
func rootHandler() common.Handler {
|
|
return func(rc *common.RouterContext, w http.ResponseWriter, r *http.Request) *common.HTTPError {
|
|
|
|
var file string
|
|
switch r.URL.Path {
|
|
case "/rss":
|
|
w.Header().Set("Content-Type", "application/rss+xml")
|
|
file = "assets/web/feed.rss"
|
|
case "/json":
|
|
w.Header().Set("Content-Type", "application/json")
|
|
file = "assets/web/feed.json"
|
|
case "/":
|
|
w.Header().Set("Content-Type", "text/html")
|
|
file = "assets/web/index.html"
|
|
default:
|
|
return &common.HTTPError{
|
|
Message: fmt.Sprintf("%s: Not Found", r.URL.Path),
|
|
StatusCode: http.StatusNotFound,
|
|
}
|
|
}
|
|
|
|
return common.ReadAndServeFile(file, w)
|
|
}
|
|
}
|
|
|
|
func adminHandler() common.Handler {
|
|
return func(rc *common.RouterContext, w http.ResponseWriter, r *http.Request) *common.HTTPError {
|
|
return common.ReadAndServeFile("assets/web/admin.html", w)
|
|
}
|
|
}
|
|
|
|
// Serve setup.html and config parameters
|
|
func serveSetup() common.Handler {
|
|
return func(rc *common.RouterContext, w http.ResponseWriter, r *http.Request) *common.HTTPError {
|
|
if r.Method == "GET" {
|
|
return common.ReadAndServeFile("assets/web/setup.html", w)
|
|
}
|
|
r.ParseMultipartForm(32 << 20)
|
|
|
|
// Parse form and convert to JSON
|
|
cnf := NewConfig{
|
|
strings.Join(r.Form["podcastname"], ""), // Podcast name
|
|
strings.Join(r.Form["podcasthost"], ""), // Podcast host
|
|
strings.Join(r.Form["podcastemail"], ""), // Podcast host email
|
|
"", // Podcast image
|
|
"", // Podcast location
|
|
"", // Podcast location
|
|
}
|
|
|
|
b, err := json.Marshal(cnf)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
ioutil.WriteFile("assets/config/config.json", b, 0644)
|
|
w.Write([]byte("Done"))
|
|
return nil
|
|
}
|
|
}
|