Skip to main content

openauth_plugins/api_key/routes/
get.rs

1use http::{Method, StatusCode};
2use serde::{Deserialize, Serialize};
3
4use super::{
5    config_id_matches, current_identity, endpoint, error, json, query_param, SharedConfigurations,
6};
7use crate::api_key::errors;
8use crate::api_key::options::ApiKeyReference;
9use crate::api_key::organization::{ensure_organization_permission, owns_user_key, ApiKeyAction};
10use crate::api_key::storage::ApiKeyStore;
11
12#[derive(Debug, Clone, Deserialize, Serialize, Default)]
13#[serde(rename_all = "camelCase")]
14pub struct GetApiKeyQuery {
15    pub id: String,
16    pub config_id: Option<String>,
17}
18
19pub fn get_endpoint(configurations: SharedConfigurations) -> openauth_core::api::AsyncAuthEndpoint {
20    endpoint(
21        "/api-key/get",
22        Method::GET,
23        configurations,
24        |context, request, configurations| {
25            Box::pin(async move {
26                let id = match query_param(&request, "id") {
27                    Some(id) => id,
28                    None => return error(StatusCode::BAD_REQUEST, errors::KEY_NOT_FOUND),
29                };
30                let config_id = query_param(&request, "configId");
31                let options = configurations.resolve(config_id.as_deref())?;
32                let Some(identity) = current_identity(context, &request).await? else {
33                    return error(StatusCode::UNAUTHORIZED, errors::UNAUTHORIZED_SESSION);
34                };
35                let Some(api_key) = ApiKeyStore::new(context, &options).get_by_id(&id).await?
36                else {
37                    return error(StatusCode::NOT_FOUND, errors::KEY_NOT_FOUND);
38                };
39                let expected_config_id = options.config_id.as_deref().unwrap_or("default");
40                if !config_id_matches(&api_key.config_id, expected_config_id) {
41                    return error(StatusCode::NOT_FOUND, errors::KEY_NOT_FOUND);
42                }
43                match options.reference {
44                    ApiKeyReference::User
45                        if owns_user_key(
46                            options.reference,
47                            &api_key.reference_id,
48                            &identity.user.id,
49                        ) => {}
50                    ApiKeyReference::User => {
51                        return error(StatusCode::NOT_FOUND, errors::KEY_NOT_FOUND);
52                    }
53                    ApiKeyReference::Organization => {
54                        if let Err(error) = ensure_organization_permission(
55                            context,
56                            &identity.user.id,
57                            &api_key.reference_id,
58                            ApiKeyAction::Read,
59                        )
60                        .await
61                        {
62                            return error_response_from_openauth(error);
63                        }
64                    }
65                }
66                json(StatusCode::OK, &api_key.public())
67            })
68        },
69    )
70}
71
72fn error_response_from_openauth(
73    error: openauth_core::error::OpenAuthError,
74) -> Result<openauth_core::api::ApiResponse, openauth_core::error::OpenAuthError> {
75    let message = error.to_string();
76    if message.contains(errors::message(errors::USER_NOT_MEMBER_OF_ORGANIZATION)) {
77        return super::error(
78            StatusCode::FORBIDDEN,
79            errors::USER_NOT_MEMBER_OF_ORGANIZATION,
80        );
81    }
82    if message.contains(errors::message(errors::ORGANIZATION_PLUGIN_REQUIRED)) {
83        return super::error(
84            StatusCode::INTERNAL_SERVER_ERROR,
85            errors::ORGANIZATION_PLUGIN_REQUIRED,
86        );
87    }
88    super::error(
89        StatusCode::FORBIDDEN,
90        errors::INSUFFICIENT_API_KEY_PERMISSIONS,
91    )
92}