fix(api): mc_uuid 统一校验为 UUID,非法值返回 400 bad_mc_uuid 并按规范形式存储

This commit is contained in:
Lemon-miaow committed 2026-09-27 12:57:40 +08:00
1 parent 5b0686dc06
commit e91886822c
13 files changed
+159 -35

No files matched your search

+12 -8
View File
@@ -447,11 +447,15 @@ func (a *API) handleUnbindUserPasskeys(w http.ResponseWriter, r *http.Request) {
// (DELETE /users/{id}/links/{mc_uuid}).
func (a *API) handleUnlinkAccount(w http.ResponseWriter, r *http.Request) {
userID := r.PathValue("id")
mcUUID := r.PathValue("mc_uuid")
if userID == "" || mcUUID == "" {
if userID == "" {
writeError(w, r, errBadRequest)
return
}
mcUUID, err := parseMCUUID(r.PathValue("mc_uuid"))
if err != nil {
writeError(w, r, err)
return
}
if err := a.Repo.UnlinkAccount(r.Context(), userID, mcUUID); err != nil {
if errors.Is(err, ErrNotFound) {
@@ -484,16 +488,16 @@ func (a *API) handleLinkAccount(w http.ResponseWriter, r *http.Request) {
writeError(w, r, err)
return
}
if body.MCUUID == "" {
writeError(w, r, newError(http.StatusBadRequest, "bad_request",
"mc_uuid is required"))
mcUUID, err := parseMCUUID(body.MCUUID)
if err != nil {
writeError(w, r, err)
return
}
if body.AuthSource == "" {
// Same version-nibble inference as the mint path (handlers_account.go):
// defaulting to mojang here would leave a force-linked thirdparty UUID
// outside the reclaim guard.
body.AuthSource = deriveAuthSource(body.MCUUID)
body.AuthSource = deriveAuthSource(mcUUID)
}
if !validAuthSource(body.AuthSource) {
writeError(w, r, newError(http.StatusBadRequest, "bad_request",
@@ -501,7 +505,7 @@ func (a *API) handleLinkAccount(w http.ResponseWriter, r *http.Request) {
return
}
if err := a.Repo.LinkAccount(r.Context(), userID, body.MCUUID, body.AuthSource); err != nil {
if err := a.Repo.LinkAccount(r.Context(), userID, mcUUID, body.AuthSource); err != nil {
if errors.Is(err, ErrConflict) {
writeError(w, r, newError(http.StatusConflict, "already_linked",
"this UUID is already linked to a different user"))
@@ -518,7 +522,7 @@ func (a *API) handleLinkAccount(w http.ResponseWriter, r *http.Request) {
a.audit(r, "user.link_account", userID)
writeJSON(w, http.StatusOK, map[string]any{
"ok": true,
"mc_uuid": body.MCUUID,
"mc_uuid": mcUUID,
"auth_source": body.AuthSource,
})
}