Display Usersign metadata in admin dashboard

This commit is contained in:
techknowlogick committed 2025-03-20 19:52:31 -04:00
1 parent a4df01b580
commit 5d716fbe0b
8 files changed
+290 -2

No files matched your search

+164
View File
@@ -0,0 +1,164 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package admin
import (
"net/http"
"strings"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
tplIPs templates.TplName = "admin/ips/list"
)
// trimPortFromIP removes the client port from an IP address
// Handles both IPv4 and IPv6 addresses with ports
func trimPortFromIP(ip string) string {
// Handle IPv6 with brackets: [IPv6]:port
if strings.HasPrefix(ip, "[") {
// If there's no port, return as is
if !strings.Contains(ip, "]:") {
return ip
}
// Remove the port part after ]:
return strings.Split(ip, "]:")[0] + "]"
}
// Count colons to differentiate between IPv4 and IPv6
colonCount := strings.Count(ip, ":")
// Handle IPv4 with port (single colon)
if colonCount == 1 {
return strings.Split(ip, ":")[0]
}
return ip
}
// IPs show all user signup IPs
func IPs(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("admin.ips")
ctx.Data["PageIsAdminIPs"] = true
ctx.Data["RecordUserSignupMetadata"] = setting.RecordUserSignupMetadata
// If record user signup metadata is disabled, don't show the page
if !setting.RecordUserSignupMetadata {
ctx.Redirect(setting.AppSubURL + "/-/admin")
return
}
page := ctx.FormInt("page")
if page <= 1 {
page = 1
}
// Define the user IP result struct
type UserIPResult struct {
UID int64
Name string
FullName string
IP string
UserAgent string
}
var (
userIPs []UserIPResult
count int64
err error
orderBy string
keyword = ctx.FormTrim("q")
sortType = ctx.FormString("sort")
)
ctx.Data["SortType"] = sortType
switch sortType {
case "ip":
orderBy = "user_setting.setting_value ASC, user.id ASC"
case "reverseip":
orderBy = "user_setting.setting_value DESC, user.id DESC"
case "username":
orderBy = "user.lower_name ASC, user.id ASC"
case "reverseusername":
orderBy = "user.lower_name DESC, user.id DESC"
default:
ctx.Data["SortType"] = "ip"
sortType = "ip"
orderBy = "user_setting.setting_value ASC, user.id ASC"
}
// Get the count and user IPs for pagination
if len(keyword) == 0 {
// Simple count without keyword
count, err = db.GetEngine(ctx).
Join("INNER", "user", "user.id = user_setting.user_id").
Where("user_setting.setting_key = ?", user_model.SignupIP).
Count(new(user_model.Setting))
if err != nil {
ctx.ServerError("Count", err)
return
}
// Get the user IPs
err = db.GetEngine(ctx).
Table("user_setting").
Join("INNER", "user", "user.id = user_setting.user_id").
Where("user_setting.setting_key = ?", user_model.SignupIP).
Select("user.id as uid, user.name, user.full_name, user_setting.setting_value as ip, '' as user_agent").
OrderBy(orderBy).
Limit(setting.UI.Admin.UserPagingNum, (page-1)*setting.UI.Admin.UserPagingNum).
Find(&userIPs)
if err != nil {
ctx.ServerError("Find", err)
return
}
} else {
// Count with keyword filter
count, err = db.GetEngine(ctx).
Join("INNER", "user", "user.id = user_setting.user_id").
Where("user_setting.setting_key = ?", user_model.SignupIP).
And("(user.lower_name LIKE ? OR user.full_name LIKE ? OR user_setting.setting_value LIKE ?)",
"%"+strings.ToLower(keyword)+"%", "%"+keyword+"%", "%"+keyword+"%").
Count(new(user_model.Setting))
if err != nil {
ctx.ServerError("Count", err)
return
}
// Get the user IPs with keyword filter
err = db.GetEngine(ctx).
Table("user_setting").
Join("INNER", "user", "user.id = user_setting.user_id").
Where("user_setting.setting_key = ?", user_model.SignupIP).
And("(user.lower_name LIKE ? OR user.full_name LIKE ? OR user_setting.setting_value LIKE ?)",
"%"+strings.ToLower(keyword)+"%", "%"+keyword+"%", "%"+keyword+"%").
Select("user.id as uid, user.name, user.full_name, user_setting.setting_value as ip, '' as user_agent").
OrderBy(orderBy).
Limit(setting.UI.Admin.UserPagingNum, (page-1)*setting.UI.Admin.UserPagingNum).
Find(&userIPs)
if err != nil {
ctx.ServerError("Find", err)
return
}
}
for i := range userIPs {
// Trim the port from the IP
// FIXME: Maybe have a different helper for this?
userIPs[i].IP = trimPortFromIP(userIPs[i].IP)
}
ctx.Data["UserIPs"] = userIPs
ctx.Data["Total"] = count
ctx.Data["Keyword"] = keyword
// Setup pagination
ctx.Data["Page"] = context.NewPagination(int(count), setting.UI.Admin.UserPagingNum, page, 5)
ctx.HTML(http.StatusOK, tplIPs)
}
+20
View File
@@ -263,6 +263,7 @@ func ViewUser(ctx *context.Context) {
ctx.Data["DisableRegularOrgCreation"] = setting.Admin.DisableRegularOrgCreation
ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
ctx.Data["ShowUserSignupMetadata"] = setting.RecordUserSignupMetadata
u := prepareUserInfo(ctx)
if ctx.Written() {
@@ -292,6 +293,25 @@ func ViewUser(ctx *context.Context) {
ctx.Data["Emails"] = emails
ctx.Data["EmailsTotal"] = len(emails)
// If record user signup metadata is enabled, get the user's signup IP and user agent
if setting.RecordUserSignupMetadata {
signupIP, err := user_model.GetUserSetting(ctx, u.ID, user_model.SignupIP)
if err == nil && len(signupIP) > 0 {
ctx.Data["HasSignupIP"] = true
ctx.Data["SignupIP"] = trimPortFromIP(signupIP)
} else {
ctx.Data["HasSignupIP"] = false
}
signupUserAgent, err := user_model.GetUserSetting(ctx, u.ID, user_model.SignupUserAgent)
if err == nil && len(signupUserAgent) > 0 {
ctx.Data["HasSignupUserAgent"] = true
ctx.Data["SignupUserAgent"] = signupUserAgent
} else {
ctx.Data["HasSignupUserAgent"] = false
}
}
orgs, err := db.Find[org_model.Organization](ctx, org_model.FindOrgOptions{
ListOptions: db.ListOptionsAll,
UserID: u.ID,
+5 -1
View File
@@ -757,6 +757,10 @@ func registerRoutes(m *web.Router) {
m.Post("/delete", admin.DeleteEmail)
})
m.Group("/ips", func() {
m.Get("", admin.IPs)
})
m.Group("/orgs", func() {
m.Get("", admin.Organizations)
})
@@ -816,7 +820,7 @@ func registerRoutes(m *web.Router) {
addSettingsRunnersRoutes()
addSettingsVariablesRoutes()
})
}, adminReq, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled))
}, adminReq, ctxDataSet("RecordUserSignupMetadata", setting.RecordUserSignupMetadata, "EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled))
// ***** END: Admin *****
m.Group("", func() {