API: Reformat API error responses
Some checks failed
Build CI / build (push) Has been cancelled
golangci-lint / lint (push) Has been cancelled

This commit is contained in:
Palapeli 2026-04-24 12:15:57 -04:00
parent 51610cb3b7
commit b70c693d26
No known key found for this signature in database
GPG Key ID: 1FFE8F556A474925
6 changed files with 38 additions and 22 deletions

View File

@ -34,7 +34,7 @@ func HandleBan(w http.ResponseWriter, r *http.Request) {
}
if req.Reason == "" {
replyError(w, http.StatusBadRequest, APIErrorInvalidBanReason)
replyError(w, http.StatusBadRequest, APIErrorInvalidReason)
return
}
@ -51,8 +51,6 @@ func HandleBan(w http.ResponseWriter, r *http.Request) {
length := time.Duration(minutes) * time.Minute
logging.Notice("API:"+moderator, "Ban profile:", aurora.Cyan(req.ProfileID), "TOS:", aurora.Cyan(req.Tos), "Length:", aurora.Cyan(length), "Reason:", aurora.BrightCyan(req.Reason), "Reason (Hidden):", aurora.BrightCyan(req.ReasonHidden))
if !db.BanUser(req.ProfileID, req.Tos, length, req.Reason, req.ReasonHidden, moderator) {
replyError(w, http.StatusInternalServerError, APIErrorBanFailed)
return
@ -70,4 +68,6 @@ func HandleBan(w http.ResponseWriter, r *http.Request) {
"reason_hidden": req.ReasonHidden,
"moderator": moderator,
})
logging.Notice("API:"+moderator, "Ban:", aurora.Cyan(req.ProfileID), "TOS:", aurora.Cyan(req.Tos), "Length:", aurora.Cyan(length), "Reason:", aurora.BrightCyan(req.Reason), "Reason (Hidden):", aurora.BrightCyan(req.ReasonHidden))
}

View File

@ -26,7 +26,7 @@ func HandleBanInfo(w http.ResponseWriter, r *http.Request) {
search := query.Get("q")
if search == "" {
replyError(w, http.StatusBadRequest, APIErrorInvalidBanQuery)
replyError(w, http.StatusBadRequest, APIErrorInvalidQuery)
return
}
@ -37,14 +37,14 @@ func HandleBanInfo(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(search, "NG") {
ngId, err := strconv.ParseUint(search[2:], 16, 32)
if err != nil {
replyError(w, http.StatusBadRequest, APIErrorInvalidBanQuery)
replyError(w, http.StatusBadRequest, APIErrorInvalidQuery)
return
}
ngDeviceId = uint32(ngId)
} else {
pId, err := strconv.ParseUint(search, 10, 64)
if err != nil {
replyError(w, http.StatusBadRequest, APIErrorInvalidBanQuery)
replyError(w, http.StatusBadRequest, APIErrorInvalidQuery)
return
}
// Truncate to 32 bits as that's how friend codes work

View File

@ -14,6 +14,7 @@ func HandleGroups(w http.ResponseWriter, r *http.Request) {
groups := qr2.GetGroups(query["game"], query["id"], true)
if len(groups) == 0 {
// I would return No Content, but here is compatibility
replyOK(w, "[]")
return
}

View File

@ -4,6 +4,8 @@ import (
"net/http"
"wwfc/gpcm"
"wwfc/logging"
"github.com/logrusorgru/aurora/v3"
)
type KickRequestSpec struct {
@ -24,7 +26,7 @@ func HandleKick(w http.ResponseWriter, r *http.Request) {
}
if req.Reason == "" {
replyError(w, http.StatusBadRequest, APIErrorInvalidBanReason)
replyError(w, http.StatusBadRequest, APIErrorInvalidReason)
return
}
@ -36,4 +38,6 @@ func HandleKick(w http.ResponseWriter, r *http.Request) {
"profile_id": req.ProfileID,
"reason": req.Reason,
})
logging.Notice("API:admin", "Kick:", aurora.Cyan(req.ProfileID), "Reason:", aurora.BrightCyan(req.Reason))
}

View File

@ -3,6 +3,8 @@ package api
import (
"net/http"
"wwfc/logging"
"github.com/logrusorgru/aurora/v3"
)
type UnbanRequestSpec struct {
@ -31,4 +33,6 @@ func HandleUnban(w http.ResponseWriter, r *http.Request) {
logging.Event("profile_unbanned", map[string]any{
"profile_id": req.ProfileID,
})
logging.Notice("API:admin", "Unban:", aurora.Cyan(req.ProfileID))
}

View File

@ -13,15 +13,14 @@ import (
type APIErrorString string
const (
APIErrorAuthenticationFailed APIErrorString = "AuthenticationFailed"
APIErrorInvalidQuery APIErrorString = "InvalidQuery"
APIErrorInvalidProfileID APIErrorString = "InvalidProfileID"
APIErrorInvalidBanReason APIErrorString = "InvalidBanReason"
APIErrorInvalidBanLength APIErrorString = "InvalidBanLength"
APIErrorBanFailed APIErrorString = "BanFailed"
APIErrorUnbanFailed APIErrorString = "UnbanFailed"
APIErrorInvalidBanQuery APIErrorString = "InvalidBanQuery"
APIErrorBanNotFound APIErrorString = "BanNotFound"
APIErrorFailedAuthentication APIErrorString = "failed_authentication"
APIErrorInvalidQuery APIErrorString = "invalid_query"
APIErrorInvalidProfileID APIErrorString = "invalid_profile_id"
APIErrorInvalidReason APIErrorString = "invalid_reason"
APIErrorInvalidBanLength APIErrorString = "invalid_ban_length"
APIErrorBanFailed APIErrorString = "ban_failed"
APIErrorUnbanFailed APIErrorString = "unban_failed"
APIErrorBanNotFound APIErrorString = "ban_not_found"
)
type APIError struct {
@ -80,7 +79,7 @@ func parseGet(r *http.Request, w http.ResponseWriter, requiredRole Role) (query
authInfo := makeAuthInfo(query)
if !authenticate(authInfo, requiredRole) {
replyError(w, http.StatusUnauthorized, APIErrorAuthenticationFailed)
replyError(w, http.StatusUnauthorized, APIErrorFailedAuthentication)
return nil, errAuthFailed
}
return query, nil
@ -127,7 +126,7 @@ func parsePost(r *http.Request, w http.ResponseWriter, parsed any, requiredRole
return errNoAuthInfo
}
if !authenticate(authInfo, requiredRole) {
replyError(w, http.StatusUnauthorized, APIErrorAuthenticationFailed)
replyError(w, http.StatusUnauthorized, APIErrorFailedAuthentication)
return errAuthFailed
}
return nil
@ -159,11 +158,19 @@ func replyOK(w http.ResponseWriter, data any) {
}
w.Header().Set("Content-Type", "application/json")
jsonData, err := json.Marshal(data)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
var jsonData []byte
if reflect.ValueOf(data).Kind() == reflect.String {
// Assume it's already JSON
jsonData = []byte(data.(string))
} else {
var err error
jsonData, err = json.Marshal(data)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
}
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
_, _ = w.Write(jsonData)
}