Files
NexaVPN/backend/internal/audit/repository.go
nessi 830491cb0d chore: initial project scaffold with admin web, backend, desktop client, and deployment setup
Add monorepo structure for NexaVPN WireGuard control plane including:
- .gitignore for node_modules, build artifacts, and environment files
- README with project overview, monorepo layout, and quick start guide
- Admin web UI with React, Vite, TypeScript, and nginx reverse proxy
- API client with type definitions for users, devices, policies, gateways, and audit logs
- Admin pages for dashboard, users, devices, policies, g
2026-03-15 16:32:34 +01:00

71 lines
1.5 KiB
Go

package audit
import (
"context"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
)
type PGRepository struct {
db *pgxpool.Pool
}
func NewPGRepository(db *pgxpool.Pool) *PGRepository {
return &PGRepository{db: db}
}
func (r *PGRepository) Write(ctx context.Context, entry Entry) error {
const query = `
insert into audit_logs (id, actor_user_id, entity_type, entity_id, event_type, status, message, metadata)
values ($1, $2, $3, $4, $5, $6, $7, $8::jsonb)
`
_, err := r.db.Exec(
ctx,
query,
uuid.New(),
entry.ActorUserID,
entry.EntityType,
entry.EntityID,
entry.EventType,
entry.Status,
entry.Message,
MarshalMetadata(entry.Metadata),
)
return err
}
func (r *PGRepository) List(ctx context.Context, limit int) ([]map[string]any, error) {
rows, err := r.db.Query(ctx, `
select id, event_type, entity_type, status, message, created_at
from audit_logs
order by created_at desc
limit $1
`, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var entries []map[string]any
for rows.Next() {
var id uuid.UUID
var eventType, entityType, status, message string
var createdAt any
if err := rows.Scan(&id, &eventType, &entityType, &status, &message, &createdAt); err != nil {
return nil, err
}
entries = append(entries, map[string]any{
"id": id,
"event_type": eventType,
"entity_type": entityType,
"status": status,
"message": message,
"created_at": createdAt,
})
}
return entries, rows.Err()
}