Skip to content

feat(admin): audit log page in the admin panel - #20

Merged
letreset merged 1 commit into
mainfrom
feature/audit-log
Sep 27, 2026
Merged

letreset merged 1 commit into
mainfrom
feature/audit-log

Conversation

@letreset

Copy link
Copy Markdown
Owner

Store successful audit events and list them on Admin > Audit log

  • New AuditEvent entity (time, event, actor, IP, feed, target, detail, package id/version) with an AddAuditEvents migration for Sqlite, SqlServer, PostgreSql and MySql, and an index on TimestampUtc.
  • WebAuditLog is the one path for every AUDIT line: the NuGet API lines of PackagePublishController and SymbolController moved onto it. Message format and placeholders are unchanged; all lines now use the PaGetto.Web.Audit.WebAuditLog log category (docs and appsettings.json updated).
  • Only Information (successful) events are stored; denied and failed attempts stay log-only, so a noisy client can't flood the table. Each event is stored in its own DI scope, so recording one never saves changes the caller hasn't saved yet (e.g. mirror edits on Feed settings), and a storage failure is logged without failing the request.
  • Pages/Admin/Audit (admins only, new tab): paged (50 per page), newest first, filters for event, actor, feed, target or package id and a UTC date range. Dates are culture-independent (Html.DisplayDate).
  • Audit:RetentionDays (default 30, 0 keeps events forever, negative values fail validation) applied by AuditRetentionService at startup and then daily.
  • WebAuditLog methods are now async (AdminAsync, PackageAsync, SymbolAsync); call sites updated, including group_updated from feat(admin): edit the name and description of a group #15, which is also added to the documented event table.
  • Tests: AuditEventServiceTests, AuditRetentionServiceTests, AuditModelFacts (filters, paging, non-admin redirect), WebAuditLogFacts, PackagePublishControllerFacts (stored only on success), ValidatePaGettoOptionsTests, and an AuditLogIntegrationTests push through the API. Docs for the page and the config key, and rows U1 to U4 in testenv/UI-TESTS.md.

Verified U1 to U4 against the testenv snapshot with a locally built image: the migration applies to the snapshot, group create/delete and an API push by alice show up, the rejected duplicate push does not, filters work, and a non-admin is redirected.

Not covered: a successful symbol push through the NuGet API writes no audit line today, so it doesn't appear on the page either (web UI symbol uploads do).

Addresses #13

Successful audit events are now stored in a new AuditEvents table (with
a migration for every provider) and listed on Admin > Audit log: paged,
newest first, filterable by event, actor, feed, target or package id and
a range of UTC days. Only admins can open it.

WebAuditLog is the one path for every AUDIT line: the NuGet API lines of
PackagePublishController and SymbolController moved onto it. The line
format and placeholders are unchanged, but all lines now use the
PaGetto.Web.Audit.WebAuditLog log category. Only Information events are
stored; denied and failed attempts are still only logged, so a noisy
client can't fill the table. Events are stored in a scope of their own,
so recording one never saves changes the caller hasn't saved yet, and a
failure to store one is logged without failing the request.

Audit:RetentionDays (default 30, 0 keeps events forever, validated at
startup) is applied by AuditRetentionService at startup and then daily.

Closes #13
@letreset
letreset merged commit df942ef into main Sep 27, 2026
10 checks passed
@letreset
letreset deleted the feature/audit-log branch September 27, 2026 23:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant