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}}