diff --git a/admin/accounthttp.go b/admin/accounthttp.go
index aa1e042..408b4c5 100644
--- a/admin/accounthttp.go
+++ b/admin/accounthttp.go
@@ -63,7 +63,7 @@ func accountIndexHandler(app *model.AppState) http.Handler {
session.Message = sessionMessage
session.Error = sessionError
- err = pages["account"].Execute(w, accountResponse{
+ err = accountTemplate.Execute(w, accountResponse{
Session: session,
TOTPs: totps,
})
@@ -199,7 +199,7 @@ func totpSetupHandler(app *model.AppState) http.Handler {
session := r.Context().Value("session").(*model.Session)
- err := pages["totp-setup"].Execute(w, totpSetupData{ Session: session })
+ err := totpSetupTemplate.Execute(w, totpSetupData{ Session: session })
if err != nil {
fmt.Printf("WARN: Failed to render TOTP setup page: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
@@ -216,6 +216,7 @@ func totpSetupHandler(app *model.AppState) http.Handler {
Session *model.Session
TOTP *model.TOTP
NameEscaped string
+ QRBase64Image string
}
err := r.ParseForm()
@@ -242,7 +243,7 @@ func totpSetupHandler(app *model.AppState) http.Handler {
if err != nil {
fmt.Printf("WARN: Failed to create TOTP method: %s\n", err)
controller.SetSessionError(app.DB, session, "Something went wrong. Please try again.")
- err := pages["totp-setup"].Execute(w, totpSetupData{ Session: session })
+ err := totpSetupTemplate.Execute(w, totpSetupData{ Session: session })
if err != nil {
fmt.Printf("WARN: Failed to render TOTP setup page: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
@@ -250,10 +251,24 @@ func totpSetupHandler(app *model.AppState) http.Handler {
return
}
- err = pages["totp-confirm"].Execute(w, totpSetupData{
+ qrBase64Image, err := controller.GenerateQRCode(
+ controller.GenerateTOTPURI(session.Account.Username, totp.Secret))
+ if err != nil {
+ fmt.Printf("WARN: Failed to generate TOTP setup QR code: %s\n", err)
+ controller.SetSessionError(app.DB, session, "Something went wrong. Please try again.")
+ err := totpSetupTemplate.Execute(w, totpSetupData{ Session: session })
+ if err != nil {
+ fmt.Printf("WARN: Failed to render TOTP setup page: %s\n", err)
+ http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
+ }
+ return
+ }
+
+ err = totpConfirmTemplate.Execute(w, totpSetupData{
Session: session,
TOTP: &totp,
NameEscaped: url.PathEscape(totp.Name),
+ QRBase64Image: qrBase64Image,
})
if err != nil {
fmt.Printf("WARN: Failed to render TOTP confirm page: %s\n", err)
@@ -304,18 +319,12 @@ func totpConfirmHandler(app *model.AppState) http.Handler {
return
}
- fmt.Printf(
- "TOTP:\n\tName: %s\n\tSecret: %s\n",
- totp.Name,
- totp.Secret,
- )
-
confirmCode := controller.GenerateTOTP(totp.Secret, 0)
if code != confirmCode {
confirmCodeOffset := controller.GenerateTOTP(totp.Secret, 1)
if code != confirmCodeOffset {
controller.SetSessionError(app.DB, session, "Incorrect TOTP code. Please try again.")
- err = pages["totp-confirm"].Execute(w, totpConfirmData{
+ err = totpConfirmTemplate.Execute(w, totpConfirmData{
Session: session,
TOTP: totp,
})
diff --git a/admin/artisthttp.go b/admin/artisthttp.go
index 5979493..6dfbbfd 100644
--- a/admin/artisthttp.go
+++ b/admin/artisthttp.go
@@ -39,7 +39,7 @@ func serveArtist(app *model.AppState) http.Handler {
session := r.Context().Value("session").(*model.Session)
- err = pages["artist"].Execute(w, ArtistResponse{
+ err = artistTemplate.Execute(w, ArtistResponse{
Session: session,
Artist: artist,
Credits: credits,
diff --git a/admin/http.go b/admin/http.go
index 42b7e46..6fd8f59 100644
--- a/admin/http.go
+++ b/admin/http.go
@@ -20,7 +20,7 @@ func Handler(app *model.AppState) http.Handler {
mux := http.NewServeMux()
mux.Handle("/qr-test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- qrB64Img, err := controller.GenerateQRCode([]byte("super epic mega gaming test message. be sure to buy free2play on bandcamp so i can put food on my family"))
+ qrB64Img, err := controller.GenerateQRCode("super epic mega gaming test message. be sure to buy free2play on bandcamp so i can put food on my family")
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to generate QR code: %v\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
@@ -87,7 +87,7 @@ func AdminIndexHandler(app *model.AppState) http.Handler {
Tracks []*model.Track
}
- err = pages["index"].Execute(w, IndexData{
+ err = indexTemplate.Execute(w, IndexData{
Session: session,
Releases: releases,
Artists: artists,
@@ -116,7 +116,7 @@ func registerAccountHandler(app *model.AppState) http.Handler {
}
render := func() {
- err := pages["register"].Execute(w, registerData{ Session: session })
+ err := registerTemplate.Execute(w, registerData{ Session: session })
if err != nil {
fmt.Printf("WARN: Error rendering create account page: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
@@ -229,7 +229,7 @@ func loginHandler(app *model.AppState) http.Handler {
}
render := func() {
- err := pages["login"].Execute(w, loginData{ Session: session })
+ err := loginTemplate.Execute(w, loginData{ Session: session })
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Error rendering admin login page: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
@@ -307,7 +307,7 @@ func loginHandler(app *model.AppState) http.Handler {
Username string
Password string
}
- err = pages["login-totp"].Execute(w, loginTOTPData{
+ err = loginTOTPTemplate.Execute(w, loginTOTPData{
Session: session,
Username: credentials.Username,
Password: credentials.Password,
@@ -379,7 +379,7 @@ func logoutHandler(app *model.AppState) http.Handler {
Path: "/",
})
- err = pages["logout"].Execute(w, nil)
+ err = logoutTemplate.Execute(w, nil)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to render logout page: %v\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
diff --git a/admin/releasehttp.go b/admin/releasehttp.go
index cd73e98..be5052b 100644
--- a/admin/releasehttp.go
+++ b/admin/releasehttp.go
@@ -60,7 +60,7 @@ func serveRelease(app *model.AppState) http.Handler {
Release *model.Release
}
- err = pages["release"].Execute(w, ReleaseResponse{
+ err = releaseTemplate.Execute(w, ReleaseResponse{
Session: session,
Release: release,
})
@@ -74,7 +74,7 @@ func serveRelease(app *model.AppState) http.Handler {
func serveEditCredits(release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
- err := components["editcredits"].Execute(w, release)
+ err := editCreditsTemplate.Execute(w, release)
if err != nil {
fmt.Printf("Error rendering edit credits component for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
@@ -97,7 +97,7 @@ func serveAddCredit(app *model.AppState, release *model.Release) http.Handler {
}
w.Header().Set("Content-Type", "text/html")
- err = components["addcredit"].Execute(w, response{
+ err = addCreditTemplate.Execute(w, response{
ReleaseID: release.ID,
Artists: artists,
})
@@ -123,7 +123,7 @@ func serveNewCredit(app *model.AppState) http.Handler {
}
w.Header().Set("Content-Type", "text/html")
- err = components["newcredit"].Execute(w, artist)
+ err = newCreditTemplate.Execute(w, artist)
if err != nil {
fmt.Printf("Error rendering new credit component for %s: %s\n", artist.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
@@ -134,7 +134,7 @@ func serveNewCredit(app *model.AppState) http.Handler {
func serveEditLinks(release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
- err := components["editlinks"].Execute(w, release)
+ err := editLinksTemplate.Execute(w, release)
if err != nil {
fmt.Printf("Error rendering edit links component for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
@@ -151,7 +151,7 @@ func serveEditTracks(release *model.Release) http.Handler {
Add func(a int, b int) int
}
- err := components["edittracks"].Execute(w, editTracksData{
+ err := editTracksTemplate.Execute(w, editTracksData{
Release: release,
Add: func(a, b int) int { return a + b },
})
@@ -177,7 +177,7 @@ func serveAddTrack(app *model.AppState, release *model.Release) http.Handler {
}
w.Header().Set("Content-Type", "text/html")
- err = components["addtrack"].Execute(w, response{
+ err = addTrackTemplate.Execute(w, response{
ReleaseID: release.ID,
Tracks: tracks,
})
@@ -204,7 +204,7 @@ func serveNewTrack(app *model.AppState) http.Handler {
}
w.Header().Set("Content-Type", "text/html")
- err = components["newtrack"].Execute(w, track)
+ err = newTrackTemplate.Execute(w, track)
if err != nil {
fmt.Printf("Error rendering new track component for %s: %s\n", track.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
diff --git a/admin/templates.go b/admin/templates.go
index d9a74ca..49c118b 100644
--- a/admin/templates.go
+++ b/admin/templates.go
@@ -1,80 +1,90 @@
package admin
import (
- "html/template"
- "path/filepath"
+ "html/template"
+ "path/filepath"
)
-var pages = map[string]*template.Template{
- "index": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "components", "release", "release-list-item.html"),
- filepath.Join("admin", "views", "index.html"),
- )),
+var indexTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "components", "release", "release-list-item.html"),
+ filepath.Join("admin", "views", "index.html"),
+))
- "login": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "login.html"),
- )),
- "login-totp": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "login-totp.html"),
- )),
- "register": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "register.html"),
- )),
- "logout": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "logout.html"),
- )),
- "account": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "edit-account.html"),
- )),
- "totp-setup": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "totp-setup.html"),
- )),
- "totp-confirm": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "totp-confirm.html"),
- )),
+var loginTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "views", "login.html"),
+))
+var loginTOTPTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "views", "login-totp.html"),
+))
+var registerTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "views", "register.html"),
+))
+var logoutTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "views", "logout.html"),
+))
+var accountTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "views", "edit-account.html"),
+))
+var totpSetupTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "views", "totp-setup.html"),
+))
+var totpConfirmTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "views", "totp-confirm.html"),
+))
- "release": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "edit-release.html"),
- )),
- "artist": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "edit-artist.html"),
- )),
- "track": template.Must(template.ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "components", "release", "release-list-item.html"),
- filepath.Join("admin", "views", "edit-track.html"),
- )),
-}
+var releaseTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "views", "edit-release.html"),
+))
+var artistTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "views", "edit-artist.html"),
+))
+var trackTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "views", "layout.html"),
+ filepath.Join("views", "prideflag.html"),
+ filepath.Join("admin", "components", "release", "release-list-item.html"),
+ filepath.Join("admin", "views", "edit-track.html"),
+))
-var components = map[string]*template.Template{
- "editcredits": template.Must(template.ParseFiles(filepath.Join("admin", "components", "credits", "editcredits.html"))),
- "addcredit": template.Must(template.ParseFiles(filepath.Join("admin", "components", "credits", "addcredit.html"))),
- "newcredit": template.Must(template.ParseFiles(filepath.Join("admin", "components", "credits", "newcredit.html"))),
+var editCreditsTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "components", "credits", "editcredits.html"),
+))
+var addCreditTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "components", "credits", "addcredit.html"),
+))
+var newCreditTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "components", "credits", "newcredit.html"),
+))
- "editlinks": template.Must(template.ParseFiles(filepath.Join("admin", "components", "links", "editlinks.html"))),
+var editLinksTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "components", "links", "editlinks.html"),
+))
- "edittracks": template.Must(template.ParseFiles(filepath.Join("admin", "components", "tracks", "edittracks.html"))),
- "addtrack": template.Must(template.ParseFiles(filepath.Join("admin", "components", "tracks", "addtrack.html"))),
- "newtrack": template.Must(template.ParseFiles(filepath.Join("admin", "components", "tracks", "newtrack.html"))),
-}
+var editTracksTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "components", "tracks", "edittracks.html"),
+))
+var addTrackTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "components", "tracks", "addtrack.html"),
+))
+var newTrackTemplate = template.Must(template.ParseFiles(
+ filepath.Join("admin", "components", "tracks", "newtrack.html"),
+))
diff --git a/admin/trackhttp.go b/admin/trackhttp.go
index 9436671..a92f81a 100644
--- a/admin/trackhttp.go
+++ b/admin/trackhttp.go
@@ -39,7 +39,7 @@ func serveTrack(app *model.AppState) http.Handler {
session := r.Context().Value("session").(*model.Session)
- err = pages["track"].Execute(w, TrackResponse{
+ err = trackTemplate.Execute(w, TrackResponse{
Session: session,
Track: track,
Releases: releases,
diff --git a/admin/views/totp-confirm.html b/admin/views/totp-confirm.html
index ac39e52..b0810e2 100644
--- a/admin/views/totp-confirm.html
+++ b/admin/views/totp-confirm.html
@@ -3,6 +3,9 @@