From 6dc33d610bdc7cc7da22041362fd2b08870ee6e6 Mon Sep 17 00:00:00 2001 From: ppeb Date: Sun, 20 Apr 2025 14:43:37 -0500 Subject: [PATCH] Return additional info in authenticated pinfo requests Real psql error messages will be sent (ephemeral bot side, so no user info can leak that mods cannot already leak) Hidden ban reason will be sent --- api/ban.go | 4 ++-- api/kick.go | 4 ++-- api/pinfo.go | 21 +++++++++++++++------ api/unban.go | 4 ++-- database/user.go | 24 +++++++++++++++--------- gpcm/profile.go | 4 ++-- 6 files changed, 38 insertions(+), 23 deletions(-) diff --git a/api/ban.go b/api/ban.go index 4263a6e..9a4c077 100644 --- a/api/ban.go +++ b/api/ban.go @@ -106,9 +106,9 @@ func handleBanImpl(r *http.Request) (*database.User, int, error) { gpcm.KickPlayerCustomMessage(req.ProfileID, req.Reason, gpcm.WWFCMsgProfileRestrictedCustom) - user, success := database.GetProfile(pool, ctx, req.ProfileID) + user, err := database.GetProfile(pool, ctx, req.ProfileID) - if !success { + if err != nil { return nil, http.StatusInternalServerError, ErrUserQueryTransaction } diff --git a/api/kick.go b/api/kick.go index cf64fc8..e73a6da 100644 --- a/api/kick.go +++ b/api/kick.go @@ -78,9 +78,9 @@ func handleKickImpl(r *http.Request) (*database.User, int, error) { gpcm.KickPlayerCustomMessage(req.ProfileID, req.Reason, gpcm.WWFCMsgKickedCustom) - user, success := database.GetProfile(pool, ctx, req.ProfileID) + user, err := database.GetProfile(pool, ctx, req.ProfileID) - if !success { + if err != nil { return nil, http.StatusInternalServerError, ErrUserQueryTransaction } diff --git a/api/pinfo.go b/api/pinfo.go index 4794eb3..08eab0c 100644 --- a/api/pinfo.go +++ b/api/pinfo.go @@ -63,14 +63,23 @@ func handlePinfoImpl(r *http.Request) (*database.User, int, error) { return nil, http.StatusBadRequest, ErrRequestBody } - realUser, success := database.GetProfile(pool, ctx, req.ProfileID) - var ret *database.User - - if !success { - return &database.User{}, http.StatusInternalServerError, ErrUserQuery + goodSecret := false + if apiSecret != "" && req.Secret == apiSecret { + goodSecret = true } - if apiSecret == "" || req.Secret != apiSecret { + realUser, err := database.GetProfile(pool, ctx, req.ProfileID) + var ret *database.User + + if err != nil { + if !goodSecret { + err = ErrUserQuery + } + + return &database.User{}, http.StatusInternalServerError, err + } + + if !goodSecret { // Invalid secret, only report normal user info ret = &database.User{ ProfileId: realUser.ProfileId, diff --git a/api/unban.go b/api/unban.go index 622580f..bdb93b1 100644 --- a/api/unban.go +++ b/api/unban.go @@ -74,9 +74,9 @@ func handleUnbanImpl(r *http.Request) (*database.User, int, error) { return nil, http.StatusInternalServerError, ErrTransaction } - user, success := database.GetProfile(pool, ctx, req.ProfileID) + user, err := database.GetProfile(pool, ctx, req.ProfileID) - if !success { + if err != nil { return nil, http.StatusInternalServerError, ErrUserQueryTransaction } diff --git a/database/user.go b/database/user.go index aaa2a72..0f31376 100644 --- a/database/user.go +++ b/database/user.go @@ -16,7 +16,7 @@ const ( UpdateUserProfileID = `UPDATE users SET profile_id = $3 WHERE user_id = $1 AND gsbrcd = $2` UpdateUserNGDeviceID = `UPDATE users SET ng_device_id = $2 WHERE profile_id = $1` UpdateUserCsnum = `UPDATE users SET csnum = $2 WHERE profile_id = $1` - GetUser = `SELECT user_id, gsbrcd, ng_device_id, email, unique_nick, firstname, lastname, has_ban, ban_reason, open_host, last_ingamesn, last_ip_address, csnum, ban_moderator, ban_issued, ban_expires FROM users WHERE profile_id = $1` + GetUser = `SELECT user_id, gsbrcd, ng_device_id, email, unique_nick, firstname, lastname, has_ban, ban_reason, open_host, last_ingamesn, last_ip_address, csnum, ban_moderator, ban_reason_hidden, ban_issued, ban_expires FROM users WHERE profile_id = $1` ClearProfileQuery = `DELETE FROM users WHERE profile_id = $1 RETURNING user_id, gsbrcd, email, unique_nick, firstname, lastname, open_host, last_ip_address, last_ingamesn, csnum` DoesUserExist = `SELECT EXISTS(SELECT 1 FROM users WHERE user_id = $1 AND gsbrcd = $2)` IsProfileIDInUse = `SELECT EXISTS(SELECT 1 FROM users WHERE profile_id = $1)` @@ -46,10 +46,11 @@ type User struct { LastInGameSn string LastIPAddress string Csnum []string - // Two fields only used in GetUser query - BanModerator string - BanIssued *time.Time - BanExpires *time.Time + // Following fields only used in GetUser query + BanModerator string + BanReasonHidden string + BanIssued *time.Time + BanExpires *time.Time } var ( @@ -135,7 +136,7 @@ func (user *User) UpdateProfile(pool *pgxpool.Pool, ctx context.Context, data ma } } -func GetProfile(pool *pgxpool.Pool, ctx context.Context, profileId uint32) (User, bool) { +func GetProfile(pool *pgxpool.Pool, ctx context.Context, profileId uint32) (User, error) { user := User{} row := pool.QueryRow(ctx, GetUser, profileId) @@ -146,11 +147,12 @@ func GetProfile(pool *pgxpool.Pool, ctx context.Context, profileId uint32) (User var lastInGameSn *string var lastIPAddress *string var banModerator *string + var banHiddenReason *string - err := row.Scan(&user.UserId, &user.GsbrCode, &user.NgDeviceId, &user.Email, &user.UniqueNick, &firstName, &lastName, &user.Restricted, &banReason, &user.OpenHost, &lastInGameSn, &lastIPAddress, &user.Csnum, &banModerator, &user.BanIssued, &user.BanExpires) + err := row.Scan(&user.UserId, &user.GsbrCode, &user.NgDeviceId, &user.Email, &user.UniqueNick, &firstName, &lastName, &user.Restricted, &banReason, &user.OpenHost, &lastInGameSn, &lastIPAddress, &user.Csnum, &banModerator, &banHiddenReason, &user.BanIssued, &user.BanExpires) if err != nil { - return User{}, false + return User{}, err } user.ProfileId = profileId @@ -179,7 +181,11 @@ func GetProfile(pool *pgxpool.Pool, ctx context.Context, profileId uint32) (User user.BanModerator = *banModerator } - return user, true + if banHiddenReason != nil { + user.BanReasonHidden = *banHiddenReason + } + + return user, nil } func ClearProfile(pool *pgxpool.Pool, ctx context.Context, profileId uint32) (User, bool) { diff --git a/gpcm/profile.go b/gpcm/profile.go index fd71b6c..a8b2f0f 100644 --- a/gpcm/profile.go +++ b/gpcm/profile.go @@ -31,8 +31,8 @@ func (g *GameSpySession) getProfile(command common.GameSpyCommand) { mutex.Unlock() } else { mutex.Unlock() - user, ok = database.GetProfile(pool, ctx, uint32(profileId)) - if !ok { + user, err = database.GetProfile(pool, ctx, uint32(profileId)) + if err != nil { // The profile info was requested on is invalid. g.replyError(ErrGetProfileBadProfile) return