this repo has no description
1use crate::api::ApiError; 2use crate::state::AppState; 3use axum::{ 4 Json, 5 extract::State, 6 http::StatusCode, 7 response::{IntoResponse, Response}, 8}; 9use chrono::{Duration, Utc}; 10use serde_json::json; 11use tracing::{error, info, warn}; 12 13fn generate_plc_token() -> String { 14 crate::util::generate_token_code() 15} 16 17pub async fn request_plc_operation_signature( 18 State(state): State<AppState>, 19 headers: axum::http::HeaderMap, 20) -> Response { 21 let token = match crate::auth::extract_bearer_token_from_header( 22 headers.get("Authorization").and_then(|h| h.to_str().ok()), 23 ) { 24 Some(t) => t, 25 None => return ApiError::AuthenticationRequired.into_response(), 26 }; 27 let auth_user = 28 match crate::auth::validate_bearer_token_allow_deactivated(&state.db, &token).await { 29 Ok(user) => user, 30 Err(e) => return ApiError::from(e).into_response(), 31 }; 32 if let Err(e) = crate::auth::scope_check::check_identity_scope( 33 auth_user.is_oauth, 34 auth_user.scope.as_deref(), 35 crate::oauth::scopes::IdentityAttr::Wildcard, 36 ) { 37 return e; 38 } 39 let user = match sqlx::query!("SELECT id FROM users WHERE did = $1", auth_user.did) 40 .fetch_optional(&state.db) 41 .await 42 { 43 Ok(Some(row)) => row, 44 Ok(None) => return ApiError::AccountNotFound.into_response(), 45 Err(e) => { 46 error!("DB error: {:?}", e); 47 return ApiError::InternalError.into_response(); 48 } 49 }; 50 let _ = sqlx::query!( 51 "DELETE FROM plc_operation_tokens WHERE user_id = $1 OR expires_at < NOW()", 52 user.id 53 ) 54 .execute(&state.db) 55 .await; 56 let plc_token = generate_plc_token(); 57 let expires_at = Utc::now() + Duration::minutes(10); 58 if let Err(e) = sqlx::query!( 59 r#" 60 INSERT INTO plc_operation_tokens (user_id, token, expires_at) 61 VALUES ($1, $2, $3) 62 "#, 63 user.id, 64 plc_token, 65 expires_at 66 ) 67 .execute(&state.db) 68 .await 69 { 70 error!("Failed to create PLC token: {:?}", e); 71 return ( 72 StatusCode::INTERNAL_SERVER_ERROR, 73 Json(json!({"error": "InternalError"})), 74 ) 75 .into_response(); 76 } 77 let hostname = std::env::var("PDS_HOSTNAME").unwrap_or_else(|_| "localhost".to_string()); 78 if let Err(e) = 79 crate::comms::enqueue_plc_operation(&state.db, user.id, &plc_token, &hostname).await 80 { 81 warn!("Failed to enqueue PLC operation notification: {:?}", e); 82 } 83 info!( 84 "PLC operation signature requested for user {}", 85 auth_user.did 86 ); 87 (StatusCode::OK, Json(json!({}))).into_response() 88}