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
+8
View File
@@ -12,12 +12,14 @@ import (
"net/http"
"strings"
audit_model "gitea.dev/models/audit"
"gitea.dev/models/auth"
user_model "gitea.dev/models/user"
"gitea.dev/modules/log"
"gitea.dev/modules/session"
"gitea.dev/modules/setting"
"gitea.dev/modules/web"
"gitea.dev/services/audit"
"gitea.dev/services/context"
"gitea.dev/services/forms"
@@ -57,6 +59,8 @@ func RegenerateScratchTwoFactor(ctx *context.Context) {
return
}
audit.Record(ctx, audit_model.UserTwoFactorRegenerate, ctx.Doer, "two_factor_id", t.ID)
ctx.Flash.Success(ctx.Tr("settings.twofa_scratch_token_regenerated", token))
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
}
@@ -93,6 +97,8 @@ func DisableTwoFactor(ctx *context.Context) {
return
}
audit.Record(ctx, audit_model.UserTwoFactorDisable, ctx.Doer, "two_factor_id", t.ID)
ctx.Flash.Success(ctx.Tr("settings.twofa_disabled"))
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
}
@@ -273,6 +279,8 @@ func EnrollTwoFactorPost(ctx *context.Context) {
return
}
audit.Record(ctx, audit_model.UserTwoFactorEnable, ctx.Doer)
ctx.Flash.Success(ctx.Tr("settings.twofa_enrolled", token))
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
}
+19 -1
View File
@@ -7,12 +7,14 @@ import (
"errors"
"net/http"
audit_model "gitea.dev/models/audit"
user_model "gitea.dev/models/user"
"gitea.dev/modules/auth/openid"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
"gitea.dev/modules/util"
"gitea.dev/modules/web"
"gitea.dev/services/audit"
"gitea.dev/services/context"
"gitea.dev/services/forms"
)
@@ -105,6 +107,9 @@ func settingsOpenIDVerify(ctx *context.Context) {
return
}
log.Trace("Associated OpenID %s to user %s", id, ctx.Doer.Name)
audit.Record(ctx, audit_model.UserOpenIDAdd, ctx.Doer, "openid", oid.URI)
ctx.Flash.Success(ctx.Tr("settings.add_openid_success"))
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
@@ -117,7 +122,17 @@ func DeleteOpenID(ctx *context.Context) {
return
}
if err := user_model.DeleteUserOpenID(ctx, &user_model.UserOpenID{ID: ctx.FormInt64("id"), UID: ctx.Doer.ID}); err != nil {
oid, err := user_model.GetUserOpenIDByID(ctx, ctx.FormInt64("id"), ctx.Doer.ID)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
ctx.HTTPError(http.StatusNotFound)
} else {
ctx.ServerError("GetUserOpenIDByID", err)
}
return
}
if err := user_model.DeleteUserOpenID(ctx, oid); err != nil {
if errors.Is(err, util.ErrNotExist) {
ctx.HTTPError(http.StatusNotFound)
} else {
@@ -125,6 +140,9 @@ func DeleteOpenID(ctx *context.Context) {
}
return
}
audit.Record(ctx, audit_model.UserOpenIDRemove, ctx.Doer, "openid", oid.URI)
log.Trace("OpenID address deleted: %s", ctx.Doer.Name)
ctx.Flash.Success(ctx.Tr("settings.openid_deletion_success"))
@@ -8,12 +8,14 @@ import (
"net/http"
"sort"
audit_model "gitea.dev/models/audit"
auth_model "gitea.dev/models/auth"
"gitea.dev/models/db"
user_model "gitea.dev/models/user"
"gitea.dev/modules/optional"
"gitea.dev/modules/setting"
"gitea.dev/modules/templates"
"gitea.dev/services/audit"
"gitea.dev/services/auth/source/oauth2"
"gitea.dev/services/context"
)
@@ -58,6 +60,8 @@ func DeleteAccountLink(ctx *context.Context) {
if _, err := user_model.RemoveAccountLink(ctx, ctx.Doer, id); err != nil {
ctx.Flash.Error("RemoveAccountLink: " + err.Error())
} else {
audit.Record(ctx, audit_model.UserExternalLoginRemove, ctx.Doer, "auth_source_id", id)
ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success"))
}
}
+16 -3
View File
@@ -9,6 +9,7 @@ import (
"strconv"
"time"
audit_model "gitea.dev/models/audit"
"gitea.dev/models/auth"
user_model "gitea.dev/models/user"
wa "gitea.dev/modules/auth/webauthn"
@@ -16,6 +17,7 @@ import (
"gitea.dev/modules/session"
"gitea.dev/modules/setting"
"gitea.dev/modules/web"
"gitea.dev/services/audit"
"gitea.dev/services/context"
"gitea.dev/services/forms"
@@ -124,13 +126,16 @@ func WebauthnRegisterPost(ctx *context.Context) {
}
// Create the credential
_, err = auth.CreateCredential(ctx, ctx.Doer.ID, name, cred)
dbCred, err = auth.CreateCredential(ctx, ctx.Doer.ID, name, cred)
if err != nil {
ctx.ServerError("CreateCredential", err)
return
}
_ = ctx.Session.Delete("webauthnName")
_ = ctx.Session.Set(session.KeyUserHasTwoFactorAuth, true)
audit.Record(ctx, audit_model.UserWebAuthAdd, ctx.Doer, "credential", dbCred.Name)
ctx.JSON(http.StatusCreated, cred)
}
@@ -141,9 +146,17 @@ func WebauthnDelete(ctx *context.Context) {
return
}
if _, err := auth.DeleteCredential(ctx, ctx.FormInt64("id"), ctx.Doer.ID); err != nil {
ctx.ServerError("GetWebAuthnCredentialByID", err)
cred, err := auth.GetWebAuthnCredentialByID(ctx, ctx.FormInt64("id"))
if err != nil {
ctx.NotFoundOrServerError("GetWebAuthnCredentialByID", auth.IsErrWebAuthnCredentialNotExist, err)
return
}
if ok, err := auth.DeleteCredential(ctx, cred.ID, ctx.Doer.ID); err != nil {
ctx.ServerError("DeleteCredential", err)
return
} else if ok {
audit.Record(ctx, audit_model.UserWebAuthRemove, ctx.Doer, "credential", cred.Name)
}
ctx.JSONRedirect(setting.AppSubURL + "/user/settings/security")
}