mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-14 19:22:09 +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:
@@ -8,12 +8,14 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
audit_model "gitea.dev/models/audit"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
"gitea.dev/models/db"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/templates"
|
||||
"gitea.dev/modules/util"
|
||||
"gitea.dev/modules/web"
|
||||
"gitea.dev/services/audit"
|
||||
"gitea.dev/services/context"
|
||||
"gitea.dev/services/forms"
|
||||
)
|
||||
@@ -104,6 +106,8 @@ func ApplicationsPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
audit.Record(ctx, audit_model.UserAccessTokenAdd, ctx.Doer, "token", t.Name, "token_scope", t.Scope)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.generate_token_success"))
|
||||
ctx.Flash.Info(t.Token)
|
||||
|
||||
@@ -112,9 +116,14 @@ func ApplicationsPost(ctx *context.Context) {
|
||||
|
||||
// DeleteApplication response for delete user access token
|
||||
func DeleteApplication(ctx *context.Context) {
|
||||
if err := auth_model.DeleteAccessTokenByID(ctx, ctx.FormInt64("id"), ctx.Doer.ID); err != nil {
|
||||
t, err := auth_model.GetAccessTokenByID(ctx, ctx.FormInt64("id"), ctx.Doer.ID)
|
||||
if err != nil {
|
||||
ctx.Flash.Error("GetAccessTokenByID: " + err.Error())
|
||||
} else if err := auth_model.DeleteAccessTokenByID(ctx, t.ID, ctx.Doer.ID); err != nil {
|
||||
ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error())
|
||||
} else {
|
||||
audit.Record(ctx, audit_model.UserAccessTokenRemove, ctx.Doer, "token", t.Name)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.delete_token_success"))
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
audit_model "gitea.dev/models/audit"
|
||||
shared_audit "gitea.dev/routers/web/shared/audit"
|
||||
"gitea.dev/services/context"
|
||||
)
|
||||
|
||||
func ViewAuditLogs(ctx *context.Context) {
|
||||
shared_audit.View(ctx, shared_audit.ViewOptions{
|
||||
Template: "user/settings/audit_logs",
|
||||
ScopeType: audit_model.ScopeUser,
|
||||
ScopeID: ctx.Doer.ID,
|
||||
PageData: map[string]any{"PageIsSettingsAudit": true},
|
||||
})
|
||||
}
|
||||
@@ -9,12 +9,14 @@ import (
|
||||
"net/http"
|
||||
|
||||
asymkey_model "gitea.dev/models/asymkey"
|
||||
audit_model "gitea.dev/models/audit"
|
||||
"gitea.dev/models/db"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/templates"
|
||||
"gitea.dev/modules/web"
|
||||
asymkey_service "gitea.dev/services/asymkey"
|
||||
"gitea.dev/services/audit"
|
||||
"gitea.dev/services/context"
|
||||
"gitea.dev/services/forms"
|
||||
)
|
||||
@@ -68,7 +70,8 @@ func KeysPost(ctx *context.Context) {
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||
return
|
||||
}
|
||||
if _, err = asymkey_service.AddPrincipalKey(ctx, ctx.Doer.ID, content, 0); err != nil {
|
||||
key, err := asymkey_service.AddPrincipalKey(ctx, ctx.Doer.ID, content, 0)
|
||||
if err != nil {
|
||||
ctx.Data["HasPrincipalError"] = true
|
||||
switch {
|
||||
case asymkey_model.IsErrKeyAlreadyExist(err), asymkey_model.IsErrKeyNameAlreadyUsed(err):
|
||||
@@ -81,6 +84,9 @@ func KeysPost(ctx *context.Context) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
audit.Record(ctx, audit_model.UserKeyPrincipalAdd, ctx.Doer, "key", key.Name)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||
case "gpg":
|
||||
@@ -135,6 +141,8 @@ func KeysPost(ctx *context.Context) {
|
||||
for _, key := range keys {
|
||||
keyIDs += key.KeyID
|
||||
keyIDs += ", "
|
||||
|
||||
audit.Record(ctx, audit_model.UserKeyGPGAdd, ctx.Doer, "gpg_key_id", key.KeyID)
|
||||
}
|
||||
if len(keyIDs) > 0 {
|
||||
keyIDs = keyIDs[:len(keyIDs)-2]
|
||||
@@ -189,7 +197,8 @@ func KeysPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = asymkey_model.AddPublicKey(ctx, ctx.Doer.ID, form.Title, content, 0, false); err != nil {
|
||||
key, err := asymkey_model.AddPublicKey(ctx, ctx.Doer.ID, form.Title, content, 0, false)
|
||||
if err != nil {
|
||||
ctx.Data["HasSSHError"] = true
|
||||
switch {
|
||||
case asymkey_model.IsErrKeyAlreadyExist(err):
|
||||
@@ -210,6 +219,9 @@ func KeysPost(ctx *context.Context) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
audit.Record(ctx, audit_model.UserKeySSHAdd, ctx.Doer, "fingerprint", key.Fingerprint)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||
case "verify_ssh":
|
||||
@@ -256,10 +268,18 @@ func DeleteKey(ctx *context.Context) {
|
||||
ctx.JSONError("gpg keys setting is not allowed to be visited")
|
||||
return
|
||||
}
|
||||
key, err := asymkey_model.GetGPGKeyForUserByID(ctx, ctx.Doer.ID, ctx.FormInt64("id"))
|
||||
if err != nil && !asymkey_model.IsErrGPGKeyNotExist(err) {
|
||||
ctx.ServerError("GetGPGKeyForUserByID", err)
|
||||
return
|
||||
}
|
||||
if err := asymkey_model.DeleteGPGKey(ctx, ctx.Doer, ctx.FormInt64("id")); err != nil {
|
||||
ctx.JSONError("Failed to delete PGP key")
|
||||
return
|
||||
}
|
||||
if key != nil {
|
||||
audit.Record(ctx, audit_model.UserKeyGPGRemove, ctx.Doer, "gpg_key_id", key.KeyID)
|
||||
}
|
||||
ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success"))
|
||||
case "ssh":
|
||||
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package setting
|
||||
|
||||
import (
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/templates"
|
||||
"gitea.dev/services/context"
|
||||
@@ -13,9 +14,9 @@ const (
|
||||
tplSettingsOAuthApplicationEdit templates.TplName = "user/settings/applications_oauth2_edit"
|
||||
)
|
||||
|
||||
func newOAuth2CommonHandlers(userID int64) *OAuth2CommonHandlers {
|
||||
func newOAuth2CommonHandlers(owner *user_model.User) *OAuth2CommonHandlers {
|
||||
return &OAuth2CommonHandlers{
|
||||
OwnerID: userID,
|
||||
Owner: owner,
|
||||
BasePathList: setting.AppSubURL + "/user/settings/applications",
|
||||
BasePathEditPrefix: setting.AppSubURL + "/user/settings/applications/oauth2",
|
||||
TplAppEdit: tplSettingsOAuthApplicationEdit,
|
||||
@@ -27,7 +28,7 @@ func OAuthApplicationsPost(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings_title")
|
||||
ctx.Data["PageIsSettingsApplications"] = true
|
||||
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer.ID)
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer)
|
||||
oa.AddApp(ctx)
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ func OAuthApplicationsEdit(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings_title")
|
||||
ctx.Data["PageIsSettingsApplications"] = true
|
||||
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer.ID)
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer)
|
||||
oa.EditSave(ctx)
|
||||
}
|
||||
|
||||
@@ -45,24 +46,24 @@ func OAuthApplicationsRegenerateSecret(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings_title")
|
||||
ctx.Data["PageIsSettingsApplications"] = true
|
||||
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer.ID)
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer)
|
||||
oa.RegenerateSecret(ctx)
|
||||
}
|
||||
|
||||
// OAuth2ApplicationShow displays the given application
|
||||
func OAuth2ApplicationShow(ctx *context.Context) {
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer.ID)
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer)
|
||||
oa.EditShow(ctx)
|
||||
}
|
||||
|
||||
// DeleteOAuth2Application deletes the given oauth2 application
|
||||
func DeleteOAuth2Application(ctx *context.Context) {
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer.ID)
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer)
|
||||
oa.DeleteApp(ctx)
|
||||
}
|
||||
|
||||
// RevokeOAuth2Grant revokes the grant with the given id
|
||||
func RevokeOAuth2Grant(ctx *context.Context) {
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer.ID)
|
||||
oa := newOAuth2CommonHandlers(ctx.Doer)
|
||||
oa.RevokeGrant(ctx)
|
||||
}
|
||||
|
||||
@@ -8,21 +8,36 @@ import (
|
||||
"net/http"
|
||||
|
||||
"gitea.dev/models/auth"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/templates"
|
||||
"gitea.dev/modules/util"
|
||||
"gitea.dev/modules/web"
|
||||
shared_user "gitea.dev/routers/web/shared/user"
|
||||
"gitea.dev/services/audit"
|
||||
"gitea.dev/services/context"
|
||||
"gitea.dev/services/forms"
|
||||
)
|
||||
|
||||
type OAuth2CommonHandlers struct {
|
||||
OwnerID int64 // 0 for instance-wide, otherwise OrgID or UserID
|
||||
Owner *user_model.User // nil for instance-wide, otherwise the Org or User owning the applications
|
||||
BasePathList string // the base URL for the application list page, eg: "/user/setting/applications"
|
||||
BasePathEditPrefix string // the base URL for the application edit page, will be appended with app id, eg: "/user/setting/applications/oauth2"
|
||||
TplAppEdit templates.TplName // the template for the application edit page
|
||||
}
|
||||
|
||||
func (oa *OAuth2CommonHandlers) ownerID() int64 {
|
||||
if oa.Owner != nil {
|
||||
return oa.Owner.ID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// recordAudit emits an OAuth2 application audit event scoped to the owner, which
|
||||
// is nil for instance-wide (admin) applications, an organization, or a user.
|
||||
func (oa *OAuth2CommonHandlers) recordAudit(ctx *context.Context, actions audit.ScopedActions, appName string) {
|
||||
audit.RecordScoped(ctx, oa.Owner, nil, actions, "oauth2_application", appName)
|
||||
}
|
||||
|
||||
func (oa *OAuth2CommonHandlers) renderEditPage(ctx *context.Context, app *auth.OAuth2Application) {
|
||||
ctx.Data["App"] = app
|
||||
ctx.Data["FormActionPath"] = fmt.Sprintf("%s/%d", oa.BasePathEditPrefix, app.ID)
|
||||
@@ -50,7 +65,7 @@ func (oa *OAuth2CommonHandlers) AddApp(ctx *context.Context) {
|
||||
app, err := auth.CreateOAuth2Application(ctx, auth.CreateOAuth2ApplicationOptions{
|
||||
Name: form.Name,
|
||||
RedirectURIs: util.SplitTrimSpace(form.RedirectURIs, "\n"),
|
||||
UserID: oa.OwnerID,
|
||||
UserID: oa.ownerID(),
|
||||
ConfidentialClient: form.ConfidentialClient,
|
||||
SkipSecondaryAuthorization: form.SkipSecondaryAuthorization,
|
||||
})
|
||||
@@ -59,6 +74,8 @@ func (oa *OAuth2CommonHandlers) AddApp(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
oa.recordAudit(ctx, audit.OAuth2ApplicationAdd, app.Name)
|
||||
|
||||
// render the edit page with secret
|
||||
ctx.Flash.Success(ctx.Tr("settings.create_oauth2_application_success"), true)
|
||||
ctx.Data["ClientSecret"], err = app.GenerateClientSecret(ctx)
|
||||
@@ -81,7 +98,7 @@ func (oa *OAuth2CommonHandlers) EditShow(ctx *context.Context) {
|
||||
ctx.ServerError("GetOAuth2ApplicationByID", err)
|
||||
return
|
||||
}
|
||||
if app.UID != oa.OwnerID {
|
||||
if app.UID != oa.ownerID() {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
@@ -102,7 +119,7 @@ func (oa *OAuth2CommonHandlers) EditSave(ctx *context.Context) {
|
||||
ctx.ServerError("GetOAuth2ApplicationByID", err)
|
||||
return
|
||||
}
|
||||
if app.UID != oa.OwnerID {
|
||||
if app.UID != oa.ownerID() {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
@@ -110,18 +127,21 @@ func (oa *OAuth2CommonHandlers) EditSave(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
if ctx.Data["App"], err = auth.UpdateOAuth2Application(ctx, auth.UpdateOAuth2ApplicationOptions{
|
||||
updatedApp, err := auth.UpdateOAuth2Application(ctx, auth.UpdateOAuth2ApplicationOptions{
|
||||
ID: ctx.PathParamInt64("id"),
|
||||
Name: form.Name,
|
||||
RedirectURIs: util.SplitTrimSpace(form.RedirectURIs, "\n"),
|
||||
UserID: oa.OwnerID,
|
||||
UserID: oa.ownerID(),
|
||||
ConfidentialClient: form.ConfidentialClient,
|
||||
SkipSecondaryAuthorization: form.SkipSecondaryAuthorization,
|
||||
}); err != nil {
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("UpdateOAuth2Application", err)
|
||||
return
|
||||
}
|
||||
|
||||
oa.recordAudit(ctx, audit.OAuth2ApplicationUpdate, updatedApp.Name)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.update_oauth2_application_success"))
|
||||
ctx.Redirect(oa.BasePathList)
|
||||
}
|
||||
@@ -137,7 +157,7 @@ func (oa *OAuth2CommonHandlers) RegenerateSecret(ctx *context.Context) {
|
||||
ctx.ServerError("GetOAuth2ApplicationByID", err)
|
||||
return
|
||||
}
|
||||
if app.UID != oa.OwnerID {
|
||||
if app.UID != oa.ownerID() {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
@@ -146,28 +166,59 @@ func (oa *OAuth2CommonHandlers) RegenerateSecret(ctx *context.Context) {
|
||||
ctx.ServerError("GenerateClientSecret", err)
|
||||
return
|
||||
}
|
||||
|
||||
oa.recordAudit(ctx, audit.OAuth2ApplicationSecret, app.Name)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.update_oauth2_application_success"), true)
|
||||
oa.renderEditPage(ctx, app)
|
||||
}
|
||||
|
||||
// DeleteApp deletes the given oauth2 application
|
||||
func (oa *OAuth2CommonHandlers) DeleteApp(ctx *context.Context) {
|
||||
if err := auth.DeleteOAuth2Application(ctx, ctx.PathParamInt64("id"), oa.OwnerID); err != nil {
|
||||
app, err := auth.GetOAuth2ApplicationByID(ctx, ctx.PathParamInt64("id"))
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetOAuth2ApplicationByID", auth.IsErrOAuthApplicationNotFound, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := auth.DeleteOAuth2Application(ctx, app.ID, oa.ownerID()); err != nil {
|
||||
ctx.ServerError("DeleteOAuth2Application", err)
|
||||
return
|
||||
}
|
||||
|
||||
oa.recordAudit(ctx, audit.OAuth2ApplicationRemove, app.Name)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.remove_oauth2_application_success"))
|
||||
ctx.JSONRedirect(oa.BasePathList)
|
||||
}
|
||||
|
||||
// RevokeGrant revokes the grant
|
||||
func (oa *OAuth2CommonHandlers) RevokeGrant(ctx *context.Context) {
|
||||
if err := auth.RevokeOAuth2Grant(ctx, ctx.PathParamInt64("grantId"), oa.OwnerID); err != nil {
|
||||
grant, err := auth.GetOAuth2GrantByID(ctx, ctx.PathParamInt64("grantId"))
|
||||
if err != nil {
|
||||
ctx.ServerError("GetOAuth2GrantByID", err)
|
||||
return
|
||||
}
|
||||
// grants belong to individual users, so this also rejects the instance-wide
|
||||
// (owner nil, ID 0) and organization handlers without assuming who routes here
|
||||
if grant == nil || oa.Owner == nil || grant.UserID != oa.Owner.ID {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
|
||||
app, err := auth.GetOAuth2ApplicationByID(ctx, grant.ApplicationID)
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetOAuth2ApplicationByID", auth.IsErrOAuthApplicationNotFound, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := auth.RevokeOAuth2Grant(ctx, grant.ID, oa.ownerID()); err != nil {
|
||||
ctx.ServerError("RevokeOAuth2Grant", err)
|
||||
return
|
||||
}
|
||||
|
||||
oa.recordAudit(ctx, audit.OAuth2ApplicationRevoke, app.Name)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.revoke_oauth2_grant_success"))
|
||||
ctx.JSONRedirect(oa.BasePathList)
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"gitea.dev/models/webhook"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/templates"
|
||||
"gitea.dev/services/audit"
|
||||
"gitea.dev/services/context"
|
||||
)
|
||||
|
||||
@@ -37,9 +38,14 @@ func Webhooks(ctx *context.Context) {
|
||||
|
||||
// DeleteWebhook response for delete webhook
|
||||
func DeleteWebhook(ctx *context.Context) {
|
||||
if err := webhook.DeleteWebhookByOwnerID(ctx, ctx.Doer.ID, ctx.FormInt64("id")); err != nil {
|
||||
hook, err := webhook.GetWebhookByOwnerID(ctx, ctx.Doer.ID, ctx.FormInt64("id"))
|
||||
if err != nil {
|
||||
ctx.Flash.Error("GetWebhookByOwnerID: " + err.Error())
|
||||
} else if err := webhook.DeleteWebhookByOwnerID(ctx, ctx.Doer.ID, hook.ID); err != nil {
|
||||
ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error())
|
||||
} else {
|
||||
audit.RecordScoped(ctx, ctx.Doer, nil, audit.WebhookRemove, "webhook", hook.URL)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user