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