From cda690bf39bc1c26634ed8ba07539196bed59257 Mon Sep 17 00:00:00 2001 From: Pa1NarK <69745008+pixincreate@users.noreply.github.com> Date: Wed, 25 Sep 2024 16:22:09 +0530 Subject: [PATCH] fix(api_key): fix api key `list` and `update` endpoints for v2 (#5980) --- .../api-reference/api-key/api-key--list.mdx | 3 + api-reference-v2/mint.json | 3 +- api-reference-v2/openapi_spec.json | 54 ++++++++++++ .../api-reference/api-key/api-key--list.mdx | 3 + api-reference/mint.json | 3 +- api-reference/openapi_spec.json | 63 ++++++++++++++ crates/api_models/src/api_keys.rs | 2 +- crates/api_models/src/events.rs | 1 + crates/openapi/src/openapi.rs | 1 + crates/openapi/src/openapi_v2.rs | 1 + crates/openapi/src/routes/api_keys.rs | 41 +++++++++ crates/router/src/routes/api_keys.rs | 86 +++++++++---------- 12 files changed, 214 insertions(+), 47 deletions(-) create mode 100644 api-reference-v2/api-reference/api-key/api-key--list.mdx create mode 100644 api-reference/api-reference/api-key/api-key--list.mdx diff --git a/api-reference-v2/api-reference/api-key/api-key--list.mdx b/api-reference-v2/api-reference/api-key/api-key--list.mdx new file mode 100644 index 00000000000..5975e9bd6ca --- /dev/null +++ b/api-reference-v2/api-reference/api-key/api-key--list.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /v2/api_keys/list +--- diff --git a/api-reference-v2/mint.json b/api-reference-v2/mint.json index 4c053f4d96d..030d29958dc 100644 --- a/api-reference-v2/mint.json +++ b/api-reference-v2/mint.json @@ -86,7 +86,8 @@ "api-reference/api-key/api-key--create", "api-reference/api-key/api-key--retrieve", "api-reference/api-key/api-key--update", - "api-reference/api-key/api-key--revoke" + "api-reference/api-key/api-key--revoke", + "api-reference/api-key/api-key--list" ] }, { diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 99462e95e07..2a32899880d 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -1433,6 +1433,60 @@ ] } }, + "/v2/api_keys/list": { + "get": { + "tags": [ + "API Key" + ], + "summary": "API Key - List", + "description": "List all the API Keys associated to a merchant account.", + "operationId": "List all API Keys associated with a merchant account", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "The maximum number of API Keys to include in the response", + "required": false, + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "skip", + "in": "query", + "description": "The number of API Keys to skip when retrieving the list of API keys.", + "required": false, + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + } + ], + "responses": { + "200": { + "description": "List of API Keys retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RetrieveApiKeyResponse" + } + } + } + } + } + }, + "security": [ + { + "admin_api_key": [] + } + ] + } + }, "/v2/customers": { "post": { "tags": [ diff --git a/api-reference/api-reference/api-key/api-key--list.mdx b/api-reference/api-reference/api-key/api-key--list.mdx new file mode 100644 index 00000000000..ba371a57ce9 --- /dev/null +++ b/api-reference/api-reference/api-key/api-key--list.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /api_keys/{merchant_id}/list +--- diff --git a/api-reference/mint.json b/api-reference/mint.json index b5d9a4b6206..03a76fed183 100644 --- a/api-reference/mint.json +++ b/api-reference/mint.json @@ -137,7 +137,8 @@ "api-reference/api-key/api-key--create", "api-reference/api-key/api-key--retrieve", "api-reference/api-key/api-key--update", - "api-reference/api-key/api-key--revoke" + "api-reference/api-key/api-key--revoke", + "api-reference/api-key/api-key--list" ] }, { diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index f5f01c8c49c..dfcaf157c21 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -4841,6 +4841,69 @@ ] } }, + "/api_keys/{merchant_id}/list": { + "get": { + "tags": [ + "API Key" + ], + "summary": "API Key - List", + "description": "List all the API Keys associated to a merchant account.", + "operationId": "List all API Keys associated with a merchant account", + "parameters": [ + { + "name": "merchant_id", + "in": "path", + "description": "The unique identifier for the merchant account", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "The maximum number of API Keys to include in the response", + "required": false, + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "skip", + "in": "query", + "description": "The number of API Keys to skip when retrieving the list of API keys.", + "required": false, + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + } + ], + "responses": { + "200": { + "description": "List of API Keys retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RetrieveApiKeyResponse" + } + } + } + } + } + }, + "security": [ + { + "admin_api_key": [] + } + ] + } + }, "/events/{merchant_id}": { "get": { "tags": [ diff --git a/crates/api_models/src/api_keys.rs b/crates/api_models/src/api_keys.rs index 1fc7ce97be8..65cc6b9a25a 100644 --- a/crates/api_models/src/api_keys.rs +++ b/crates/api_models/src/api_keys.rs @@ -154,7 +154,7 @@ pub struct RevokeApiKeyResponse { } /// The constraints that are applicable when listing API Keys associated with a merchant account. -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(deny_unknown_fields)] pub struct ListApiKeyConstraints { /// The maximum number of API Keys to include in the response. diff --git a/crates/api_models/src/events.rs b/crates/api_models/src/events.rs index b8a872ffd25..5816df518bd 100644 --- a/crates/api_models/src/events.rs +++ b/crates/api_models/src/events.rs @@ -90,6 +90,7 @@ impl_api_event_type!( CardInfoResponse, CreateApiKeyResponse, CreateApiKeyRequest, + ListApiKeyConstraints, MerchantConnectorDeleteResponse, MerchantConnectorUpdate, MerchantConnectorCreate, diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs index 85865584494..ae999bb0604 100644 --- a/crates/openapi/src/openapi.rs +++ b/crates/openapi/src/openapi.rs @@ -183,6 +183,7 @@ Never share your secret api keys. Keep them guarded and secure. routes::api_keys::api_key_retrieve, routes::api_keys::api_key_update, routes::api_keys::api_key_revoke, + routes::api_keys::api_key_list, // Routes for events routes::webhook_events::list_initial_webhook_delivery_attempts, diff --git a/crates/openapi/src/openapi_v2.rs b/crates/openapi/src/openapi_v2.rs index 6e6e2f6f87d..64fb7a4e93d 100644 --- a/crates/openapi/src/openapi_v2.rs +++ b/crates/openapi/src/openapi_v2.rs @@ -109,6 +109,7 @@ Never share your secret api keys. Keep them guarded and secure. routes::api_keys::api_key_retrieve, routes::api_keys::api_key_update, routes::api_keys::api_key_revoke, + routes::api_keys::api_key_list, //Routes for customers routes::customers::customers_create, diff --git a/crates/openapi/src/routes/api_keys.rs b/crates/openapi/src/routes/api_keys.rs index 7ed2afe91a1..7527c8a1095 100644 --- a/crates/openapi/src/routes/api_keys.rs +++ b/crates/openapi/src/routes/api_keys.rs @@ -163,3 +163,44 @@ pub async fn api_key_revoke() {} security(("admin_api_key" = [])) )] pub async fn api_key_revoke() {} + +#[cfg(feature = "v1")] +/// API Key - List +/// +/// List all the API Keys associated to a merchant account. +#[utoipa::path( + get, + path = "/api_keys/{merchant_id}/list", + params( + ("merchant_id" = String, Path, description = "The unique identifier for the merchant account"), + ("limit" = Option, Query, description = "The maximum number of API Keys to include in the response"), + ("skip" = Option, Query, description = "The number of API Keys to skip when retrieving the list of API keys."), + ), + responses( + (status = 200, description = "List of API Keys retrieved successfully", body = Vec), + ), + tag = "API Key", + operation_id = "List all API Keys associated with a merchant account", + security(("admin_api_key" = [])) +)] +pub async fn api_key_list() {} + +#[cfg(feature = "v2")] +/// API Key - List +/// +/// List all the API Keys associated to a merchant account. +#[utoipa::path( + get, + path = "/v2/api_keys/list", + params( + ("limit" = Option, Query, description = "The maximum number of API Keys to include in the response"), + ("skip" = Option, Query, description = "The number of API Keys to skip when retrieving the list of API keys."), + ), + responses( + (status = 200, description = "List of API Keys retrieved successfully", body = Vec), + ), + tag = "API Key", + operation_id = "List all API Keys associated with a merchant account", + security(("admin_api_key" = [])) +)] +pub async fn api_key_list() {} diff --git a/crates/router/src/routes/api_keys.rs b/crates/router/src/routes/api_keys.rs index a00e740b3e6..047e0d9b886 100644 --- a/crates/router/src/routes/api_keys.rs +++ b/crates/router/src/routes/api_keys.rs @@ -9,10 +9,6 @@ use crate::{ types::api as api_types, }; -/// API Key - Create -/// -/// Create a new API Key for accessing our APIs from your servers. The plaintext API Key will be -/// displayed only once on creation, so ensure you store it securely. #[cfg(feature = "v1")] #[instrument(skip_all, fields(flow = ?Flow::ApiKeyCreate))] pub async fn api_key_create( @@ -78,9 +74,6 @@ pub async fn api_key_create( .await } -/// API Key - Retrieve -/// -/// Retrieve information about the specified API Key. #[cfg(feature = "v2")] #[instrument(skip_all, fields(flow = ?Flow::ApiKeyRetrieve))] pub async fn api_key_retrieve( @@ -117,9 +110,6 @@ pub async fn api_key_retrieve( } #[cfg(feature = "v1")] -/// API Key - Retrieve -/// -/// Retrieve information about the specified API Key. #[instrument(skip_all, fields(flow = ?Flow::ApiKeyRetrieve))] pub async fn api_key_retrieve( state: web::Data, @@ -150,9 +140,6 @@ pub async fn api_key_retrieve( } #[cfg(feature = "v1")] -/// API Key - Update -/// -/// Update information for the specified API Key. #[instrument(skip_all, fields(flow = ?Flow::ApiKeyUpdate))] pub async fn api_key_update( state: web::Data, @@ -190,26 +177,27 @@ pub async fn api_key_update( pub async fn api_key_update( state: web::Data, req: HttpRequest, - path: web::Path<(common_utils::id_type::MerchantId, String)>, + key_id: web::Path, json_payload: web::Json, ) -> impl Responder { let flow = Flow::ApiKeyUpdate; - let (merchant_id, key_id) = path.into_inner(); + let api_key_id = key_id.into_inner(); let mut payload = json_payload.into_inner(); - payload.key_id = key_id; - payload.merchant_id.clone_from(&merchant_id); + payload.key_id = api_key_id; api::server_wrap( flow, state, &req, payload, - |state, _, payload, _| api_keys::update_api_key(state, payload), + |state, authentication_data, mut payload, _| { + payload.merchant_id = authentication_data.merchant_account.get_id().to_owned(); + api_keys::update_api_key(state, payload) + }, auth::auth_type( - &auth::AdminApiAuth, - &auth::JWTAuthMerchantFromRoute { - merchant_id, - required_permission: Permission::ApiKeyWrite, + &auth::AdminApiAuthWithMerchantIdFromHeader, + &auth::JWTAuthMerchantFromHeader { + required_permission: Permission::ApiKeyRead, minimum_entity_level: EntityType::Merchant, }, req.headers(), @@ -220,10 +208,6 @@ pub async fn api_key_update( } #[cfg(feature = "v1")] -/// API Key - Revoke -/// -/// Revoke the specified API Key. Once revoked, the API Key can no longer be used for -/// authenticating with our APIs. #[instrument(skip_all, fields(flow = ?Flow::ApiKeyRevoke))] pub async fn api_key_revoke( state: web::Data, @@ -283,24 +267,7 @@ pub async fn api_key_revoke( .await } -/// API Key - List -/// -/// List all API Keys associated with your merchant account. -#[utoipa::path( - get, - path = "/api_keys/{merchant_id}/list", - params( - ("merchant_id" = String, Path, description = "The unique identifier for the merchant account"), - ("limit" = Option, Query, description = "The maximum number of API Keys to include in the response"), - ("skip" = Option, Query, description = "The number of API Keys to skip when retrieving the list of API keys."), - ), - responses( - (status = 200, description = "List of API Keys retrieved successfully", body = Vec), - ), - tag = "API Key", - operation_id = "List all API Keys associated with a merchant account", - security(("admin_api_key" = [])) -)] +#[cfg(feature = "v1")] #[instrument(skip_all, fields(flow = ?Flow::ApiKeyList))] pub async fn api_key_list( state: web::Data, @@ -335,3 +302,34 @@ pub async fn api_key_list( ) .await } +#[cfg(feature = "v2")] +#[instrument(skip_all, fields(flow = ?Flow::ApiKeyList))] +pub async fn api_key_list( + state: web::Data, + req: HttpRequest, + query: web::Query, +) -> impl Responder { + let flow = Flow::ApiKeyList; + let payload = query.into_inner(); + + api::server_wrap( + flow, + state, + &req, + payload, + |state, authentication_data, payload, _| async move { + let merchant_id = authentication_data.merchant_account.get_id().to_owned(); + api_keys::list_api_keys(state, merchant_id, payload.limit, payload.skip).await + }, + auth::auth_type( + &auth::AdminApiAuthWithMerchantIdFromHeader, + &auth::JWTAuthMerchantFromHeader { + required_permission: Permission::ApiKeyRead, + minimum_entity_level: EntityType::Merchant, + }, + req.headers(), + ), + api_locking::LockAction::NotApplicable, + ) + .await +}