A decentralized music tracking and discovery platform built on AT Protocol 🎵

Merge branch 'main' into feat/feed-generator

+31 -1
+24
crates/scrobbler/src/auth.rs
··· 10 11 use crate::cache::Cache; 12 use crate::repo; 13 use crate::signature::generate_signature; 14 use crate::xata::user::User; 15 ··· 149 let user: User = serde_json::from_str(&user) 150 .map_err(|e| Error::msg(format!("Failed to deserialize user: {}", e)))?; 151 Ok(user.xata_id) 152 } 153 154 #[cfg(test)]
··· 10 11 use crate::cache::Cache; 12 use crate::repo; 13 + use crate::rocksky::ROCKSKY_API; 14 use crate::signature::generate_signature; 15 use crate::xata::user::User; 16 ··· 150 let user: User = serde_json::from_str(&user) 151 .map_err(|e| Error::msg(format!("Failed to deserialize user: {}", e)))?; 152 Ok(user.xata_id) 153 + } 154 + 155 + pub async fn validate_bearer_token(pool: &Pool<Postgres>, token: &str) -> Result<(), Error> { 156 + let user = repo::user::get_user_by_apikey(pool, token).await?; 157 + if user.is_none() { 158 + return Err(Error::msg("Invalid token")); 159 + } 160 + 161 + let user = user.unwrap(); 162 + let jwt = generate_token(&user.did)?; 163 + let client = reqwest::Client::new(); 164 + 165 + client 166 + .get(&format!( 167 + "{}/xrpc/app.rocksky.actor.getProfile", 168 + ROCKSKY_API 169 + )) 170 + .bearer_auth(jwt) 171 + .send() 172 + .await? 173 + .error_for_status()?; 174 + 175 + Ok(()) 176 } 177 178 #[cfg(test)]
+6
crates/scrobbler/src/listenbrainz/handlers.rs
··· 4 use sqlx::{Pool, Postgres}; 5 6 use crate::{ 7 cache::Cache, 8 listenbrainz::{ 9 core::{ ··· 55 if token.is_empty() { 56 return Ok(HttpResponse::Unauthorized().finish()); 57 } 58 59 let payload = read_payload!(payload); 60 let body = String::from_utf8_lossy(&payload);
··· 4 use sqlx::{Pool, Postgres}; 5 6 use crate::{ 7 + auth::validate_bearer_token, 8 cache::Cache, 9 listenbrainz::{ 10 core::{ ··· 56 if token.is_empty() { 57 return Ok(HttpResponse::Unauthorized().finish()); 58 } 59 + 60 + let pool = data.get_ref(); 61 + validate_bearer_token(pool, token) 62 + .await 63 + .map_err(|e| actix_web::error::ErrorUnauthorized(format!("Invalid token: {}", e)))?; 64 65 let payload = read_payload!(payload); 66 let body = String::from_utf8_lossy(&payload);
+1 -1
crates/scrobbler/src/rocksky.rs
··· 3 4 use crate::{auth::generate_token, cache::Cache, types::Track}; 5 6 - const ROCKSKY_API: &str = "https://api.rocksky.app"; 7 8 pub async fn scrobble(cache: &Cache, did: &str, track: Track, timestamp: u64) -> Result<(), Error> { 9 let key = format!(
··· 3 4 use crate::{auth::generate_token, cache::Cache, types::Track}; 5 6 + pub const ROCKSKY_API: &str = "https://api.rocksky.app"; 7 8 pub async fn scrobble(cache: &Cache, did: &str, track: Track, timestamp: u64) -> Result<(), Error> { 9 let key = format!(