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