admin page updates

This commit is contained in:
2026-02-14 14:54:06 +11:00
parent 136adabb92
commit f0e7962af5
22 changed files with 2136 additions and 318 deletions

View File

@@ -11,13 +11,19 @@ import (
"git.haelnorr.com/h/oslstats/internal/throw"
"git.haelnorr.com/h/oslstats/internal/validation"
adminview "git.haelnorr.com/h/oslstats/internal/view/adminview"
"git.haelnorr.com/h/timefmt"
"github.com/pkg/errors"
"github.com/uptrace/bun"
)
// AdminAuditLogsPage renders the full admin dashboard page with audit logs section
// AdminAuditLogsPage renders the full admin dashboard page with audit logs section (GET request)
func AdminAuditLogsPage(s *hws.Server, conn *bun.DB) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
pageOpts := pageOptsFromQuery(s, w, r)
if pageOpts == nil {
return
}
var logs *db.List[db.AuditLog]
var users []*db.User
var actions []string
@@ -26,12 +32,6 @@ func AdminAuditLogsPage(s *hws.Server, conn *bun.DB) http.Handler {
if ok := db.WithReadTx(s, w, r, conn, func(ctx context.Context, tx bun.Tx) (bool, error) {
var err error
// Get page options from query
pageOpts := pageOptsFromQuery(s, w, r)
if pageOpts == nil {
return false, nil
}
// Get filters from query
filters, ok := getAuditFiltersFromQuery(s, w, r)
if !ok {
@@ -72,9 +72,14 @@ func AdminAuditLogsPage(s *hws.Server, conn *bun.DB) http.Handler {
})
}
// AdminAuditLogsList shows audit logs (HTMX content replacement - full section with filters)
// AdminAuditLogsList shows the full audit logs list with filters (POST request for HTMX)
func AdminAuditLogsList(s *hws.Server, conn *bun.DB) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
pageOpts := pageOptsFromForm(s, w, r)
if pageOpts == nil {
return
}
var logs *db.List[db.AuditLog]
var users []*db.User
var actions []string
@@ -83,15 +88,12 @@ func AdminAuditLogsList(s *hws.Server, conn *bun.DB) http.Handler {
if ok := db.WithReadTx(s, w, r, conn, func(ctx context.Context, tx bun.Tx) (bool, error) {
var err error
// Get page options from form
pageOpts := pageOptsFromForm(s, w, r)
if pageOpts == nil {
// Get filters from form
filters, ok := getAuditFiltersFromForm(s, w, r)
if !ok {
return false, nil
}
// No filters for initial section load
filters := db.NewAuditLogFilter()
// Get audit logs
logs, err = db.GetAuditLogs(ctx, tx, pageOpts, filters)
if err != nil {
@@ -126,20 +128,19 @@ func AdminAuditLogsList(s *hws.Server, conn *bun.DB) http.Handler {
})
}
// AdminAuditLogsFilter handles filter requests and returns only the results table
// AdminAuditLogsFilter returns only the results container (table + pagination) for HTMX updates
func AdminAuditLogsFilter(s *hws.Server, conn *bun.DB) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
pageOpts := pageOptsFromForm(s, w, r)
if pageOpts == nil {
return
}
var logs *db.List[db.AuditLog]
if ok := db.WithReadTx(s, w, r, conn, func(ctx context.Context, tx bun.Tx) (bool, error) {
var err error
// Get page options from form
pageOpts := pageOptsFromForm(s, w, r)
if pageOpts == nil {
return false, nil
}
// Get filters from form
filters, ok := getAuditFiltersFromForm(s, w, r)
if !ok {
@@ -157,6 +158,7 @@ func AdminAuditLogsFilter(s *hws.Server, conn *bun.DB) http.Handler {
return
}
// Return only the results container, not the full page with filters
renderSafely(adminview.AuditLogsResults(logs), s, r, w)
})
}
@@ -201,7 +203,8 @@ func AdminAuditLogDetail(s *hws.Server, conn *bun.DB) http.Handler {
// getAuditFiltersFromQuery extracts audit log filters from query string
func getAuditFiltersFromQuery(s *hws.Server, w http.ResponseWriter, r *http.Request) (*db.AuditLogFilter, bool) {
g := validation.NewQueryGetter(r)
return buildAuditFilters(g, s, w, r)
filters, ok := buildAuditFilters(g, s, w, r)
return filters, ok
}
// getAuditFiltersFromForm extracts audit log filters from form data
@@ -217,57 +220,38 @@ func getAuditFiltersFromForm(s *hws.Server, w http.ResponseWriter, r *http.Reque
func buildAuditFilters(g validation.Getter, s *hws.Server, w http.ResponseWriter, r *http.Request) (*db.AuditLogFilter, bool) {
filters := db.NewAuditLogFilter()
// User ID filter (optional)
userID := g.Int("user_id").Optional().Min(1).Value
userIDs := g.IntList("user_id").Values()
actions := g.StringList("action").Values()
resourceTypes := g.StringList("resource_type").Values()
results := g.StringList("result").Values()
format := timefmt.NewBuilder().DayNumeric2().Slash().
MonthNumeric2().Slash().Year4().Build()
startDate := g.Time("start_date", format).Optional().Value
endDate := g.Time("end_date", format).Optional().Value
// Action filter (optional)
action := g.String("action").TrimSpace().Optional().Value
// Resource Type filter (optional)
resourceType := g.String("resource_type").TrimSpace().Optional().Value
// Result filter (optional)
result := g.String("result").TrimSpace().Optional().AllowedValues([]string{"success", "denied", "error"}).Value
// Date range filter (optional)
startDateStr := g.String("start_date").TrimSpace().Optional().Value
endDateStr := g.String("end_date").TrimSpace().Optional().Value
// Validate
if !g.ValidateAndError(s, w, r) {
return nil, false
}
// Apply filters
if userID > 0 {
filters.UserID(userID)
if len(userIDs) > 0 {
filters.UserIDs(userIDs)
}
if len(actions) > 0 {
filters.Actions(actions)
}
if len(resourceTypes) > 0 {
filters.ResourceTypes(resourceTypes)
}
if len(results) > 0 {
filters.Results(results)
}
if action != "" {
filters.Action(action)
if !startDate.IsZero() {
filters.DateRange(startDate.Unix(), 0)
}
if resourceType != "" {
filters.ResourceType(resourceType)
}
if result != "" {
filters.Result(result)
}
// Parse and apply date range
if startDateStr != "" {
if startDate, err := time.Parse("2006-01-02", startDateStr); err == nil {
filters.DateRange(startDate.Unix(), 0)
}
}
if endDateStr != "" {
if endDate, err := time.Parse("2006-01-02", endDateStr); err == nil {
// Set to end of day
endOfDay := endDate.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
filters.DateRange(0, endOfDay.Unix())
}
if !endDate.IsZero() {
endOfDay := endDate.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
filters.DateRange(0, endOfDay.Unix())
}
return filters, true