fix(server): accept nil user_id placeholder in push; use received_at for leaderboard (#73, #74)
Build and Deploy / build-and-push (push) Successful in 3m37s
Build and Deploy / build-and-push (push) Successful in 3m37s
- sync.rs: replace Uuid::nil() placeholder with the authenticated user's real UUID before the mismatch check so desktop client pushes no longer fail with 400 user_id mismatch (#73) - replays.rs: use server-computed received_at instead of client-supplied header.recorded_at when updating leaderboard recorded_at to prevent timestamp spoofing (#74) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
use axum::{Json, extract::State};
|
||||
use chrono::Utc;
|
||||
use sqlx::SqlitePool;
|
||||
use uuid::Uuid;
|
||||
|
||||
use solitaire_sync::{
|
||||
AchievementRecord, PlayerProgress, StatsSnapshot, SyncPayload, SyncResponse, merge,
|
||||
@@ -142,10 +143,19 @@ pub async fn pull(
|
||||
pub async fn push(
|
||||
State(state): State<AppState>,
|
||||
user: AuthenticatedUser,
|
||||
Json(client_payload): Json<SyncPayload>,
|
||||
Json(mut client_payload): Json<SyncPayload>,
|
||||
) -> Result<Json<SyncResponse>, AppError> {
|
||||
// Reject payloads that claim to belong to a different user.
|
||||
if client_payload.user_id.to_string() != user.user_id {
|
||||
let user_uuid: Uuid = user
|
||||
.user_id
|
||||
.parse()
|
||||
.map_err(|_| AppError::Internal("invalid user_id UUID in JWT".into()))?;
|
||||
|
||||
// The desktop client always sends Uuid::nil() as a placeholder for the
|
||||
// authenticated user's real ID (see build_payload docstring). Replace it
|
||||
// here. Reject payloads that explicitly claim a different user's identity.
|
||||
if client_payload.user_id == Uuid::nil() {
|
||||
client_payload.user_id = user_uuid;
|
||||
} else if client_payload.user_id != user_uuid {
|
||||
return Err(AppError::BadRequest("user_id mismatch".into()));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user