diff --git a/admin/accounthttp.go b/admin/accounthttp.go
index fc03d77..098eb59 100644
--- a/admin/accounthttp.go
+++ b/admin/accounthttp.go
@@ -6,9 +6,9 @@ import (
"net/http"
"net/url"
"os"
+ "time"
"arimelody-web/controller"
- "arimelody-web/log"
"arimelody-web/model"
"golang.org/x/crypto/bcrypt"
@@ -115,8 +115,6 @@ func changePasswordHandler(app *model.AppState) http.Handler {
return
}
- app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" changed password by user request. (%s)", session.Account.Username, controller.ResolveIP(r))
-
controller.SetSessionError(app.DB, session, "")
controller.SetSessionMessage(app.DB, session, "Password updated successfully.")
http.Redirect(w, r, "/admin/account", http.StatusFound)
@@ -145,7 +143,11 @@ func deleteAccountHandler(app *model.AppState) http.Handler {
// check password
if err := bcrypt.CompareHashAndPassword([]byte(session.Account.Password), []byte(r.Form.Get("password"))); err != nil {
- app.Log.Warn(log.TYPE_ACCOUNT, "Account \"%s\" attempted account deletion with incorrect password. (%s)", session.Account.Username, controller.ResolveIP(r))
+ fmt.Printf(
+ "[%s] WARN: Account \"%s\" attempted account deletion with incorrect password.\n",
+ time.Now().Format(time.UnixDate),
+ session.Account.Username,
+ )
controller.SetSessionError(app.DB, session, "Incorrect password.")
http.Redirect(w, r, "/admin/account", http.StatusFound)
return
@@ -159,7 +161,11 @@ func deleteAccountHandler(app *model.AppState) http.Handler {
return
}
- app.Log.Info(log.TYPE_ACCOUNT, "Account \"%s\" deleted by user request. (%s)", session.Account.Username, controller.ResolveIP(r))
+ fmt.Printf(
+ "[%s] INFO: Account \"%s\" deleted by user request.\n",
+ time.Now().Format(time.UnixDate),
+ session.Account.Username,
+ )
controller.SetSessionAccount(app.DB, session, nil)
controller.SetSessionError(app.DB, session, "")
@@ -318,8 +324,6 @@ func totpConfirmHandler(app *model.AppState) http.Handler {
return
}
- app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" created TOTP method \"%s\".", session.Account.Username, totp.Name)
-
controller.SetSessionError(app.DB, session, "")
controller.SetSessionMessage(app.DB, session, fmt.Sprintf("TOTP method \"%s\" created successfully.", totp.Name))
http.Redirect(w, r, "/admin/account", http.StatusFound)
@@ -361,8 +365,6 @@ func totpDeleteHandler(app *model.AppState) http.Handler {
return
}
- app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" deleted TOTP method \"%s\".", session.Account.Username, totp.Name)
-
controller.SetSessionError(app.DB, session, "")
controller.SetSessionMessage(app.DB, session, fmt.Sprintf("TOTP method \"%s\" deleted successfully.", totp.Name))
http.Redirect(w, r, "/admin/account", http.StatusFound)
diff --git a/admin/http.go b/admin/http.go
index c70dd1d..0ca61a3 100644
--- a/admin/http.go
+++ b/admin/http.go
@@ -11,7 +11,6 @@ import (
"time"
"arimelody-web/controller"
- "arimelody-web/log"
"arimelody-web/model"
"golang.org/x/crypto/bcrypt"
@@ -40,8 +39,6 @@ func Handler(app *model.AppState) http.Handler {
mux.Handle("/account", requireAccount(accountIndexHandler(app)))
mux.Handle("/account/", requireAccount(http.StripPrefix("/account", accountHandler(app))))
- mux.Handle("/logs", requireAccount(logsHandler(app)))
-
mux.Handle("/release/", requireAccount(http.StripPrefix("/release", serveRelease(app))))
mux.Handle("/artist/", requireAccount(http.StripPrefix("/artist", serveArtist(app))))
mux.Handle("/track/", requireAccount(http.StripPrefix("/track", serveTrack(app))))
@@ -201,12 +198,15 @@ func registerAccountHandler(app *model.AppState) http.Handler {
return
}
- app.Log.Info(log.TYPE_ACCOUNT, "Account \"%s\" (%s) created using invite \"%s\". (%s)", account.Username, account.ID, invite.Code, controller.ResolveIP(r))
+ fmt.Printf(
+ "[%s]: Account registered: %s (%s)\n",
+ time.Now().Format(time.UnixDate),
+ account.Username,
+ account.ID,
+ )
err = controller.DeleteInvite(app.DB, invite.Code)
- if err != nil {
- app.Log.Warn(log.TYPE_ACCOUNT, "Failed to delete expired invite \"%s\": %v", invite.Code, err)
- }
+ if err != nil { fmt.Fprintf(os.Stderr, "WARN: Failed to delete expired invite: %v\n", err) }
// registration success!
controller.SetSessionAccount(app.DB, session, &account)
@@ -277,7 +277,11 @@ func loginHandler(app *model.AppState) http.Handler {
err = bcrypt.CompareHashAndPassword([]byte(account.Password), []byte(password))
if err != nil {
- app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" attempted login with incorrect password. (%s)", account.Username, controller.ResolveIP(r))
+ fmt.Printf(
+ "[%s] INFO: Account \"%s\" attempted login with incorrect password.\n",
+ time.Now().Format(time.UnixDate),
+ account.Username,
+ )
controller.SetSessionError(app.DB, session, "Invalid username or password.")
render()
return
@@ -303,11 +307,15 @@ func loginHandler(app *model.AppState) http.Handler {
return
}
- // login success!
- // TODO: log login activity to user
- app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" logged in. (%s)", account.Username, controller.ResolveIP(r))
- app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" does not have any TOTP methods assigned.", account.Username)
+ fmt.Printf(
+ "[%s] INFO: Account \"%s\" logged in\n",
+ time.Now().Format(time.UnixDate),
+ account.Username,
+ )
+ // TODO: log login activity to user
+
+ // login success!
err = controller.SetSessionAccount(app.DB, session, account)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to set session account: %v\n", err)
@@ -363,7 +371,6 @@ func loginTOTPHandler(app *model.AppState) http.Handler {
totpCode := r.FormValue("totp")
if len(totpCode) != controller.TOTP_CODE_LENGTH {
- app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" failed login (Invalid TOTP). (%s)", session.AttemptAccount.Username, controller.ResolveIP(r))
controller.SetSessionError(app.DB, session, "Invalid TOTP.")
render()
return
@@ -377,13 +384,17 @@ func loginTOTPHandler(app *model.AppState) http.Handler {
return
}
if totpMethod == nil {
- app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" failed login (Invalid TOTP). (%s)", session.AttemptAccount.Username, controller.ResolveIP(r))
controller.SetSessionError(app.DB, session, "Invalid TOTP.")
render()
return
}
- app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" logged in with TOTP method \"%s\". (%s)", session.AttemptAccount.Username, totpMethod.Name, controller.ResolveIP(r))
+ fmt.Printf(
+ "[%s] INFO: Account \"%s\" logged in with method \"%s\"\n",
+ time.Now().Format(time.UnixDate),
+ session.AttemptAccount.Username,
+ totpMethod.Name,
+ )
err = controller.SetSessionAccount(app.DB, session, session.AttemptAccount)
if err != nil {
diff --git a/admin/logshttp.go b/admin/logshttp.go
deleted file mode 100644
index 93dc5b7..0000000
--- a/admin/logshttp.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package admin
-
-import (
- "arimelody-web/log"
- "arimelody-web/model"
- "fmt"
- "net/http"
- "os"
- "strings"
-)
-
-func logsHandler(app *model.AppState) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if r.Method != http.MethodGet {
- http.NotFound(w, r)
- return
- }
-
- session := r.Context().Value("session").(*model.Session)
-
- levelFilter := []log.LogLevel{}
- typeFilter := []string{}
-
- query := r.URL.Query().Get("q")
-
- for key, value := range r.URL.Query() {
- if strings.HasPrefix(key, "level-") && value[0] == "on" {
- m := map[string]log.LogLevel{
- "info": log.LEVEL_INFO,
- "warn": log.LEVEL_WARN,
- }
- level, ok := m[strings.TrimPrefix(key, "level-")]
- if ok {
- levelFilter = append(levelFilter, level)
- }
- continue
- }
-
- if strings.HasPrefix(key, "type-") && value[0] == "on" {
- typeFilter = append(typeFilter, string(strings.TrimPrefix(key, "type-")))
- continue
- }
- }
-
- logs, err := app.Log.Search(levelFilter, typeFilter, query, 100, 0)
- if err != nil {
- fmt.Fprintf(os.Stderr, "WARN: Failed to fetch audit logs: %v\n", err)
- http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
- return
- }
-
- type LogsResponse struct {
- Session *model.Session
- Logs []*log.Log
- }
-
- err = logsTemplate.Execute(w, LogsResponse{
- Session: session,
- Logs: logs,
- })
- if err != nil {
- fmt.Fprintf(os.Stderr, "WARN: Failed to render audit logs page: %v\n", err)
- http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
- return
- }
- })
-}
diff --git a/admin/releasehttp.go b/admin/releasehttp.go
index 7ef4d37..be5052b 100644
--- a/admin/releasehttp.go
+++ b/admin/releasehttp.go
@@ -22,7 +22,7 @@ func serveRelease(app *model.AppState) http.Handler {
http.NotFound(w, r)
return
}
- fmt.Printf("WARN: Failed to pull full release data for %s: %s\n", releaseID, err)
+ fmt.Printf("FATAL: Failed to pull full release data for %s: %s\n", releaseID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
@@ -86,7 +86,7 @@ func serveAddCredit(app *model.AppState, release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
artists, err := controller.GetArtistsNotOnRelease(app.DB, release.ID)
if err != nil {
- fmt.Printf("WARN: Failed to pull artists not on %s: %s\n", release.ID, err)
+ fmt.Printf("FATAL: Failed to pull artists not on %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
@@ -113,7 +113,7 @@ func serveNewCredit(app *model.AppState) http.Handler {
artistID := strings.Split(r.URL.Path, "/")[3]
artist, err := controller.GetArtist(app.DB, artistID)
if err != nil {
- fmt.Printf("WARN: Failed to pull artists %s: %s\n", artistID, err)
+ fmt.Printf("FATAL: Failed to pull artists %s: %s\n", artistID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
@@ -166,7 +166,7 @@ func serveAddTrack(app *model.AppState, release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tracks, err := controller.GetTracksNotOnRelease(app.DB, release.ID)
if err != nil {
- fmt.Printf("WARN: Failed to pull tracks not on %s: %s\n", release.ID, err)
+ fmt.Printf("FATAL: Failed to pull tracks not on %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
diff --git a/admin/static/logs.css b/admin/static/logs.css
deleted file mode 100644
index 6ed91b5..0000000
--- a/admin/static/logs.css
+++ /dev/null
@@ -1,85 +0,0 @@
-main {
- width: min(1080px, calc(100% - 2em))!important
-}
-
-form {
- margin: 1em 0;
-}
-
-div#search {
- display: flex;
-}
-
-#search input {
- margin: 0;
- flex-grow: 1;
-
- border-right: none;
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
-}
-
-#search button {
- padding: 0 .5em;
-
- border-top-left-radius: 0;
- border-bottom-left-radius: 0;
-}
-
-form #filters p {
- margin: .5em 0 0 0;
-}
-form #filters label {
- display: inline;
-}
-form #filters input {
- margin-right: 1em;
- display: inline;
-}
-
-#logs {
- width: 100%;
- border-collapse: collapse;
-}
-
-#logs tr {
-}
-
-#logs tr td {
- border-bottom: 1px solid #8888;
-}
-
-#logs tr td:nth-child(even) {
- background: #00000004;
-}
-
-#logs th, #logs td {
- padding: .4em .8em;
-}
-
-td, th {
- width: 1%;
- text-align: left;
- white-space: nowrap;
-}
-td.log-level,
-th.log-level,
-td.log-type,
-th.log-type {
- text-align: center;
-}
-td.log-content,
-td.log-content {
- width: 100%;
-}
-
-.log:hover {
- background: #fff8;
-}
-
-.log.warn {
- background: #ffe86a;
-}
-.log.warn:hover {
- background: #ffec81;
-}
diff --git a/admin/templates.go b/admin/templates.go
index 12cdf08..49c118b 100644
--- a/admin/templates.go
+++ b/admin/templates.go
@@ -1,12 +1,8 @@
package admin
import (
- "arimelody-web/log"
- "fmt"
- "html/template"
- "path/filepath"
- "strings"
- "time"
+ "html/template"
+ "path/filepath"
)
var indexTemplate = template.Must(template.ParseFiles(
@@ -52,37 +48,6 @@ var totpConfirmTemplate = template.Must(template.ParseFiles(
filepath.Join("admin", "views", "totp-confirm.html"),
))
-var logsTemplate = template.Must(template.New("layout.html").Funcs(template.FuncMap{
- "parseLevel": func(level log.LogLevel) string {
- switch level {
- case log.LEVEL_INFO:
- return "INFO"
- case log.LEVEL_WARN:
- return "WARN"
- }
- return fmt.Sprintf("%d?", level)
- },
- "titleCase": func(logType string) string {
- runes := []rune(logType)
- for i, r := range runes {
- if (i == 0 || runes[i - 1] == ' ') && r >= 'a' && r <= 'z' {
- runes[i] = r + ('A' - 'a')
- }
- }
- return string(runes)
- },
- "lower": func(str string) string { return strings.ToLower(str) },
- "prettyTime": func(t time.Time) string {
- // return t.Format("2006-01-02 15:04:05")
- // return t.Format("15:04:05, 2 Jan 2006")
- return t.Format("02 Jan 2006, 15:04:05")
- },
-}).ParseFiles(
- filepath.Join("admin", "views", "layout.html"),
- filepath.Join("views", "prideflag.html"),
- filepath.Join("admin", "views", "logs.html"),
-))
-
var releaseTemplate = template.Must(template.ParseFiles(
filepath.Join("admin", "views", "layout.html"),
filepath.Join("views", "prideflag.html"),
diff --git a/admin/views/layout.html b/admin/views/layout.html
index 52b0620..8c34c8e 100644
--- a/admin/views/layout.html
+++ b/admin/views/layout.html
@@ -23,14 +23,7 @@
- {{if .Session.Account}}
-
- {{end}}
-
-
{{if .Session.Account}}
account ({{.Session.Account.Username}})
diff --git a/admin/views/logs.html b/admin/views/logs.html
deleted file mode 100644
index e3a3ccb..0000000
--- a/admin/views/logs.html
+++ /dev/null
@@ -1,68 +0,0 @@
-{{define "head"}}
-
Audit Logs - ari melody 💫
-
-
-
-{{end}}
-
-{{define "content"}}
-
- Audit Logs
-
-
-
-
-
-
-
-
- Time |
- Level |
- Type |
- Message |
-
-
-
- {{range .Logs}}
-
- {{prettyTime .CreatedAt}} |
- {{parseLevel .Level}} |
- {{titleCase .Type}} |
- {{.Content}} |
-
- {{end}}
-
-
-
-{{end}}
diff --git a/api/api.go b/api/api.go
index d3c83ce..4edd07b 100644
--- a/api/api.go
+++ b/api/api.go
@@ -27,7 +27,7 @@ func Handler(app *model.AppState) http.Handler {
http.NotFound(w, r)
return
}
- fmt.Printf("WARN: Error while retrieving artist %s: %s\n", artistID, err)
+ fmt.Printf("FATAL: Error while retrieving artist %s: %s\n", artistID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
@@ -69,7 +69,7 @@ func Handler(app *model.AppState) http.Handler {
http.NotFound(w, r)
return
}
- fmt.Printf("WARN: Error while retrieving release %s: %s\n", releaseID, err)
+ fmt.Printf("FATAL: Error while retrieving release %s: %s\n", releaseID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
@@ -111,7 +111,7 @@ func Handler(app *model.AppState) http.Handler {
http.NotFound(w, r)
return
}
- fmt.Printf("WARN: Error while retrieving track %s: %s\n", trackID, err)
+ fmt.Printf("FATAL: Error while retrieving track %s: %s\n", trackID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
diff --git a/api/artist.go b/api/artist.go
index 9006cc3..51c9d62 100644
--- a/api/artist.go
+++ b/api/artist.go
@@ -11,7 +11,6 @@ import (
"time"
"arimelody-web/controller"
- "arimelody-web/log"
"arimelody-web/model"
)
@@ -89,8 +88,6 @@ func ServeArtist(app *model.AppState, artist *model.Artist) http.Handler {
func CreateArtist(app *model.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
-
var artist model.Artist
err := json.NewDecoder(r.Body).Decode(&artist)
if err != nil {
@@ -115,16 +112,12 @@ func CreateArtist(app *model.AppState) http.Handler {
return
}
- app.Log.Info(log.TYPE_ARTIST, "Artist \"%s\" created by \"%s\".", artist.Name, session.Account.Username)
-
w.WriteHeader(http.StatusCreated)
})
}
func UpdateArtist(app *model.AppState, artist *model.Artist) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
-
err := json.NewDecoder(r.Body).Decode(&artist)
if err != nil {
fmt.Printf("WARN: Failed to update artist: %s\n", err)
@@ -165,15 +158,11 @@ func UpdateArtist(app *model.AppState, artist *model.Artist) http.Handler {
fmt.Printf("WARN: Failed to update artist %s: %s\n", artist.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
-
- app.Log.Info(log.TYPE_ARTIST, "Artist \"%s\" updated by \"%s\".", artist.Name, session.Account.Username)
})
}
func DeleteArtist(app *model.AppState, artist *model.Artist) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
-
err := controller.DeleteArtist(app.DB, artist.ID)
if err != nil {
if strings.Contains(err.Error(), "no rows") {
@@ -183,7 +172,5 @@ func DeleteArtist(app *model.AppState, artist *model.Artist) http.Handler {
fmt.Printf("WARN: Failed to delete artist %s: %s\n", artist.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
-
- app.Log.Info(log.TYPE_ARTIST, "Artist \"%s\" deleted by \"%s\".", artist.Name, session.Account.Username)
})
}
diff --git a/api/release.go b/api/release.go
index efed8dd..b89cec8 100644
--- a/api/release.go
+++ b/api/release.go
@@ -11,7 +11,6 @@ import (
"time"
"arimelody-web/controller"
- "arimelody-web/log"
"arimelody-web/model"
)
@@ -190,7 +189,10 @@ func ServeCatalog(app *model.AppState) http.Handler {
func CreateRelease(app *model.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
+ if r.Method != http.MethodPost {
+ http.NotFound(w, r)
+ return
+ }
var release model.Release
err := json.NewDecoder(r.Body).Decode(&release)
@@ -224,8 +226,6 @@ func CreateRelease(app *model.AppState) http.Handler {
return
}
- app.Log.Info(log.TYPE_MUSIC, "Release \"%s\" created by \"%s\".", release.ID, session.Account.Username)
-
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
encoder := json.NewEncoder(w)
@@ -240,8 +240,6 @@ func CreateRelease(app *model.AppState) http.Handler {
func UpdateRelease(app *model.AppState, release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
-
if r.URL.Path == "/" {
http.NotFound(w, r)
return
@@ -306,15 +304,11 @@ func UpdateRelease(app *model.AppState, release *model.Release) http.Handler {
fmt.Printf("WARN: Failed to update release %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
-
- app.Log.Info(log.TYPE_MUSIC, "Release \"%s\" updated by \"%s\".", release.ID, session.Account.Username)
})
}
func UpdateReleaseTracks(app *model.AppState, release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
-
var trackIDs = []string{}
err := json.NewDecoder(r.Body).Decode(&trackIDs)
if err != nil {
@@ -331,15 +325,11 @@ func UpdateReleaseTracks(app *model.AppState, release *model.Release) http.Handl
fmt.Printf("WARN: Failed to update tracks for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
-
- app.Log.Info(log.TYPE_MUSIC, "Tracklist for release \"%s\" updated by \"%s\".", release.ID, session.Account.Username)
})
}
func UpdateReleaseCredits(app *model.AppState, release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
-
type creditJSON struct {
Artist string
Role string
@@ -376,14 +366,15 @@ func UpdateReleaseCredits(app *model.AppState, release *model.Release) http.Hand
fmt.Printf("WARN: Failed to update links for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
-
- app.Log.Info(log.TYPE_MUSIC, "Credits for release \"%s\" updated by \"%s\".", release.ID, session.Account.Username)
})
}
func UpdateReleaseLinks(app *model.AppState, release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
+ if r.Method != http.MethodPut {
+ http.NotFound(w, r)
+ return
+ }
var links = []*model.Link{}
err := json.NewDecoder(r.Body).Decode(&links)
@@ -401,15 +392,11 @@ func UpdateReleaseLinks(app *model.AppState, release *model.Release) http.Handle
fmt.Printf("WARN: Failed to update links for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
-
- app.Log.Info(log.TYPE_MUSIC, "Links for release \"%s\" updated by \"%s\".", release.ID, session.Account.Username)
})
}
func DeleteRelease(app *model.AppState, release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
-
err := controller.DeleteRelease(app.DB, release.ID)
if err != nil {
if strings.Contains(err.Error(), "no rows") {
@@ -419,7 +406,5 @@ func DeleteRelease(app *model.AppState, release *model.Release) http.Handler {
fmt.Printf("WARN: Failed to delete release %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
-
- app.Log.Info(log.TYPE_MUSIC, "Release \"%s\" deleted by \"%s\".", release.ID, session.Account.Username)
})
}
diff --git a/api/track.go b/api/track.go
index e7d7c07..c342e08 100644
--- a/api/track.go
+++ b/api/track.go
@@ -6,7 +6,6 @@ import (
"net/http"
"arimelody-web/controller"
- "arimelody-web/log"
"arimelody-web/model"
)
@@ -76,7 +75,10 @@ func ServeTrack(app *model.AppState, track *model.Track) http.Handler {
func CreateTrack(app *model.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- session := r.Context().Value("session").(*model.Session)
+ if r.Method != http.MethodPost {
+ http.NotFound(w, r)
+ return
+ }
var track model.Track
err := json.NewDecoder(r.Body).Decode(&track)
@@ -97,8 +99,6 @@ func CreateTrack(app *model.AppState) http.Handler {
return
}
- app.Log.Info(log.TYPE_MUSIC, "Track \"%s\" (%s) created by \"%s\".", track.Title, track.ID, session.Account.Username)
-
w.Header().Add("Content-Type", "text/plain")
w.WriteHeader(http.StatusCreated)
w.Write([]byte(id))
@@ -107,13 +107,11 @@ func CreateTrack(app *model.AppState) http.Handler {
func UpdateTrack(app *model.AppState, track *model.Track) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if r.URL.Path == "/" {
+ if r.Method != http.MethodPut || r.URL.Path == "/" {
http.NotFound(w, r)
return
}
- session := r.Context().Value("session").(*model.Session)
-
err := json.NewDecoder(r.Body).Decode(&track)
if err != nil {
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
@@ -132,8 +130,6 @@ func UpdateTrack(app *model.AppState, track *model.Track) http.Handler {
return
}
- app.Log.Info(log.TYPE_MUSIC, "Track \"%s\" (%s) updated by \"%s\".", track.Title, track.ID, session.Account.Username)
-
w.Header().Add("Content-Type", "application/json")
encoder := json.NewEncoder(w)
encoder.SetIndent("", "\t")
@@ -146,20 +142,16 @@ func UpdateTrack(app *model.AppState, track *model.Track) http.Handler {
func DeleteTrack(app *model.AppState, track *model.Track) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if r.URL.Path == "/" {
+ if r.Method != http.MethodDelete || r.URL.Path == "/" {
http.NotFound(w, r)
return
}
- session := r.Context().Value("session").(*model.Session)
-
var trackID = r.URL.Path[1:]
err := controller.DeleteTrack(app.DB, trackID)
if err != nil {
fmt.Printf("WARN: Failed to delete track %s: %s\n", trackID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
-
- app.Log.Info(log.TYPE_MUSIC, "Track \"%s\" (%s) deleted by \"%s\".", track.Title, track.ID, session.Account.Username)
})
}
diff --git a/api/uploads.go b/api/uploads.go
index 60ab7dd..ddcf6ee 100644
--- a/api/uploads.go
+++ b/api/uploads.go
@@ -1,7 +1,6 @@
package api
import (
- "arimelody-web/log"
"arimelody-web/model"
"bufio"
"encoding/base64"
@@ -50,7 +49,5 @@ func HandleImageUpload(app *model.AppState, data *string, directory string, file
return "", nil
}
- app.Log.Info(log.TYPE_FILES, "\"%s/%s.%s\" created.", directory, filename, ext)
-
return filename, nil
}
diff --git a/controller/ip.go b/controller/ip.go
deleted file mode 100644
index 4b1126d..0000000
--- a/controller/ip.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package controller
-
-import (
- "net/http"
- "slices"
-)
-
-// Returns the request's original IP address, resolving the `x-forwarded-for`
-// header if the request originates from a trusted proxy.
-func ResolveIP(r *http.Request) string {
- trustedProxies := []string{ "10.4.20.69" }
- if slices.Contains(trustedProxies, r.RemoteAddr) {
- forwardedFor := r.Header.Get("x-forwarded-for")
- if len(forwardedFor) > 0 {
- return forwardedFor
- }
- }
- return r.RemoteAddr
-}
diff --git a/controller/migrator.go b/controller/migrator.go
index b053a27..d0011ee 100644
--- a/controller/migrator.go
+++ b/controller/migrator.go
@@ -8,7 +8,7 @@ import (
"github.com/jmoiron/sqlx"
)
-const DB_VERSION int = 3
+const DB_VERSION int = 2
func CheckDBVersionAndMigrate(db *sqlx.DB) {
db.MustExec("CREATE SCHEMA IF NOT EXISTS arimelody")
@@ -41,10 +41,6 @@ func CheckDBVersionAndMigrate(db *sqlx.DB) {
ApplyMigration(db, "001-pre-versioning")
oldDBVersion = 2
- case 2:
- ApplyMigration(db, "002-audit-logs")
- oldDBVersion = 3
-
}
}
diff --git a/log/log.go b/log/log.go
deleted file mode 100644
index 3d023ab..0000000
--- a/log/log.go
+++ /dev/null
@@ -1,142 +0,0 @@
-package log
-
-import (
- "fmt"
- "os"
- "time"
-
- "github.com/jmoiron/sqlx"
-)
-
-type (
- Logger struct {
- DB *sqlx.DB
- }
-
- Log struct {
- ID string `json:"id" db:"id"`
- Level LogLevel `json:"level" db:"level"`
- Type string `json:"type" db:"type"`
- Content string `json:"content" db:"content"`
- CreatedAt time.Time `json:"created_at" db:"created_at"`
- }
-)
-
-const (
- TYPE_ACCOUNT string = "account"
- TYPE_MUSIC string = "music"
- TYPE_ARTIST string = "artist"
- TYPE_BLOG string = "blog"
- TYPE_ARTWORK string = "artwork"
- TYPE_FILES string = "files"
- TYPE_MISC string = "misc"
-)
-
-type LogLevel int
-const (
- LEVEL_INFO LogLevel = 0
- LEVEL_WARN LogLevel = 1
-)
-
-const DEFAULT_LOG_PAGE_LENGTH = 25
-
-func (self *Logger) Info(logType string, format string, args ...any) {
- logString := fmt.Sprintf(format, args...)
- fmt.Printf("[%s] [%s] INFO: %s\n", time.Now().Format(time.UnixDate), logType, logString)
- err := createLog(self.DB, LEVEL_INFO, logType, logString)
- if err != nil {
- fmt.Fprintf(os.Stderr, "WARN: Failed to push log to database: %v\n", err)
- }
-}
-
-func (self *Logger) Warn(logType string, format string, args ...any) {
- logString := fmt.Sprintf(format, args...)
- fmt.Fprintf(os.Stderr, "[%s] [%s] WARN: %s\n", time.Now().Format(time.UnixDate), logType, logString)
- err := createLog(self.DB, LEVEL_WARN, logType, logString)
- if err != nil {
- fmt.Fprintf(os.Stderr, "WARN: Failed to push log to database: %v\n", err)
- }
-}
-
-func (self *Logger) Fetch(id string) (*Log, error) {
- log := Log{}
- err := self.DB.Get(&log, "SELECT * FROM auditlog WHERE id=$1", id)
- return &log, err
-}
-
-func (self *Logger) Search(levelFilters []LogLevel, typeFilters []string, content string, limit int, offset int) ([]*Log, error) {
- logs := []*Log{}
-
- params := []any{ limit, offset }
- conditions := ""
-
- if len(content) > 0 {
- content = "%" + content + "%"
- conditions += " WHERE content LIKE $3"
- params = append(params, content)
- }
-
- if len(levelFilters) > 0 {
- if len(conditions) > 0 {
- conditions += " AND level IN ("
- } else {
- conditions += " WHERE level IN ("
- }
- for i := range levelFilters {
- conditions += fmt.Sprintf("$%d", len(params) + 1)
- if i < len(levelFilters) - 1 {
- conditions += ","
- }
- params = append(params, levelFilters[i])
- }
- conditions += ")"
- }
-
- if len(typeFilters) > 0 {
- if len(conditions) > 0 {
- conditions += " AND type IN ("
- } else {
- conditions += " WHERE type IN ("
- }
- for i := range typeFilters {
- conditions += fmt.Sprintf("$%d", len(params) + 1)
- if i < len(typeFilters) - 1 {
- conditions += ","
- }
- params = append(params, typeFilters[i])
- }
- conditions += ")"
- }
-
- query := fmt.Sprintf(
- "SELECT * FROM auditlog%s ORDER BY created_at DESC LIMIT $1 OFFSET $2",
- conditions,
- )
-
- /*
- fmt.Printf("%s (", query)
- for i, param := range params {
- fmt.Print(param)
- if i < len(params) - 1 {
- fmt.Print(", ")
- }
- }
- fmt.Print(")\n")
- */
-
- err := self.DB.Select(&logs, query, params...)
- if err != nil {
- return nil, err
- }
- return logs, nil
-}
-
-func createLog(db *sqlx.DB, logLevel LogLevel, logType string, content string) error {
- _, err := db.Exec(
- "INSERT INTO auditlog (level, type, content) VALUES ($1,$2,$3)",
- logLevel,
- logType,
- content,
- )
- return err
-}
diff --git a/main.go b/main.go
index 03e9d77..7e8e06f 100644
--- a/main.go
+++ b/main.go
@@ -3,7 +3,7 @@ package main
import (
"errors"
"fmt"
- stdLog "log"
+ "log"
"math"
"math/rand"
"net/http"
@@ -19,7 +19,6 @@ import (
"arimelody-web/controller"
"arimelody-web/model"
"arimelody-web/templates"
- "arimelody-web/log"
"arimelody-web/view"
"github.com/jmoiron/sqlx"
@@ -78,8 +77,6 @@ func main() {
app.DB.SetMaxIdleConns(10)
defer app.DB.Close()
- app.Log = log.Logger{ DB: app.DB }
-
// handle command arguments
if len(os.Args) > 1 {
arg := os.Args[1]
@@ -121,7 +118,6 @@ func main() {
os.Exit(1)
}
- app.Log.Info(log.TYPE_ACCOUNT, "TOTP method \"%s\" for \"%s\" created via config utility.", totp.Name, account.Username)
url := controller.GenerateTOTPURI(account.Username, totp.Secret)
fmt.Printf("%s\n", url)
return
@@ -151,7 +147,6 @@ func main() {
os.Exit(1)
}
- app.Log.Info(log.TYPE_ACCOUNT, "TOTP method \"%s\" for \"%s\" deleted via config utility.", totpName, account.Username)
fmt.Printf("TOTP method \"%s\" deleted.\n", totpName)
return
@@ -227,7 +222,6 @@ func main() {
fmt.Fprintf(os.Stderr, "FATAL: Failed to clean up TOTP methods: %v\n", err)
os.Exit(1)
}
- app.Log.Info(log.TYPE_ACCOUNT, "TOTP methods pruned via config utility.")
fmt.Printf("Cleaned up dangling TOTP methods successfully.\n")
return
@@ -239,7 +233,6 @@ func main() {
os.Exit(1)
}
- app.Log.Info(log.TYPE_ACCOUNT, "Invite generted via config utility (%s).", invite.Code)
fmt.Printf(
"Here you go! This code expires in %d hours: %s\n",
int(math.Ceil(invite.ExpiresAt.Sub(invite.CreatedAt).Hours())),
@@ -255,7 +248,6 @@ func main() {
os.Exit(1)
}
- app.Log.Info(log.TYPE_ACCOUNT, "Invites purged via config utility.")
fmt.Printf("Invites deleted successfully.\n")
return
@@ -308,12 +300,11 @@ func main() {
account.Password = string(hashedPassword)
err = controller.UpdateAccount(app.DB, account)
if err != nil {
- fmt.Fprintf(os.Stderr, "FATAL: Failed to update password: %v\n", err)
+ fmt.Fprintf(os.Stderr, "FATAL: Failed to delete account: %v\n", err)
os.Exit(1)
}
- app.Log.Info(log.TYPE_ACCOUNT, "Password for '%s' updated via config utility.", account.Username)
- fmt.Printf("Password for \"%s\" updated successfully.\n", account.Username)
+ fmt.Printf("Account \"%s\" deleted successfully.\n", account.Username)
return
case "deleteAccount":
@@ -348,30 +339,9 @@ func main() {
os.Exit(1)
}
- app.Log.Info(log.TYPE_ACCOUNT, "Account '%s' deleted via config utility.", account.Username)
fmt.Printf("Account \"%s\" deleted successfully.\n", account.Username)
return
-
- case "logs":
- // TODO: add log search parameters
- logs, err := app.Log.Search([]log.LogLevel{}, []string{}, "", 100, 0)
- if err != nil {
- fmt.Fprintf(os.Stderr, "FATAL: Failed to fetch logs: %v\n", err)
- os.Exit(1)
- }
- for _, item := range(logs) {
- levelStr := ""
- switch item.Level {
- case log.LEVEL_INFO:
- levelStr = "INFO"
- case log.LEVEL_WARN:
- levelStr = "WARN"
- default:
- levelStr = fmt.Sprintf("? (%d)", item.Level)
- }
- fmt.Printf("[%s] %s:\n\t[%s] %s: %s\n", item.CreatedAt.Format(time.UnixDate), item.ID, item.Type, levelStr, item.Content)
- }
- return
+
}
// command help
@@ -431,7 +401,7 @@ func main() {
// start the web server!
mux := createServeMux(&app)
fmt.Printf("Now serving at http://%s:%d\n", app.Config.Host, app.Config.Port)
- stdLog.Fatal(
+ log.Fatal(
http.ListenAndServe(fmt.Sprintf("%s:%d", app.Config.Host, app.Config.Port),
HTTPLog(DefaultHeaders(mux)),
))
diff --git a/model/appstate.go b/model/appstate.go
index 2516b6e..6a965d5 100644
--- a/model/appstate.go
+++ b/model/appstate.go
@@ -1,10 +1,6 @@
package model
-import (
- "github.com/jmoiron/sqlx"
-
- "arimelody-web/log"
-)
+import "github.com/jmoiron/sqlx"
type (
DBConfig struct {
@@ -33,6 +29,5 @@ type (
AppState struct {
DB *sqlx.DB
Config Config
- Log log.Logger
}
)
diff --git a/model/release.go b/model/release.go
index 42d6fba..7b0c8d5 100644
--- a/model/release.go
+++ b/model/release.go
@@ -24,7 +24,6 @@ type (
Tracks []*Track `json:"tracks"`
Credits []*Credit `json:"credits"`
Links []*Link `json:"links"`
- CreatedAt time.Time `json:"-" db:"created_at"`
}
)
diff --git a/schema-migration/000-init.sql b/schema-migration/000-init.sql
index f70dee6..42b982a 100644
--- a/schema-migration/000-init.sql
+++ b/schema-migration/000-init.sql
@@ -2,15 +2,6 @@
-- Tables
--
--- Audit logs
-CREATE TABLE arimelody.auditlog (
- id UUID DEFAULT gen_random_uuid(),
- level int NOT NULL DEFAULT 0,
- type TEXT NOT NULL,
- content TEXT NOT NULL,
- created_at TIMESTAMP NOT NULL DEFAULT current_timestamp
-);
-
-- Accounts
CREATE TABLE arimelody.account (
id UUID DEFAULT gen_random_uuid(),
@@ -18,7 +9,7 @@ CREATE TABLE arimelody.account (
password TEXT NOT NULL,
email TEXT,
avatar_url TEXT,
- created_at TIMESTAMP NOT NULL DEFAULT current_timestamp
+ created_at TIMESTAMP DEFAULT current_timestamp
);
ALTER TABLE arimelody.account ADD CONSTRAINT account_pk PRIMARY KEY (id);
@@ -83,8 +74,7 @@ CREATE TABLE arimelody.musicrelease (
buyname text,
buylink text,
copyright text,
- copyrightURL text,
- created_at TIMESTAMP NOT NULL DEFAULT current_timestamp,
+ copyrightURL text
);
ALTER TABLE arimelody.musicrelease ADD CONSTRAINT musicrelease_pk PRIMARY KEY (id);
diff --git a/schema-migration/002-audit-logs.sql b/schema-migration/002-audit-logs.sql
deleted file mode 100644
index 7da43b5..0000000
--- a/schema-migration/002-audit-logs.sql
+++ /dev/null
@@ -1,12 +0,0 @@
--- Audit logs
-CREATE TABLE arimelody.auditlog (
- id UUID DEFAULT gen_random_uuid(),
- level int NOT NULL DEFAULT 0,
- type TEXT NOT NULL,
- content TEXT NOT NULL,
- created_at TIMESTAMP NOT NULL DEFAULT current_timestamp
-);
-
--- Need moar timestamps
-ALTER TABLE arimelody.musicrelease ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT current_timestamp;
-ALTER TABLE arimelody.account ALTER COLUMN created_at SET NOT NULL;
diff --git a/view/music.go b/view/music.go
index 2d40ef0..89e428c 100644
--- a/view/music.go
+++ b/view/music.go
@@ -37,7 +37,7 @@ func ServeCatalog(app *model.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
releases, err := controller.GetAllReleases(app.DB, true, 0, true)
if err != nil {
- fmt.Printf("WARN: Failed to pull releases for catalog: %s\n", err)
+ fmt.Printf("FATAL: Failed to pull releases for catalog: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}