mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-19 03:03:39 +09:00
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:
co-authored by
bircni
wxiaoguang
parent
4d43445532
commit
da37b7916b
@@ -0,0 +1,109 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package audit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.dev/models/unittest"
|
||||
"gitea.dev/modules/timeutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFindEventsScopeFilters(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
events := []*Event{
|
||||
{Action: UserCreate, ScopeType: ScopeUser, ScopeID: 5, Origin: OriginUI, TimestampUnix: timeutil.TimeStamp(1)},
|
||||
{Action: RepositoryCreate, ScopeType: ScopeRepository, ScopeID: 5, Origin: OriginAPI, TimestampUnix: timeutil.TimeStamp(1)},
|
||||
{Action: RepositoryCreate, ScopeType: ScopeRepository, ScopeID: 6, Origin: OriginCLI, TimestampUnix: timeutil.TimeStamp(1)},
|
||||
{Action: RepositoryCreate, ScopeType: ScopeRepository, ScopeID: 7, Origin: OriginSystem, TimestampUnix: timeutil.TimeStamp(1)},
|
||||
}
|
||||
for _, event := range events {
|
||||
require.NoError(t, InsertEvent(t.Context(), event))
|
||||
}
|
||||
|
||||
byType, _, err := FindEvents(t.Context(), &EventSearchOptions{ScopeType: ScopeRepository})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, byType, 3)
|
||||
|
||||
byID, _, err := FindEvents(t.Context(), &EventSearchOptions{ScopeID: 5})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, byID, 2)
|
||||
|
||||
byScope, _, err := FindEvents(t.Context(), &EventSearchOptions{ScopeType: ScopeRepository, ScopeID: 5})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, byScope, 1)
|
||||
|
||||
byOrigin, _, err := FindEvents(t.Context(), &EventSearchOptions{Origin: OriginAPI})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, byOrigin, 1)
|
||||
|
||||
bySystemOrigin, _, err := FindEvents(t.Context(), &EventSearchOptions{Origin: OriginSystem})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, bySystemOrigin, 1)
|
||||
}
|
||||
|
||||
func TestFindEventsActionPrefixFilter(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
for _, action := range []Action{UserImpersonation, UserImpersonationExit, UserCreate} {
|
||||
require.NoError(t, InsertEvent(t.Context(), &Event{Action: action, ScopeType: ScopeUser, ScopeID: 1, TimestampUnix: timeutil.TimeStamp(1)}))
|
||||
}
|
||||
|
||||
events, _, err := FindEvents(t.Context(), &EventSearchOptions{ActionPrefix: "user:impersonation"})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, events, 2)
|
||||
|
||||
exact, _, err := FindEvents(t.Context(), &EventSearchOptions{Action: UserImpersonationExit})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, exact, 1)
|
||||
assert.Equal(t, UserImpersonationExit, exact[0].Action)
|
||||
}
|
||||
|
||||
// Filtering for an admin must surface what they did while impersonating someone.
|
||||
func TestFindEventsActorFilterIncludesImpersonations(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
events := []*Event{
|
||||
{Action: UserPassword, ActorID: 10, ScopeType: ScopeUser, ScopeID: 10, TimestampUnix: timeutil.TimeStamp(1)},
|
||||
{Action: UserPassword, ActorID: 11, ImpersonatorID: 10, ScopeType: ScopeUser, ScopeID: 11, TimestampUnix: timeutil.TimeStamp(2)},
|
||||
{Action: UserPassword, ActorID: 12, ScopeType: ScopeUser, ScopeID: 12, TimestampUnix: timeutil.TimeStamp(3)},
|
||||
}
|
||||
for _, event := range events {
|
||||
require.NoError(t, InsertEvent(t.Context(), event))
|
||||
}
|
||||
|
||||
byAdmin, _, err := FindEvents(t.Context(), &EventSearchOptions{ActorID: 10})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, byAdmin, 2)
|
||||
|
||||
byImpersonated, _, err := FindEvents(t.Context(), &EventSearchOptions{ActorID: 11})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, byImpersonated, 1)
|
||||
}
|
||||
|
||||
func TestDeleteOldEvents(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
now := time.Now()
|
||||
old := &Event{Action: UserCreate, ScopeType: ScopeUser, ScopeID: 1, TimestampUnix: timeutil.TimeStamp(now.Add(-48 * time.Hour).Unix())}
|
||||
recent := &Event{Action: UserCreate, ScopeType: ScopeUser, ScopeID: 2, TimestampUnix: timeutil.TimeStamp(now.Unix())}
|
||||
require.NoError(t, InsertEvent(t.Context(), old))
|
||||
require.NoError(t, InsertEvent(t.Context(), recent))
|
||||
|
||||
require.NoError(t, DeleteOldEvents(t.Context(), 0)) // keeps everything
|
||||
_, count, err := FindEvents(t.Context(), &EventSearchOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, count)
|
||||
|
||||
require.NoError(t, DeleteOldEvents(t.Context(), 24*time.Hour))
|
||||
remaining, _, err := FindEvents(t.Context(), &EventSearchOptions{})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, remaining, 1)
|
||||
assert.Equal(t, recent.ID, remaining[0].ID)
|
||||
}
|
||||
Reference in New Issue
Block a user