this repo has no description
1use crate::api::repo::record::create_record_internal; 2use crate::state::AppState; 3use axum::{ 4 Json, 5 extract::State, 6 http::StatusCode, 7 response::{IntoResponse, Response}, 8}; 9use serde::{Deserialize, Serialize}; 10use serde_json::json; 11use tracing::{error, info}; 12 13#[derive(Deserialize)] 14#[serde(rename_all = "camelCase")] 15pub struct CreateProfileInput { 16 pub did: String, 17 pub display_name: Option<String>, 18 pub description: Option<String>, 19} 20 21#[derive(Deserialize)] 22#[serde(rename_all = "camelCase")] 23pub struct CreateRecordAdminInput { 24 pub did: String, 25 pub collection: String, 26 pub rkey: Option<String>, 27 pub record: serde_json::Value, 28} 29 30#[derive(Serialize)] 31#[serde(rename_all = "camelCase")] 32pub struct CreateProfileOutput { 33 pub uri: String, 34 pub cid: String, 35} 36 37pub async fn create_profile( 38 State(state): State<AppState>, 39 headers: axum::http::HeaderMap, 40 Json(input): Json<CreateProfileInput>, 41) -> Response { 42 let auth_header = headers.get("Authorization"); 43 if auth_header.is_none() { 44 return ( 45 StatusCode::UNAUTHORIZED, 46 Json(json!({"error": "AuthenticationRequired"})), 47 ) 48 .into_response(); 49 } 50 51 let did = input.did.trim(); 52 if did.is_empty() { 53 return ( 54 StatusCode::BAD_REQUEST, 55 Json(json!({"error": "InvalidRequest", "message": "did is required"})), 56 ) 57 .into_response(); 58 } 59 60 let mut profile_record = json!({ 61 "$type": "app.bsky.actor.profile" 62 }); 63 64 if let Some(display_name) = &input.display_name { 65 profile_record["displayName"] = json!(display_name); 66 } 67 if let Some(description) = &input.description { 68 profile_record["description"] = json!(description); 69 } 70 71 match create_record_internal( 72 &state, 73 did, 74 "app.bsky.actor.profile", 75 "self", 76 &profile_record, 77 ).await { 78 Ok((uri, commit_cid)) => { 79 info!(did = %did, uri = %uri, "Created profile for user"); 80 ( 81 StatusCode::OK, 82 Json(CreateProfileOutput { 83 uri, 84 cid: commit_cid.to_string(), 85 }), 86 ) 87 .into_response() 88 } 89 Err(e) => { 90 error!("Failed to create profile for {}: {}", did, e); 91 ( 92 StatusCode::INTERNAL_SERVER_ERROR, 93 Json(json!({"error": "InternalError", "message": e})), 94 ) 95 .into_response() 96 } 97 } 98} 99 100pub async fn create_record_admin( 101 State(state): State<AppState>, 102 headers: axum::http::HeaderMap, 103 Json(input): Json<CreateRecordAdminInput>, 104) -> Response { 105 let auth_header = headers.get("Authorization"); 106 if auth_header.is_none() { 107 return ( 108 StatusCode::UNAUTHORIZED, 109 Json(json!({"error": "AuthenticationRequired"})), 110 ) 111 .into_response(); 112 } 113 114 let did = input.did.trim(); 115 if did.is_empty() { 116 return ( 117 StatusCode::BAD_REQUEST, 118 Json(json!({"error": "InvalidRequest", "message": "did is required"})), 119 ) 120 .into_response(); 121 } 122 123 let rkey = input.rkey.unwrap_or_else(|| { 124 chrono::Utc::now().format("%Y%m%d%H%M%S%f").to_string() 125 }); 126 127 match create_record_internal( 128 &state, 129 did, 130 &input.collection, 131 &rkey, 132 &input.record, 133 ).await { 134 Ok((uri, commit_cid)) => { 135 info!(did = %did, uri = %uri, "Admin created record"); 136 ( 137 StatusCode::OK, 138 Json(CreateProfileOutput { 139 uri, 140 cid: commit_cid.to_string(), 141 }), 142 ) 143 .into_response() 144 } 145 Err(e) => { 146 error!("Failed to create record for {}: {}", did, e); 147 ( 148 StatusCode::INTERNAL_SERVER_ERROR, 149 Json(json!({"error": "InternalError", "message": e})), 150 ) 151 .into_response() 152 } 153 } 154}