readysite / website / controllers / audit.go
2.4 KB
audit.go
package controllers

import (
	"net/http"
	"strings"

	"github.com/readysite/readysite/pkg/application"
	"github.com/readysite/readysite/website/internal/helpers"
	"github.com/readysite/readysite/website/models"
)

// Audit returns the audit controller.
func Audit() (string, *AuditController) {
	return "audit", &AuditController{}
}

// AuditController handles audit log viewing.
type AuditController struct {
	application.BaseController
}

// Setup registers routes.
func (c *AuditController) Setup(app *application.App) {
	c.BaseController.Setup(app)
}

// Handle implements Controller interface with value receiver for request isolation.
func (c AuditController) Handle(r *http.Request) application.Controller {
	c.Request = r
	return &c
}

// Pagination returns pagination state for the audit log list.
func (c *AuditController) Pagination() *helpers.Pagination {
	total := c.filteredCount()
	return helpers.NewPagination(c.Request, total)
}

// Filter returns the current filter parameters.
func (c *AuditController) Filter() map[string]string {
	return map[string]string{
		"action":        c.URL.Query().Get("action"),
		"resource_type": c.URL.Query().Get("resource_type"),
	}
}

// AllLogs returns paginated audit logs with optional filtering.
func (c *AuditController) AllLogs() []*models.AuditLog {
	p := c.Pagination()
	query, args := c.buildQuery()
	query += " ORDER BY CreatedAt DESC LIMIT ? OFFSET ?"
	args = append(args, p.PageSize, p.Offset)
	logs, _ := models.AuditLogs.Search(query, args...)
	return logs
}

// LogCount returns the total number of audit logs.
func (c *AuditController) LogCount() int {
	return models.AuditLogs.Count("")
}

// buildQuery constructs the WHERE clause based on filters.
func (c *AuditController) buildQuery() (string, []any) {
	var conditions []string
	var args []any

	if action := c.URL.Query().Get("action"); action != "" {
		conditions = append(conditions, "Action = ?")
		args = append(args, action)
	}
	if resourceType := c.URL.Query().Get("resource_type"); resourceType != "" {
		conditions = append(conditions, "ResourceType = ?")
		args = append(args, resourceType)
	}

	if len(conditions) == 0 {
		return "", nil
	}

	return "WHERE " + strings.Join(conditions, " AND "), args
}

// filteredCount returns the count matching current filters.
func (c *AuditController) filteredCount() int {
	query, args := c.buildQuery()
	return models.AuditLogs.Count(query, args...)
}
← Back