feat: Add audit logging (#38189)

Co-authored-by: bircni <bircni@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
bircni
2026-09-12 10:15:23 +02:00
committed by GitHub
parent 4d43445532
commit da37b7916b
136 changed files with 3864 additions and 209 deletions
+16
View File
@@ -0,0 +1,16 @@
{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin monitor")}}
<div class="admin-setting-content">
<h4 class="ui top attached header flex-left-right">
<span>{{ctx.Locale.Tr "audit.title"}}</span>
<a class="ui primary small button" href="{{AppSubUrl}}/-/admin/monitor/audit_logs/export{{if $.Page.GetParams}}?{{$.Page.GetParams}}{{end}}">
{{svg "octicon-download"}} {{ctx.Locale.Tr "audit.export"}}
</a>
</h4>
{{if not .AuditRecordEnabled}}
<div class="ui warning message">
{{ctx.Locale.Tr "audit.disabled"}}
</div>
{{end}}
{{template "shared/audit/list" .}}
</div>
{{template "admin/layout_footer" .}}
+4 -1
View File
@@ -101,9 +101,12 @@
<a class="{{if .PageIsAdminNotices}}active {{end}}item" href="{{AppSubUrl}}/-/admin/notices">
{{ctx.Locale.Tr "admin.notices"}}
</a>
<details class="item" {{if or .PageIsAdminMonitorStats .PageIsAdminMonitorCron .PageIsAdminMonitorQueue .PageIsAdminMonitorTrace}}open{{end}}>
<details class="item" {{if or .PageIsAdminMonitorAudit .PageIsAdminMonitorStats .PageIsAdminMonitorCron .PageIsAdminMonitorQueue .PageIsAdminMonitorTrace}}open{{end}}>
<summary>{{ctx.Locale.Tr "admin.monitor"}}</summary>
<div class="menu">
<a class="{{if .PageIsAdminMonitorAudit}}active {{end}}item" href="{{AppSubUrl}}/-/admin/monitor/audit_logs">
{{ctx.Locale.Tr "audit.title"}}
</a>
<a class="{{if .PageIsAdminMonitorStats}}active {{end}}item" href="{{AppSubUrl}}/-/admin/monitor/stats">
{{ctx.Locale.Tr "admin.monitor.stats"}}
</a>
+6
View File
@@ -0,0 +1,6 @@
{{template "org/settings/layout_head" (dict "ctxData" . "pageClass" "organization settings")}}
<div class="org-setting-content">
<h4 class="ui top attached header">{{ctx.Locale.Tr "audit.title"}}</h4>
{{template "shared/audit/list" .}}
</div>
{{template "org/settings/layout_footer" .}}
+3
View File
@@ -47,5 +47,8 @@
</div>
</details>
{{end}}
<a class="{{if .PageIsSettingsAudit}}active {{end}}item" href="{{.OrgLink}}/settings/audit_logs">
{{ctx.Locale.Tr "audit.title"}}
</a>
</div>
</div>
+6
View File
@@ -0,0 +1,6 @@
{{template "repo/settings/layout_head" (dict "ctxData" . "pageClass" "repository settings")}}
<div class="repo-setting-content">
<h4 class="ui top attached header">{{ctx.Locale.Tr "audit.title"}}</h4>
{{template "shared/audit/list" .}}
</div>
{{template "repo/settings/layout_footer" .}}
+3
View File
@@ -57,5 +57,8 @@
{{end}}
</div>
</details>
<a class="{{if .PageIsSettingsAudit}}active {{end}}item" href="{{.RepoLink}}/settings/audit_logs">
{{ctx.Locale.Tr "audit.title"}}
</a>
</div>
</div>
+89
View File
@@ -0,0 +1,89 @@
<div class="ui attached segment">
<form class="ui form ignore-dirty tw-flex tw-flex-wrap tw-gap-2">
{{if .AuditSort}}<input type="hidden" name="sort" value="{{.AuditSort}}">{{end}}
<div class="ui small action input tw-flex-1">
<input type="text" name="actor" value="{{.AuditFilterActor}}" placeholder="{{ctx.Locale.Tr "audit.filter.actor"}}">
{{template "shared/search/button"}}
</div>
<div class="ui small input">
<select class="ui dropdown" name="action">
<option value="">{{ctx.Locale.Tr "audit.filter.action"}}</option>
{{range $action := .AuditActions}}
<option{{if eq $.AuditFilterAction (print $action)}} selected{{end}} value="{{$action}}">{{$action}}</option>
{{end}}
</select>
</div>
<div class="ui small input">
<select class="ui dropdown" name="origin">
<option value="">{{ctx.Locale.Tr "audit.filter.origin"}}</option>
{{range $origin := .AuditOrigins}}
<option{{if eq $.AuditFilterOrigin (print $origin)}} selected{{end}} value="{{$origin}}">{{$origin}}</option>
{{end}}
</select>
</div>
</form>
</div>
<div class="ui attached table segment">
<table class="ui very basic striped table unstackable">
<thead>
<tr>
<th>{{ctx.Locale.Tr "audit.actor"}}</th>
<th>{{ctx.Locale.Tr "audit.scope"}}</th>
<th>{{ctx.Locale.Tr "audit.action"}}</th>
<th>{{ctx.Locale.Tr "audit.origin"}}</th>
<th>{{ctx.Locale.Tr "audit.details"}}</th>
<th>{{ctx.Locale.Tr "audit.ip_address"}}</th>
<th data-sortt-asc="timestamp_asc" data-sortt-desc="timestamp_desc">{{ctx.Locale.Tr "audit.timestamp"}}{{SortArrow "timestamp_asc" "timestamp_desc" $.AuditSort false}}</th>
</tr>
</thead>
<tbody>
{{range $event := .AuditEvents}}
<tr>
<td>
{{with $impersonator := $event.Impersonator}}
{{if $impersonator.HasLink}}
<a href="{{$impersonator.HomeLink}}">{{$impersonator.DisplayName}}</a>
{{else}}
{{$impersonator.DisplayName}}
{{end}}
<span class="text small">{{ctx.Locale.Tr "audit.impersonating_as"}}</span>
{{end}}
{{if $event.Actor.DisplayName}}
{{if $event.Actor.HasLink}}
<a href="{{$event.Actor.HomeLink}}">{{$event.Actor.DisplayName}}</a>
{{else}}
{{$event.Actor.DisplayName}}
{{end}}
{{else}}
<span class="text small">{{ctx.Locale.Tr "audit.deleted.actor"}}</span>
{{end}}
{{if $event.ActorCredential}}
<div><code class="text small">{{$event.ActorCredential}}</code></div>
{{end}}
</td>
<td>
{{if $event.Scope.DisplayName}}
{{if $event.Scope.HasLink}}
<a href="{{$event.Scope.HomeLink}}">{{$event.Scope.DisplayName}}</a>
{{else}}
{{$event.Scope.DisplayName}}
{{end}}
{{else}}
<span class="text small">{{ctx.Locale.Tr "audit.deleted.type" $event.Scope.Type $event.Scope.ID}}</span>
{{end}}
</td>
<td><code>{{$event.Action}}</code></td>
<td><code>{{$event.Origin}}</code></td>
<td>
{{$event.Message}}
</td>
<td>{{$event.IPAddress}}</td>
<td>{{DateUtils.FullTime $event.Time}}</td>
</tr>
{{else}}
<tr><td colspan="7">{{ctx.Locale.Tr "audit.no_events"}}</td></tr>
{{end}}
</tbody>
</table>
</div>
{{template "base/paginate" .}}
+6
View File
@@ -0,0 +1,6 @@
{{template "user/settings/layout_head" (dict "ctxData" . "pageClass" "user settings audit")}}
<div class="user-setting-content">
<h4 class="ui top attached header">{{ctx.Locale.Tr "audit.title"}}</h4>
{{template "shared/audit/list" .}}
</div>
{{template "user/settings/layout_footer" .}}
+3
View File
@@ -33,6 +33,9 @@
{{ctx.Locale.Tr "settings.ssh_gpg_keys"}}
</a>
{{end}}
<a class="{{if .PageIsSettingsAudit}}active {{end}}item" href="{{AppSubUrl}}/user/settings/audit_logs">
{{ctx.Locale.Tr "audit.title"}}
</a>
{{if .EnableActions}}
<details class="item" {{if or .PageIsUserSettingsActionsGeneral .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables .PageIsSharedSettingsScopedWorkflows}}open{{end}}>
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary>