Highly ambitious ATProtocol AppView service and sdks
138
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix graphql blob ref field to return string instead of object

+34 -23
+5 -5
api/src/graphql/schema_builder.rs
··· 1064 1064 1065 1065 /// Container to hold blob data and DID for URL generation 1066 1066 #[derive(Clone)] 1067 - struct BlobContainer { 1068 - blob_ref: String, // CID reference 1069 - mime_type: String, // MIME type 1070 - size: i64, // Size in bytes 1071 - did: String, // DID for CDN URL generation 1067 + pub struct BlobContainer { 1068 + pub blob_ref: String, // CID reference 1069 + pub mime_type: String, // MIME type 1070 + pub size: i64, // Size in bytes 1071 + pub did: String, // DID for CDN URL generation 1072 1072 } 1073 1073 1074 1074 /// Creates a GraphQL Object type for a record collection
+29 -18
api/src/graphql/schema_ext/blob_upload.rs
··· 1 1 //! GraphQL schema extension for blob uploads 2 2 3 3 use async_graphql::dynamic::{Field, FieldFuture, FieldValue, InputValue, Object, TypeRef}; 4 - use async_graphql::{Error, Value as GraphQLValue}; 4 + use async_graphql::Error; 5 5 use base64::engine::general_purpose; 6 6 use base64::Engine; 7 7 8 8 use crate::atproto_extensions::upload_blob as atproto_upload_blob; 9 9 use crate::auth; 10 - 11 - /// Container for blob upload response 12 - #[derive(Clone)] 13 - struct BlobUploadContainer { 14 - blob: serde_json::Value, 15 - } 10 + use crate::graphql::schema_builder::BlobContainer; 16 11 17 12 /// Creates the BlobUploadResponse GraphQL type 18 13 pub fn create_blob_upload_response_type() -> Object { 19 14 let mut response = Object::new("BlobUploadResponse"); 20 15 21 - response = response.field(Field::new("blob", TypeRef::named_nn("JSON"), |ctx| { 16 + // Return the Blob type instead of JSON to ensure consistent ref field handling 17 + response = response.field(Field::new("blob", TypeRef::named_nn("Blob"), |ctx| { 22 18 FieldFuture::new(async move { 23 - let container = ctx.parent_value.try_downcast_ref::<BlobUploadContainer>()?; 24 - // Convert serde_json::Value to async_graphql::Value 25 - let graphql_value: GraphQLValue = serde_json::from_value(container.blob.clone()) 26 - .map_err(|e| async_graphql::Error::new(format!("Failed to convert blob to GraphQL value: {}", e)))?; 27 - Ok(Some(graphql_value)) 19 + // The BlobContainer is passed through from the mutation resolver 20 + // The Blob type resolver will handle extracting the fields 21 + let container = ctx.parent_value.try_downcast_ref::<BlobContainer>()?; 22 + Ok(Some(FieldValue::owned_any(container.clone()))) 28 23 }) 29 24 })); 30 25 ··· 70 65 .decode(data_base64) 71 66 .map_err(|e| Error::new(format!("Invalid base64 data: {}", e)))?; 72 67 68 + // Verify OAuth token to get user info (needed for DID) 69 + let user_info = auth::verify_oauth_token_cached( 70 + token, 71 + &auth_base, 72 + gql_ctx.auth_cache.clone(), 73 + ) 74 + .await 75 + .map_err(|e| Error::new(format!("Invalid token: {}", e)))?; 76 + 73 77 // Get ATProto DPoP auth and PDS URL for this user 74 78 let (dpop_auth, pds_url) = auth::get_atproto_auth_for_user_cached( 75 79 token, ··· 91 95 .await 92 96 .map_err(|e| Error::new(format!("Failed to upload blob: {}", e)))?; 93 97 94 - // Convert blob to JSON value 95 - let blob_json = serde_json::to_value(&upload_result.blob) 96 - .map_err(|e| Error::new(format!("Failed to serialize blob: {}", e)))?; 98 + // Extract the DID from user info 99 + let did = user_info.did.unwrap_or(user_info.sub); 100 + 101 + // Create BlobContainer with flattened ref field (CID string) 102 + // This ensures the GraphQL Blob type returns ref as a String, not an object 103 + let blob_container = BlobContainer { 104 + blob_ref: upload_result.blob.r#ref.link.clone(), // Extract CID from ref.$link 105 + mime_type: upload_result.blob.mime_type.clone(), 106 + size: upload_result.blob.size as i64, 107 + did, 108 + }; 97 109 98 - let container = BlobUploadContainer { blob: blob_json }; 99 - Ok(Some(FieldValue::owned_any(container))) 110 + Ok(Some(FieldValue::owned_any(blob_container))) 100 111 }) 101 112 }, 102 113 )