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:
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();