mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-03-21 17:44:58 -05:00
Include User object with responses to some APIs
This commit is contained in:
parent
90f38dccca
commit
c099348636
44
api/ban.go
44
api/ban.go
|
|
@ -11,26 +11,32 @@ import (
|
|||
)
|
||||
|
||||
func HandleBan(w http.ResponseWriter, r *http.Request) {
|
||||
var jsonData map[string]string
|
||||
var user *database.User
|
||||
var success bool
|
||||
var err string
|
||||
var statusCode int
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodHead:
|
||||
statusCode = http.StatusOK
|
||||
case http.MethodPost:
|
||||
jsonData, statusCode = handleBanImpl(w, r)
|
||||
user, success, err, statusCode = handleBanImpl(w, r)
|
||||
default:
|
||||
jsonData = mmss("error", "Incorrect request. POST or HEAD only.")
|
||||
err = "Incorrect request. POST or HEAD only."
|
||||
statusCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
user = &database.User{}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
if len(jsonData) == 0 {
|
||||
if r.Method == http.MethodHead {
|
||||
w.WriteHeader(statusCode)
|
||||
} else {
|
||||
json, _ := json.Marshal(jsonData)
|
||||
json, _ := json.Marshal(UserActionResponse{*user, success, err})
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(json)))
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(json)
|
||||
|
|
@ -49,30 +55,30 @@ type BanRequestSpec struct {
|
|||
Moderator string
|
||||
}
|
||||
|
||||
func handleBanImpl(w http.ResponseWriter, r *http.Request) (map[string]string, int) {
|
||||
func handleBanImpl(w http.ResponseWriter, r *http.Request) (*database.User, bool, string, int) {
|
||||
// TODO: Actual authentication rather than a fixed secret
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return mmss("error", "Unable to read request body"), http.StatusBadRequest
|
||||
return nil, false, "Unable to read request body", http.StatusBadRequest
|
||||
}
|
||||
|
||||
var req BanRequestSpec
|
||||
err = json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
return mmss("error", err.Error()), http.StatusBadRequest
|
||||
return nil, false, err.Error(), http.StatusBadRequest
|
||||
}
|
||||
|
||||
if apiSecret == "" || req.Secret != apiSecret {
|
||||
return mmss("error", "Invalid API secret in request"), http.StatusUnauthorized
|
||||
return nil, false, "Invalid API secret in request", http.StatusUnauthorized
|
||||
}
|
||||
|
||||
if req.Pid == 0 {
|
||||
return mmss("error", "pid missing or 0 in request"), http.StatusBadRequest
|
||||
return nil, false, "pid missing or 0 in request", http.StatusBadRequest
|
||||
}
|
||||
|
||||
if req.Reason == "" {
|
||||
return mmss("error", "Missing ban reason in request"), http.StatusBadRequest
|
||||
return nil, false, "Missing ban reason in request", http.StatusBadRequest
|
||||
}
|
||||
|
||||
moderator := req.Moderator
|
||||
|
|
@ -82,13 +88,13 @@ func handleBanImpl(w http.ResponseWriter, r *http.Request) (map[string]string, i
|
|||
|
||||
minutes := req.Days*24*60 + req.Hours*60 + req.Minutes
|
||||
if minutes == 0 {
|
||||
return mmss("error", "Ban length missing or 0"), http.StatusBadRequest
|
||||
return nil, false, "Ban length missing or 0", http.StatusBadRequest
|
||||
}
|
||||
|
||||
length := time.Duration(minutes) * time.Minute
|
||||
|
||||
if !database.BanUser(pool, ctx, req.Pid, req.Tos, length, req.Reason, req.ReasonHidden, moderator) {
|
||||
return mmss("error", "Failed to ban user"), http.StatusInternalServerError
|
||||
return nil, false, "Failed to ban user", http.StatusInternalServerError
|
||||
}
|
||||
|
||||
if req.Tos {
|
||||
|
|
@ -97,6 +103,14 @@ func handleBanImpl(w http.ResponseWriter, r *http.Request) (map[string]string, i
|
|||
gpcm.KickPlayer(req.Pid, "restricted")
|
||||
}
|
||||
|
||||
ip := database.GetUserIP(pool, ctx, req.Pid)
|
||||
return mmss("result", "success", "ip", ip), http.StatusOK
|
||||
var message string
|
||||
user, success := database.GetProfile(pool, ctx, req.Pid)
|
||||
|
||||
if success {
|
||||
message = ""
|
||||
} else {
|
||||
message = "Unable to query user data from the database"
|
||||
}
|
||||
|
||||
return &user, success, message, http.StatusOK
|
||||
}
|
||||
|
|
|
|||
38
api/kick.go
38
api/kick.go
|
|
@ -10,26 +10,32 @@ import (
|
|||
)
|
||||
|
||||
func HandleKick(w http.ResponseWriter, r *http.Request) {
|
||||
var jsonData map[string]string
|
||||
var user *database.User
|
||||
var success bool
|
||||
var err string
|
||||
var statusCode int
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodHead:
|
||||
statusCode = http.StatusOK
|
||||
case http.MethodPost:
|
||||
jsonData, statusCode = handleKickImpl(w, r)
|
||||
user, success, err, statusCode = handleKickImpl(w, r)
|
||||
default:
|
||||
jsonData = mmss("error", "Incorrect request. POST or HEAD only.")
|
||||
err = "Incorrect request. POST or HEAD only."
|
||||
statusCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
user = &database.User{}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
if len(jsonData) == 0 {
|
||||
if r.Method == http.MethodHead {
|
||||
w.WriteHeader(statusCode)
|
||||
} else {
|
||||
json, _ := json.Marshal(jsonData)
|
||||
json, _ := json.Marshal(UserActionResponse{*user, success, err})
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(json)))
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(json)
|
||||
|
|
@ -41,30 +47,38 @@ type KickRequestSpec struct {
|
|||
Pid uint32
|
||||
}
|
||||
|
||||
func handleKickImpl(w http.ResponseWriter, r *http.Request) (map[string]string, int) {
|
||||
func handleKickImpl(w http.ResponseWriter, r *http.Request) (*database.User, bool, string, int) {
|
||||
// TODO: Actual authentication rather than a fixed secret
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return mmss("error", "Unable to read request body"), http.StatusBadRequest
|
||||
return nil, false, "Unable to read request body", http.StatusBadRequest
|
||||
}
|
||||
|
||||
var req KickRequestSpec
|
||||
err = json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
return mmss("error", err.Error()), http.StatusBadRequest
|
||||
return nil, false, err.Error(), http.StatusBadRequest
|
||||
}
|
||||
|
||||
if apiSecret == "" || req.Secret != apiSecret {
|
||||
return mmss("error", "Invalid API secret in request"), http.StatusUnauthorized
|
||||
return nil, false, "Invalid API secret in request", http.StatusUnauthorized
|
||||
}
|
||||
|
||||
if req.Pid == 0 {
|
||||
return mmss("error", "pid missing or 0 in request"), http.StatusBadRequest
|
||||
return nil, false, "pid missing or 0 in request", http.StatusBadRequest
|
||||
}
|
||||
|
||||
gpcm.KickPlayer(req.Pid, "moderator_kick")
|
||||
|
||||
ip := database.GetUserIP(pool, ctx, req.Pid)
|
||||
return mmss("status", "success", "ip", ip), http.StatusOK
|
||||
var message string
|
||||
user, success := database.GetProfile(pool, ctx, req.Pid)
|
||||
|
||||
if success {
|
||||
message = ""
|
||||
} else {
|
||||
message = "Unable to query user data from the database"
|
||||
}
|
||||
|
||||
return &user, success, message, http.StatusOK
|
||||
}
|
||||
|
|
|
|||
39
api/motd.go
39
api/motd.go
|
|
@ -9,36 +9,39 @@ import (
|
|||
)
|
||||
|
||||
func HandleMotd(w http.ResponseWriter, r *http.Request) {
|
||||
var jsonData map[string]string
|
||||
var motd string
|
||||
var success bool
|
||||
var err string
|
||||
var statusCode int
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodHead:
|
||||
statusCode = http.StatusOK
|
||||
case http.MethodGet:
|
||||
motd, err := gpcm.GetMessageOfTheDay()
|
||||
if err != nil {
|
||||
jsonData = mmss("error", err.Error())
|
||||
_motd, motdErr := gpcm.GetMessageOfTheDay()
|
||||
if motdErr != nil {
|
||||
err = motdErr.Error()
|
||||
statusCode = http.StatusInternalServerError
|
||||
break
|
||||
}
|
||||
|
||||
jsonData = mmss("motd", motd)
|
||||
motd = _motd
|
||||
success = true
|
||||
statusCode = http.StatusOK
|
||||
case http.MethodPost:
|
||||
jsonData, statusCode = handleMotdImpl(w, r)
|
||||
success, err, statusCode = handleMotdImpl(w, r)
|
||||
default:
|
||||
jsonData = mmss("error", "Incorrect request. POST, GET, or HEAD only.")
|
||||
err = "Incorrect request. POST, GET, or HEAD only."
|
||||
statusCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
if len(jsonData) == 0 {
|
||||
if r.Method == http.MethodHead {
|
||||
w.WriteHeader(statusCode)
|
||||
} else {
|
||||
json, _ := json.Marshal(jsonData)
|
||||
json, _ := json.Marshal(MotdResponse{motd, success, err})
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(json)))
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(json)
|
||||
|
|
@ -50,29 +53,35 @@ type MotdRequestSpec struct {
|
|||
Motd string
|
||||
}
|
||||
|
||||
func handleMotdImpl(w http.ResponseWriter, r *http.Request) (map[string]string, int) {
|
||||
type MotdResponse struct {
|
||||
Motd string
|
||||
Success bool
|
||||
Error string
|
||||
}
|
||||
|
||||
func handleMotdImpl(w http.ResponseWriter, r *http.Request) (bool, string, int) {
|
||||
// TODO: Actual authentication rather than a fixed secret
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return mmss("error", "Unable to read request body"), http.StatusBadRequest
|
||||
return false, "Unable to read request body", http.StatusBadRequest
|
||||
}
|
||||
|
||||
var req MotdRequestSpec
|
||||
err = json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
return mmss("error", err.Error()), http.StatusBadRequest
|
||||
return false, err.Error(), http.StatusBadRequest
|
||||
}
|
||||
|
||||
if apiSecret == "" || req.Secret != apiSecret {
|
||||
return mmss("error", "Invalid API secret in request"), http.StatusUnauthorized
|
||||
return false, "Invalid API secret in request", http.StatusUnauthorized
|
||||
}
|
||||
|
||||
err = gpcm.SetMessageOfTheDay(req.Motd)
|
||||
if err != nil {
|
||||
return mmss("error", err.Error()), http.StatusInternalServerError
|
||||
return false, err.Error(), http.StatusInternalServerError
|
||||
}
|
||||
|
||||
// Don't return empty JSON, this is placeholder for now.
|
||||
return mmss("result", "success"), http.StatusOK
|
||||
return true, "", http.StatusOK
|
||||
}
|
||||
|
|
|
|||
40
api/unban.go
40
api/unban.go
|
|
@ -9,26 +9,32 @@ import (
|
|||
)
|
||||
|
||||
func HandleUnban(w http.ResponseWriter, r *http.Request) {
|
||||
var jsonData map[string]string
|
||||
var user *database.User
|
||||
var success bool
|
||||
var err string
|
||||
var statusCode int
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodHead:
|
||||
statusCode = http.StatusOK
|
||||
case http.MethodPost:
|
||||
jsonData, statusCode = handleUnbanImpl(w, r)
|
||||
user, success, err, statusCode = handleUnbanImpl(w, r)
|
||||
default:
|
||||
jsonData = mmss("error", "Incorrect request. POST or HEAD only.")
|
||||
err = "Incorrect request. POST or HEAD only."
|
||||
statusCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
user = &database.User{}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
if len(jsonData) == 0 {
|
||||
if r.Method == http.MethodHead {
|
||||
w.WriteHeader(statusCode)
|
||||
} else {
|
||||
json, _ := json.Marshal(jsonData)
|
||||
json, _ := json.Marshal(UserActionResponse{*user, success, err})
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(json)))
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(json)
|
||||
|
|
@ -40,32 +46,40 @@ type UnbanRequestSpec struct {
|
|||
Pid uint32
|
||||
}
|
||||
|
||||
func handleUnbanImpl(w http.ResponseWriter, r *http.Request) (map[string]string, int) {
|
||||
func handleUnbanImpl(w http.ResponseWriter, r *http.Request) (*database.User, bool, string, int) {
|
||||
// TODO: Actual authentication rather than a fixed secret
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return mmss("error", "Unable to read request body"), http.StatusBadRequest
|
||||
return nil, false, "Unable to read request body", http.StatusBadRequest
|
||||
}
|
||||
|
||||
var req UnbanRequestSpec
|
||||
err = json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
return mmss("error", err.Error()), http.StatusBadRequest
|
||||
return nil, false, err.Error(), http.StatusBadRequest
|
||||
}
|
||||
|
||||
if apiSecret == "" || req.Secret != apiSecret {
|
||||
return mmss("error", "Invalid API secret in request"), http.StatusUnauthorized
|
||||
return nil, false, "Invalid API secret in request", http.StatusUnauthorized
|
||||
}
|
||||
|
||||
if req.Pid == 0 {
|
||||
return mmss("error", "pid missing or 0 in request"), http.StatusBadRequest
|
||||
return nil, false, "pid missing or 0 in request", http.StatusBadRequest
|
||||
}
|
||||
|
||||
if !database.UnbanUser(pool, ctx, req.Pid) {
|
||||
return mmss("error", "Failed to unban user"), http.StatusInternalServerError
|
||||
return nil, false, "Failed to unban user", http.StatusInternalServerError
|
||||
}
|
||||
|
||||
ip := database.GetUserIP(pool, ctx, req.Pid)
|
||||
return mmss("result", "success", "ip", ip), http.StatusOK
|
||||
var message string
|
||||
user, success := database.GetProfile(pool, ctx, req.Pid)
|
||||
|
||||
if success {
|
||||
message = ""
|
||||
} else {
|
||||
message = "Unable to query user data from the database"
|
||||
}
|
||||
|
||||
return &user, success, message, http.StatusOK
|
||||
}
|
||||
|
|
|
|||
21
api/utils.go
21
api/utils.go
|
|
@ -1,18 +1,11 @@
|
|||
package api
|
||||
|
||||
// make map string string
|
||||
func mmss(data ...string) map[string]string {
|
||||
ret := make(map[string]string)
|
||||
import (
|
||||
"wwfc/database"
|
||||
)
|
||||
|
||||
l := len(data)
|
||||
|
||||
if l%2 != 0 || l == 0 {
|
||||
panic("Length of data must be divisible by two")
|
||||
}
|
||||
|
||||
for i := 0; i < l; i += 2 {
|
||||
ret[data[i]] = data[i+1]
|
||||
}
|
||||
|
||||
return ret
|
||||
type UserActionResponse struct {
|
||||
User database.User
|
||||
Success bool
|
||||
Error string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ const (
|
|||
UpdateUserTable = `UPDATE users SET firstname = CASE WHEN $3 THEN $2 ELSE firstname END, lastname = CASE WHEN $5 THEN $4 ELSE lastname END, open_host = CASE WHEN $7 THEN $6 ELSE open_host END WHERE profile_id = $1`
|
||||
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`
|
||||
GetUser = `SELECT user_id, gsbrcd, email, unique_nick, firstname, lastname, open_host FROM users WHERE profile_id = $1`
|
||||
GetUserLastIPAddress = `SELECT last_ip_address FROM users WHERE profile_id = $1`
|
||||
GetUser = `SELECT user_id, gsbrcd, email, unique_nick, firstname, lastname, open_host, last_ip_address, last_ingamesn FROM users WHERE profile_id = $1`
|
||||
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)`
|
||||
DeleteUserSession = `DELETE FROM sessions WHERE profile_id = $1`
|
||||
|
|
@ -41,6 +40,8 @@ type User struct {
|
|||
Restricted bool
|
||||
RestrictedDeviceId uint32
|
||||
OpenHost bool
|
||||
LastInGameSn string
|
||||
LastIPAddress string
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -129,7 +130,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) {
|
||||
user := User{}
|
||||
row := pool.QueryRow(ctx, GetUser, profileId)
|
||||
err := row.Scan(&user.UserId, &user.GsbrCode, &user.Email, &user.UniqueNick, &user.FirstName, &user.LastName, &user.OpenHost)
|
||||
err := row.Scan(&user.UserId, &user.GsbrCode, &user.Email, &user.UniqueNick, &user.FirstName, &user.LastName, &user.OpenHost, &user.LastIPAddress, &user.LastInGameSn)
|
||||
if err != nil {
|
||||
return User{}, false
|
||||
}
|
||||
|
|
@ -148,16 +149,6 @@ func UnbanUser(pool *pgxpool.Pool, ctx context.Context, profileId uint32) bool {
|
|||
return err == nil
|
||||
}
|
||||
|
||||
func GetUserIP(pool *pgxpool.Pool, ctx context.Context, profileId uint32) string {
|
||||
var ip string
|
||||
err := pool.QueryRow(ctx, GetUserLastIPAddress, profileId).Scan(&ip)
|
||||
if err != nil {
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
return ip
|
||||
}
|
||||
|
||||
func GetMKWFriendInfo(pool *pgxpool.Pool, ctx context.Context, profileId uint32) string {
|
||||
var info string
|
||||
err := pool.QueryRow(ctx, GetMKWFriendInfoQuery, profileId).Scan(&info)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user