Skip to main content

rustauth_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) -> rustauth_core::api::AsyncAuthEndpoint {
20    endpoint(
21        "/api-key/get",
22        Method::GET,
23        configurations,
24        |context, request, configurations| async move {
25            let id = match query_param(&request, "id") {
26                Some(id) => id,
27                None => return error(StatusCode::BAD_REQUEST, errors::KEY_NOT_FOUND),
28            };
29            let config_id = query_param(&request, "configId");
30            let options = configurations.resolve(config_id.as_deref())?;
31            let Some(identity) = current_identity(&context, &request).await? else {
32                return error(StatusCode::UNAUTHORIZED, errors::UNAUTHORIZED_SESSION);
33            };
34            let store = ApiKeyStore::new(&context, &options);
35            let Some(mut api_key) = store.get_by_id(&id).await? else {
36                return error(StatusCode::NOT_FOUND, errors::KEY_NOT_FOUND);
37            };
38            let expected_config_id = options.config_id.as_deref().unwrap_or("default");
39            if !config_id_matches(&api_key.config_id, expected_config_id) {
40                return error(StatusCode::NOT_FOUND, errors::KEY_NOT_FOUND);
41            }
42            match options.reference {
43                ApiKeyReference::User
44                    if owns_user_key(
45                        options.reference,
46                        &api_key.reference_id,
47                        &identity.user.id,
48                    ) => {}
49                ApiKeyReference::User => {
50                    return error(StatusCode::NOT_FOUND, errors::KEY_NOT_FOUND);
51                }
52                ApiKeyReference::Organization => {
53                    if let Err(error) = ensure_organization_permission(
54                        &context,
55                        &identity.user.id,
56                        &api_key.reference_id,
57                        ApiKeyAction::Read,
58                    )
59                    .await
60                    {
61                        return error_response_from_rustauth(error);
62                    }
63                }
64            }
65            store.migrate_metadata_if_needed(&mut api_key).await;
66            json(StatusCode::OK, &api_key.public())
67        },
68    )
69}
70
71fn error_response_from_rustauth(
72    error: rustauth_core::error::RustAuthError,
73) -> Result<rustauth_core::api::ApiResponse, rustauth_core::error::RustAuthError> {
74    let message = error.to_string();
75    if message.contains(errors::message(errors::USER_NOT_MEMBER_OF_ORGANIZATION)) {
76        return super::error(
77            StatusCode::FORBIDDEN,
78            errors::USER_NOT_MEMBER_OF_ORGANIZATION,
79        );
80    }
81    if message.contains(errors::message(errors::ORGANIZATION_PLUGIN_REQUIRED)) {
82        return super::error(
83            StatusCode::INTERNAL_SERVER_ERROR,
84            errors::ORGANIZATION_PLUGIN_REQUIRED,
85        );
86    }
87    super::error(
88        StatusCode::FORBIDDEN,
89        errors::INSUFFICIENT_API_KEY_PERMISSIONS,
90    )
91}