Change Log Updates

* Delete all change logs AboutUserID on account deletion, and export
  them in the data export zip.
* Log admin changes to ban/admin status of other users.
* Log user deactivations/reactivations and deletions (self serve or
  admin deletion).
This commit is contained in:
Noah Petherbridge 2024-02-25 17:28:40 -08:00
parent f4d176a538
commit 3142e0ce84
5 changed files with 48 additions and 0 deletions

View File

@ -41,6 +41,9 @@ func Deactivate() http.HandlerFunc {
session.LogoutUser(w, r) session.LogoutUser(w, r)
session.Flash(w, r, "Your account has been deactivated and you are now logged out. If you wish to re-activate your account, sign in again with your username and password.") session.Flash(w, r, "Your account has been deactivated and you are now logged out. If you wish to re-activate your account, sign in again with your username and password.")
templates.Redirect(w, "/") templates.Redirect(w, "/")
// Log the change.
models.LogUpdated(currentUser, nil, "users", currentUser.ID, "Deactivated their account.", nil)
return return
} }
@ -78,5 +81,8 @@ func Reactivate() http.HandlerFunc {
session.Flash(w, r, "Welcome back! Your account has been reactivated.") session.Flash(w, r, "Welcome back! Your account has been reactivated.")
templates.Redirect(w, "/") templates.Redirect(w, "/")
// Log the change.
models.LogUpdated(currentUser, nil, "users", currentUser.ID, "Reactivated their account.", nil)
}) })
} }

View File

@ -1,9 +1,11 @@
package account package account
import ( import (
"fmt"
"net/http" "net/http"
"strings" "strings"
"code.nonshy.com/nonshy/website/pkg/models"
"code.nonshy.com/nonshy/website/pkg/models/deletion" "code.nonshy.com/nonshy/website/pkg/models/deletion"
"code.nonshy.com/nonshy/website/pkg/session" "code.nonshy.com/nonshy/website/pkg/session"
"code.nonshy.com/nonshy/website/pkg/templates" "code.nonshy.com/nonshy/website/pkg/templates"
@ -40,6 +42,9 @@ func Delete() http.HandlerFunc {
session.LogoutUser(w, r) session.LogoutUser(w, r)
session.Flash(w, r, "Your account has been deleted.") session.Flash(w, r, "Your account has been deleted.")
templates.Redirect(w, "/") templates.Redirect(w, "/")
// Log the change.
models.LogDeleted(nil, nil, "users", currentUser.ID, fmt.Sprintf("Username %s has deleted their account.", currentUser.Username), nil)
return return
} }

View File

@ -1,6 +1,7 @@
package admin package admin
import ( import (
"fmt"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
@ -155,6 +156,9 @@ func UserActions() http.HandlerFunc {
user.Save() user.Save()
session.Flash(w, r, "User ban status updated!") session.Flash(w, r, "User ban status updated!")
templates.Redirect(w, "/u/"+user.Username) templates.Redirect(w, "/u/"+user.Username)
// Log the change.
models.LogUpdated(user, currentUser, "users", currentUser.ID, fmt.Sprintf("User ban status updated to: %s", status), nil)
return return
} }
case "promote": case "promote":
@ -171,6 +175,9 @@ func UserActions() http.HandlerFunc {
user.Save() user.Save()
session.Flash(w, r, "User admin status updated!") session.Flash(w, r, "User admin status updated!")
templates.Redirect(w, "/u/"+user.Username) templates.Redirect(w, "/u/"+user.Username)
// Log the change.
models.LogUpdated(user, currentUser, "users", currentUser.ID, fmt.Sprintf("User admin status updated to: %s", action), nil)
return return
} }
case "delete": case "delete":
@ -188,6 +195,9 @@ func UserActions() http.HandlerFunc {
session.Flash(w, r, "User has been deleted!") session.Flash(w, r, "User has been deleted!")
} }
templates.Redirect(w, "/admin") templates.Redirect(w, "/admin")
// Log the change.
models.LogDeleted(nil, currentUser, "users", user.ID, fmt.Sprintf("Username %s has been deleted by an admin.", user.Username), nil)
return return
} }
default: default:

View File

@ -41,6 +41,7 @@ func DeleteUser(user *models.User) error {
{"Two Factor", DeleteTwoFactor}, {"Two Factor", DeleteTwoFactor},
{"Profile Fields", DeleteProfile}, {"Profile Fields", DeleteProfile},
{"User Notes", DeleteUserNotes}, {"User Notes", DeleteUserNotes},
{"Change Logs", DeleteChangeLogs},
} }
for _, item := range todo { for _, item := range todo {
if err := item.Fn(user.ID); err != nil { if err := item.Fn(user.ID); err != nil {
@ -327,3 +328,13 @@ func DeleteUserNotes(userID uint64) error {
).Delete(&models.UserNote{}) ).Delete(&models.UserNote{})
return result.Error return result.Error
} }
// DeleteChangeLogs scrubs data for deleting a user.
func DeleteChangeLogs(userID uint64) error {
log.Error("DeleteUser: DeleteChangeLogs(%d)", userID)
result := models.DB.Where(
"about_user_id = ?",
userID,
).Delete(&models.ChangeLog{})
return result.Error
}

View File

@ -40,6 +40,7 @@ func ExportModels(zw *zip.Writer, user *models.User) error {
// Note: AdminGroup info is eager-loaded in User export // Note: AdminGroup info is eager-loaded in User export
{"UserLocation", ExportUserLocationTable}, {"UserLocation", ExportUserLocationTable},
{"UserNote", ExportUserNoteTable}, {"UserNote", ExportUserNoteTable},
{"ChangeLog", ExportChangeLogTable},
{"TwoFactor", ExportTwoFactorTable}, {"TwoFactor", ExportTwoFactorTable},
} }
for _, item := range todo { for _, item := range todo {
@ -383,6 +384,21 @@ func ExportUserNoteTable(zw *zip.Writer, user *models.User) error {
return ZipJson(zw, "user_notes.json", items) return ZipJson(zw, "user_notes.json", items)
} }
func ExportChangeLogTable(zw *zip.Writer, user *models.User) error {
var (
items = []*models.ChangeLog{}
query = models.DB.Model(&models.ChangeLog{}).Where(
"about_user_id = ? OR admin_user_id = ?",
user.ID, user.ID,
).Find(&items)
)
if query.Error != nil {
return query.Error
}
return ZipJson(zw, "change_logs.json", items)
}
func ExportUserLocationTable(zw *zip.Writer, user *models.User) error { func ExportUserLocationTable(zw *zip.Writer, user *models.User) error {
var ( var (
items = []*models.UserLocation{} items = []*models.UserLocation{}