this repo has no description
1use crate::api::ApiError;
2use crate::state::AppState;
3use axum::{
4 extract::State,
5 http::StatusCode,
6 response::{IntoResponse, Response},
7 Json,
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
28 let auth_user = match crate::auth::validate_bearer_token(&state.db, &token).await {
29 Ok(user) => user,
30 Err(e) => return ApiError::from(e).into_response(),
31 };
32
33 let user = match sqlx::query!("SELECT id FROM users WHERE did = $1", auth_user.did)
34 .fetch_optional(&state.db)
35 .await
36 {
37 Ok(Some(row)) => row,
38 Ok(None) => return ApiError::AccountNotFound.into_response(),
39 Err(e) => {
40 error!("DB error: {:?}", e);
41 return ApiError::InternalError.into_response();
42 }
43 };
44
45 let _ = sqlx::query!(
46 "DELETE FROM plc_operation_tokens WHERE user_id = $1 OR expires_at < NOW()",
47 user.id
48 )
49 .execute(&state.db)
50 .await;
51
52 let plc_token = generate_plc_token();
53 let expires_at = Utc::now() + Duration::minutes(10);
54
55 if let Err(e) = sqlx::query!(
56 r#"
57 INSERT INTO plc_operation_tokens (user_id, token, expires_at)
58 VALUES ($1, $2, $3)
59 "#,
60 user.id,
61 plc_token,
62 expires_at
63 )
64 .execute(&state.db)
65 .await
66 {
67 error!("Failed to create PLC token: {:?}", e);
68 return (
69 StatusCode::INTERNAL_SERVER_ERROR,
70 Json(json!({"error": "InternalError"})),
71 )
72 .into_response();
73 }
74
75 let hostname = std::env::var("PDS_HOSTNAME").unwrap_or_else(|_| "localhost".to_string());
76
77 if let Err(e) = crate::notifications::enqueue_plc_operation(
78 &state.db,
79 user.id,
80 &plc_token,
81 &hostname,
82 )
83 .await
84 {
85 warn!("Failed to enqueue PLC operation notification: {:?}", e);
86 }
87
88 info!("PLC operation signature requested for user {}", auth_user.did);
89
90 (StatusCode::OK, Json(json!({}))).into_response()
91}