simple-web-app

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 6e662c2483db46baaf7efc68281004e97253dee7
parent 484d607180858889f907c6efdf08cb7b08714283
Author: Silas Brack <silasbrack@gmail.com>
Date:   Sun,  7 Jun 2026 17:58:34 +0200

fix: use OR for target_id filters in vote lookup

Multiple target_id filters were AND'd together, making the query
impossible to match. Use OR for target_ids while AND'ing with
user_id and target_type. Also reverts incorrect base64 conversion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Diffstat:
Msrc/trailbase.rs | 31++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/src/trailbase.rs b/src/trailbase.rs @@ -47,10 +47,7 @@ pub fn extract_user_id_from_token(auth_token: &str) -> Option<String> { // Parse as JSON and extract "sub" claim let json: serde_json::Value = serde_json::from_str(&payload_str).ok()?; - // Convert URL-safe base64 to standard base64 to match trailbase's format - json.get("sub").and_then(|v| v.as_str()).map(|s| { - s.replace('-', "+").replace('_', "/") - }) + json.get("sub").and_then(|v| v.as_str()).map(|s| s.to_string()) } /// URL-safe base64 decode (handles missing padding) @@ -441,19 +438,23 @@ pub async fn get_user_votes( .and_then(|t| extract_user_id_from_token(&t.auth_token)) .ok_or_else(|| ClientError::Auth("Not authenticated".into()))?; - let mut filters = vec![ - Filter::new("user_id", CompareOp::Equal, &user_id), - Filter::new("target_type", CompareOp::Equal, target_type.to_string()), - ]; + use trailbase_client::ValueOrFilterGroup; - // Add filters for each target ID - let id_filters: Vec<Filter> = target_ids - .iter() - .map(|id| Filter::new("target_id", CompareOp::Equal, id.to_string())) - .collect(); - filters.extend(id_filters); + // Build: user_id=X AND target_type=T AND (target_id=A OR target_id=B OR ...) + let id_or = ValueOrFilterGroup::Or( + target_ids + .iter() + .map(|id| ValueOrFilterGroup::Filter(Filter::new("target_id", CompareOp::Equal, id.to_string()))) + .collect(), + ); + + let combined = ValueOrFilterGroup::And(vec![ + ValueOrFilterGroup::Filter(Filter::new("user_id", CompareOp::Equal, &user_id)), + ValueOrFilterGroup::Filter(Filter::new("target_type", CompareOp::Equal, target_type.to_string())), + id_or, + ]); - let args = ListArguments::new().with_filters(filters); + let args = ListArguments::new().with_filters(combined); let response = client.records("vote").list::<Vote>(args).await?; let voted_ids: Vec<i64> = response.records.iter().map(|v| v.target_id).collect();