From dde29a21ae3c624d8931e8d8e88b161185b3494d Mon Sep 17 00:00:00 2001 From: James Kachel Date: Thu, 10 Oct 2024 10:42:32 -0500 Subject: [PATCH] Reworks OpenAPI generation/setup to mirror other projects (#159) --- config/apisix/apisix.yaml | 2 +- .../src/generated/.openapi-generator/VERSION | 1 - .../api/src/generated/{ => v0}/.gitignore | 0 .../api/src/generated/{ => v0}/.npmignore | 0 .../{ => v0}/.openapi-generator-ignore | 0 .../{ => v0}/.openapi-generator/FILES | 0 .../generated/v0/.openapi-generator/VERSION | 1 + frontends/api/src/generated/{ => v0}/api.ts | 679 +++++++++-- frontends/api/src/generated/{ => v0}/base.ts | 20 +- .../api/src/generated/{ => v0}/common.ts | 2 +- .../src/generated/{ => v0}/configuration.ts | 9 + .../api/src/generated/{ => v0}/git_push.sh | 0 frontends/api/src/generated/{ => v0}/index.ts | 0 openapi/__init__.py | 0 openapi/apps.py | 6 + openapi/exceptions.py | 5 + openapi/hooks.py | 72 ++ openapi/management/__init__.py | 0 openapi/management/commands/__init__.py | 0 .../commands/generate_openapi_spec.py | 50 + .../settings_spectacular.py | 9 +- openapi/specs/v0.yaml | 1067 +++++++++++++++++ openapi/urls.py | 26 + payments/models.py | 11 +- payments/serializers/v0/__init__.py | 33 +- payments/urls.py | 6 +- payments/views/v0/__init__.py | 38 +- payments/views/v0/urls.py | 7 - scripts/generate_openapi.sh | 11 +- .../templates/modelEnum.mustache | 25 + ...pt-axios.yaml => typescript-axios-v0.yaml} | 4 +- scripts/test/openapi_spec_check.sh | 12 +- system_meta/urls.py | 12 +- unified_ecommerce/permissions.py | 7 +- unified_ecommerce/settings.py | 8 + unified_ecommerce/urls.py | 23 +- unified_ecommerce/urls_spectacular.py | 8 - unified_ecommerce/viewsets.py | 2 - 38 files changed, 1953 insertions(+), 203 deletions(-) delete mode 100644 frontends/api/src/generated/.openapi-generator/VERSION rename frontends/api/src/generated/{ => v0}/.gitignore (100%) rename frontends/api/src/generated/{ => v0}/.npmignore (100%) rename frontends/api/src/generated/{ => v0}/.openapi-generator-ignore (100%) rename frontends/api/src/generated/{ => v0}/.openapi-generator/FILES (100%) create mode 100644 frontends/api/src/generated/v0/.openapi-generator/VERSION rename frontends/api/src/generated/{ => v0}/api.ts (76%) rename frontends/api/src/generated/{ => v0}/base.ts (79%) rename frontends/api/src/generated/{ => v0}/common.ts (96%) rename frontends/api/src/generated/{ => v0}/configuration.ts (94%) rename frontends/api/src/generated/{ => v0}/git_push.sh (100%) rename frontends/api/src/generated/{ => v0}/index.ts (100%) create mode 100644 openapi/__init__.py create mode 100644 openapi/apps.py create mode 100644 openapi/exceptions.py create mode 100644 openapi/hooks.py create mode 100644 openapi/management/__init__.py create mode 100644 openapi/management/commands/__init__.py create mode 100644 openapi/management/commands/generate_openapi_spec.py rename {unified_ecommerce => openapi}/settings_spectacular.py (52%) create mode 100644 openapi/specs/v0.yaml create mode 100644 openapi/urls.py create mode 100644 scripts/openapi-configs/templates/modelEnum.mustache rename scripts/openapi-configs/{typescript-axios.yaml => typescript-axios-v0.yaml} (64%) delete mode 100644 unified_ecommerce/urls_spectacular.py diff --git a/config/apisix/apisix.yaml b/config/apisix/apisix.yaml index d4366e15..7b3985e0 100644 --- a/config/apisix/apisix.yaml +++ b/config/apisix/apisix.yaml @@ -14,7 +14,7 @@ routes: uris: - "/checkout/result/*" - "/static/*" - - "/api/schema/*" + - "/api/v0/schema/*" - id: 2 name: "ue-default" desc: "Wildcard route for the rest of the system - authentication required" diff --git a/frontends/api/src/generated/.openapi-generator/VERSION b/frontends/api/src/generated/.openapi-generator/VERSION deleted file mode 100644 index 826f5ce0..00000000 --- a/frontends/api/src/generated/.openapi-generator/VERSION +++ /dev/null @@ -1 +0,0 @@ -6.6.0 diff --git a/frontends/api/src/generated/.gitignore b/frontends/api/src/generated/v0/.gitignore similarity index 100% rename from frontends/api/src/generated/.gitignore rename to frontends/api/src/generated/v0/.gitignore diff --git a/frontends/api/src/generated/.npmignore b/frontends/api/src/generated/v0/.npmignore similarity index 100% rename from frontends/api/src/generated/.npmignore rename to frontends/api/src/generated/v0/.npmignore diff --git a/frontends/api/src/generated/.openapi-generator-ignore b/frontends/api/src/generated/v0/.openapi-generator-ignore similarity index 100% rename from frontends/api/src/generated/.openapi-generator-ignore rename to frontends/api/src/generated/v0/.openapi-generator-ignore diff --git a/frontends/api/src/generated/.openapi-generator/FILES b/frontends/api/src/generated/v0/.openapi-generator/FILES similarity index 100% rename from frontends/api/src/generated/.openapi-generator/FILES rename to frontends/api/src/generated/v0/.openapi-generator/FILES diff --git a/frontends/api/src/generated/v0/.openapi-generator/VERSION b/frontends/api/src/generated/v0/.openapi-generator/VERSION new file mode 100644 index 00000000..0ee843cc --- /dev/null +++ b/frontends/api/src/generated/v0/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.2.0 diff --git a/frontends/api/src/generated/api.ts b/frontends/api/src/generated/v0/api.ts similarity index 76% rename from frontends/api/src/generated/api.ts rename to frontends/api/src/generated/v0/api.ts index 490199a1..ba314b72 100644 --- a/frontends/api/src/generated/api.ts +++ b/frontends/api/src/generated/v0/api.ts @@ -14,14 +14,14 @@ import type { Configuration } from './configuration'; -import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios'; +import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios'; import globalAxios from 'axios'; // Some imports not used depending on template conditions // @ts-ignore import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from './common'; import type { RequestArgs } from './base'; // @ts-ignore -import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError } from './base'; +import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerMap } from './base'; /** * Basket model serializer @@ -104,6 +104,191 @@ export interface IntegratedSystem { */ 'description'?: string; } +/** + * Serializes a line item for an order. + * @export + * @interface Line + */ +export interface Line { + /** + * + * @type {number} + * @memberof Line + */ + 'id': number; + /** + * + * @type {number} + * @memberof Line + */ + 'quantity': number; + /** + * + * @type {string} + * @memberof Line + */ + 'item_description': string; + /** + * + * @type {string} + * @memberof Line + */ + 'unit_price': string; + /** + * + * @type {string} + * @memberof Line + */ + 'total_price': string; + /** + * + * @type {Product} + * @memberof Line + */ + 'product': Product; +} +/** + * + * @export + * @interface Nested + */ +export interface Nested { + /** + * + * @type {number} + * @memberof Nested + */ + 'id': number; + /** + * + * @type {string} + * @memberof Nested + */ + 'password': string; + /** + * + * @type {string} + * @memberof Nested + */ + 'last_login'?: string | null; + /** + * Designates that this user has all permissions without explicitly assigning them. + * @type {boolean} + * @memberof Nested + */ + 'is_superuser'?: boolean; + /** + * Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only. + * @type {string} + * @memberof Nested + */ + 'username': string; + /** + * + * @type {string} + * @memberof Nested + */ + 'first_name'?: string; + /** + * + * @type {string} + * @memberof Nested + */ + 'last_name'?: string; + /** + * + * @type {string} + * @memberof Nested + */ + 'email'?: string; + /** + * Designates whether the user can log into this admin site. + * @type {boolean} + * @memberof Nested + */ + 'is_staff'?: boolean; + /** + * Designates whether this user should be treated as active. Unselect this instead of deleting accounts. + * @type {boolean} + * @memberof Nested + */ + 'is_active'?: boolean; + /** + * + * @type {string} + * @memberof Nested + */ + 'date_joined'?: string; + /** + * The groups this user belongs to. A user will get all permissions granted to each of their groups. + * @type {Array} + * @memberof Nested + */ + 'groups'?: Array; + /** + * Specific permissions for this user. + * @type {Array} + * @memberof Nested + */ + 'user_permissions'?: Array; +} +/** + * + * @export + * @interface OrderHistory + */ +export interface OrderHistory { + /** + * + * @type {number} + * @memberof OrderHistory + */ + 'id': number; + /** + * + * @type {StateEnum} + * @memberof OrderHistory + */ + 'state'?: StateEnum; + /** + * + * @type {string} + * @memberof OrderHistory + */ + 'reference_number'?: string; + /** + * + * @type {Nested} + * @memberof OrderHistory + */ + 'purchaser': Nested; + /** + * + * @type {string} + * @memberof OrderHistory + */ + 'total_price_paid': string; + /** + * + * @type {Array} + * @memberof OrderHistory + */ + 'lines': Array; + /** + * + * @type {string} + * @memberof OrderHistory + */ + 'created_on': string; + /** + * + * @type {string} + * @memberof OrderHistory + */ + 'updated_on': string; +} + + /** * * @export @@ -197,6 +382,37 @@ export interface PaginatedIntegratedSystemList { */ 'results': Array; } +/** + * + * @export + * @interface PaginatedOrderHistoryList + */ +export interface PaginatedOrderHistoryList { + /** + * + * @type {number} + * @memberof PaginatedOrderHistoryList + */ + 'count': number; + /** + * + * @type {string} + * @memberof PaginatedOrderHistoryList + */ + 'next'?: string | null; + /** + * + * @type {string} + * @memberof PaginatedOrderHistoryList + */ + 'previous'?: string | null; + /** + * + * @type {Array} + * @memberof PaginatedOrderHistoryList + */ + 'results': Array; +} /** * * @export @@ -405,6 +621,35 @@ export interface Product { */ 'system': number; } +/** + * * `pending` - Pending * `fulfilled` - Fulfilled * `canceled` - Canceled * `refunded` - Refunded * `declined` - Declined * `errored` - Errored * `review` - Review + * @export + * @enum {string} + */ + +export const StateEnumDescriptions = { + 'pending': "", + 'fulfilled': "", + 'canceled': "", + 'refunded': "", + 'declined': "", + 'errored': "", + 'review': "", +} as const; + +export const StateEnum = { + Pending: 'pending', + Fulfilled: 'fulfilled', + Canceled: 'canceled', + Refunded: 'refunded', + Declined: 'declined', + Errored: 'errored', + Review: 'review' +} as const; + +export type StateEnum = typeof StateEnum[keyof typeof StateEnum]; + + /** * ApiApi - axios parameter creator @@ -417,7 +662,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsClearDestroy: async (options: AxiosRequestConfig = {}): Promise => { + apiV0PaymentsBasketsClearDestroy: async (options: RawAxiosRequestConfig = {}): Promise => { const localVarPath = `/api/v0/payments/baskets/clear/`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -450,7 +695,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsCreateFromProductCreate: async (sku: string, system_slug: string, options: AxiosRequestConfig = {}): Promise => { + apiV0PaymentsBasketsCreateFromProductCreate: async (sku: string, system_slug: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'sku' is not null or undefined assertParamExists('apiV0PaymentsBasketsCreateFromProductCreate', 'sku', sku) // verify required parameter 'system_slug' is not null or undefined @@ -489,7 +734,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsItemsCreate: async (basket: string, BasketItem: BasketItem, options: AxiosRequestConfig = {}): Promise => { + apiV0PaymentsBasketsItemsCreate: async (basket: string, BasketItem: BasketItem, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'basket' is not null or undefined assertParamExists('apiV0PaymentsBasketsItemsCreate', 'basket', basket) // verify required parameter 'BasketItem' is not null or undefined @@ -530,7 +775,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsItemsDestroy: async (basket: string, id: string, options: AxiosRequestConfig = {}): Promise => { + apiV0PaymentsBasketsItemsDestroy: async (basket: string, id: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'basket' is not null or undefined assertParamExists('apiV0PaymentsBasketsItemsDestroy', 'basket', basket) // verify required parameter 'id' is not null or undefined @@ -570,7 +815,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsItemsList: async (basket: string, limit?: number, offset?: number, options: AxiosRequestConfig = {}): Promise => { + apiV0PaymentsBasketsItemsList: async (basket: string, limit?: number, offset?: number, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'basket' is not null or undefined assertParamExists('apiV0PaymentsBasketsItemsList', 'basket', basket) const localVarPath = `/api/v0/payments/baskets/{basket}/items/` @@ -614,7 +859,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsList: async (limit?: number, offset?: number, options: AxiosRequestConfig = {}): Promise => { + apiV0PaymentsBasketsList: async (limit?: number, offset?: number, options: RawAxiosRequestConfig = {}): Promise => { const localVarPath = `/api/v0/payments/baskets/`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -654,7 +899,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsRetrieve: async (username: string, options: AxiosRequestConfig = {}): Promise => { + apiV0PaymentsBasketsRetrieve: async (username: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'username' is not null or undefined assertParamExists('apiV0PaymentsBasketsRetrieve', 'username', username) const localVarPath = `/api/v0/payments/baskets/{username}/` @@ -688,7 +933,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsCheckoutCallbackCreate: async (options: AxiosRequestConfig = {}): Promise => { + apiV0PaymentsCheckoutCallbackCreate: async (options: RawAxiosRequestConfig = {}): Promise => { const localVarPath = `/api/v0/payments/checkout/callback/`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -717,7 +962,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsCheckoutStartCheckoutCreate: async (options: AxiosRequestConfig = {}): Promise => { + apiV0PaymentsCheckoutStartCheckoutCreate: async (options: RawAxiosRequestConfig = {}): Promise => { const localVarPath = `/api/v0/payments/checkout/start_checkout/`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -734,6 +979,82 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {number} [limit] Number of results to return per page. + * @param {number} [offset] The initial index from which to return the results. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiV0PaymentsOrdersHistoryList: async (limit?: number, offset?: number, options: RawAxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v0/payments/orders/history/`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication cookieAuth required + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (offset !== undefined) { + localVarQueryParameter['offset'] = offset; + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiV0PaymentsOrdersHistoryRetrieve: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('apiV0PaymentsOrdersHistoryRetrieve', 'id', id) + const localVarPath = `/api/v0/payments/orders/history/{id}/` + .replace(`{${"id"}}`, encodeURIComponent(String(id))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication cookieAuth required + + + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; @@ -758,9 +1079,11 @@ export const ApiApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiV0PaymentsBasketsClearDestroy(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async apiV0PaymentsBasketsClearDestroy(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsBasketsClearDestroy(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsBasketsClearDestroy']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Create a new basket item from a product for the currently logged in user. Reuse the existing basket object if it exists. If the checkout flag is set in the POST data, then this will create the basket, then immediately flip the user to the checkout interstitial (which then redirects to the payment gateway). Args: system_slug (str): system slug sku (str): product slug POST Args: quantity (int): quantity of the product to add to the basket (defaults to 1) checkout (bool): redirect to checkout interstitial (defaults to False) Returns: Response: HTTP response @@ -769,9 +1092,11 @@ export const ApiApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiV0PaymentsBasketsCreateFromProductCreate(sku: string, system_slug: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async apiV0PaymentsBasketsCreateFromProductCreate(sku: string, system_slug: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsBasketsCreateFromProductCreate(sku, system_slug, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsBasketsCreateFromProductCreate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Create a new basket item. Args: request (HttpRequest): HTTP request Returns: Response: HTTP response @@ -780,9 +1105,11 @@ export const ApiApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiV0PaymentsBasketsItemsCreate(basket: string, BasketItem: BasketItem, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async apiV0PaymentsBasketsItemsCreate(basket: string, BasketItem: BasketItem, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsBasketsItemsCreate(basket, BasketItem, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsBasketsItemsCreate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * API view set for BasketItem @@ -791,9 +1118,11 @@ export const ApiApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiV0PaymentsBasketsItemsDestroy(basket: string, id: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async apiV0PaymentsBasketsItemsDestroy(basket: string, id: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsBasketsItemsDestroy(basket, id, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsBasketsItemsDestroy']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * API view set for BasketItem @@ -803,9 +1132,11 @@ export const ApiApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiV0PaymentsBasketsItemsList(basket: string, limit?: number, offset?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async apiV0PaymentsBasketsItemsList(basket: string, limit?: number, offset?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsBasketsItemsList(basket, limit, offset, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsBasketsItemsList']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * API view set for Basket @@ -814,9 +1145,11 @@ export const ApiApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiV0PaymentsBasketsList(limit?: number, offset?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async apiV0PaymentsBasketsList(limit?: number, offset?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsBasketsList(limit, offset, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsBasketsList']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * API view set for Basket @@ -824,27 +1157,58 @@ export const ApiApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiV0PaymentsBasketsRetrieve(username: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async apiV0PaymentsBasketsRetrieve(username: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsBasketsRetrieve(username, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsBasketsRetrieve']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Handle webhook call from the payment gateway when the user has completed a transaction. Returns: - HTTP_200_OK if the Order is found. Raises: - Http404 if the Order is not found. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiV0PaymentsCheckoutCallbackCreate(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async apiV0PaymentsCheckoutCallbackCreate(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsCheckoutCallbackCreate(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsCheckoutCallbackCreate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Start the checkout process. This assembles the basket items into an Order with Lines for each item, applies the attached basket discounts, and then calls the payment gateway to prepare for payment. This is expected to be called from within the Ecommerce cart app, not from an integrated system. Returns: - JSON payload from the ol-django payment gateway app. The payment gateway returns data necessary to construct a form that will ultimately POST to the actual payment processor. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiV0PaymentsCheckoutStartCheckoutCreate(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async apiV0PaymentsCheckoutStartCheckoutCreate(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsCheckoutStartCheckoutCreate(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsCheckoutStartCheckoutCreate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + }, + /** + * + * @param {number} [limit] Number of results to return per page. + * @param {number} [offset] The initial index from which to return the results. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiV0PaymentsOrdersHistoryList(limit?: number, offset?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsOrdersHistoryList(limit, offset, options); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsOrdersHistoryList']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); + }, + /** + * + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiV0PaymentsOrdersHistoryRetrieve(id: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.apiV0PaymentsOrdersHistoryRetrieve(id, options); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ApiApi.apiV0PaymentsOrdersHistoryRetrieve']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, } }; @@ -861,7 +1225,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsClearDestroy(options?: AxiosRequestConfig): AxiosPromise { + apiV0PaymentsBasketsClearDestroy(options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.apiV0PaymentsBasketsClearDestroy(options).then((request) => request(axios, basePath)); }, /** @@ -870,7 +1234,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsCreateFromProductCreate(requestParameters: ApiApiApiV0PaymentsBasketsCreateFromProductCreateRequest, options?: AxiosRequestConfig): AxiosPromise { + apiV0PaymentsBasketsCreateFromProductCreate(requestParameters: ApiApiApiV0PaymentsBasketsCreateFromProductCreateRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.apiV0PaymentsBasketsCreateFromProductCreate(requestParameters.sku, requestParameters.system_slug, options).then((request) => request(axios, basePath)); }, /** @@ -879,7 +1243,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsItemsCreate(requestParameters: ApiApiApiV0PaymentsBasketsItemsCreateRequest, options?: AxiosRequestConfig): AxiosPromise { + apiV0PaymentsBasketsItemsCreate(requestParameters: ApiApiApiV0PaymentsBasketsItemsCreateRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.apiV0PaymentsBasketsItemsCreate(requestParameters.basket, requestParameters.BasketItem, options).then((request) => request(axios, basePath)); }, /** @@ -888,7 +1252,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsItemsDestroy(requestParameters: ApiApiApiV0PaymentsBasketsItemsDestroyRequest, options?: AxiosRequestConfig): AxiosPromise { + apiV0PaymentsBasketsItemsDestroy(requestParameters: ApiApiApiV0PaymentsBasketsItemsDestroyRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.apiV0PaymentsBasketsItemsDestroy(requestParameters.basket, requestParameters.id, options).then((request) => request(axios, basePath)); }, /** @@ -897,7 +1261,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsItemsList(requestParameters: ApiApiApiV0PaymentsBasketsItemsListRequest, options?: AxiosRequestConfig): AxiosPromise { + apiV0PaymentsBasketsItemsList(requestParameters: ApiApiApiV0PaymentsBasketsItemsListRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.apiV0PaymentsBasketsItemsList(requestParameters.basket, requestParameters.limit, requestParameters.offset, options).then((request) => request(axios, basePath)); }, /** @@ -906,7 +1270,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsList(requestParameters: ApiApiApiV0PaymentsBasketsListRequest = {}, options?: AxiosRequestConfig): AxiosPromise { + apiV0PaymentsBasketsList(requestParameters: ApiApiApiV0PaymentsBasketsListRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.apiV0PaymentsBasketsList(requestParameters.limit, requestParameters.offset, options).then((request) => request(axios, basePath)); }, /** @@ -915,7 +1279,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsBasketsRetrieve(requestParameters: ApiApiApiV0PaymentsBasketsRetrieveRequest, options?: AxiosRequestConfig): AxiosPromise { + apiV0PaymentsBasketsRetrieve(requestParameters: ApiApiApiV0PaymentsBasketsRetrieveRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.apiV0PaymentsBasketsRetrieve(requestParameters.username, options).then((request) => request(axios, basePath)); }, /** @@ -923,7 +1287,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsCheckoutCallbackCreate(options?: AxiosRequestConfig): AxiosPromise { + apiV0PaymentsCheckoutCallbackCreate(options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.apiV0PaymentsCheckoutCallbackCreate(options).then((request) => request(axios, basePath)); }, /** @@ -931,9 +1295,27 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiV0PaymentsCheckoutStartCheckoutCreate(options?: AxiosRequestConfig): AxiosPromise { + apiV0PaymentsCheckoutStartCheckoutCreate(options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.apiV0PaymentsCheckoutStartCheckoutCreate(options).then((request) => request(axios, basePath)); }, + /** + * + * @param {ApiApiApiV0PaymentsOrdersHistoryListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiV0PaymentsOrdersHistoryList(requestParameters: ApiApiApiV0PaymentsOrdersHistoryListRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.apiV0PaymentsOrdersHistoryList(requestParameters.limit, requestParameters.offset, options).then((request) => request(axios, basePath)); + }, + /** + * + * @param {ApiApiApiV0PaymentsOrdersHistoryRetrieveRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiV0PaymentsOrdersHistoryRetrieve(requestParameters: ApiApiApiV0PaymentsOrdersHistoryRetrieveRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.apiV0PaymentsOrdersHistoryRetrieve(requestParameters.id, options).then((request) => request(axios, basePath)); + }, }; }; @@ -1063,6 +1445,41 @@ export interface ApiApiApiV0PaymentsBasketsRetrieveRequest { readonly username: string } +/** + * Request parameters for apiV0PaymentsOrdersHistoryList operation in ApiApi. + * @export + * @interface ApiApiApiV0PaymentsOrdersHistoryListRequest + */ +export interface ApiApiApiV0PaymentsOrdersHistoryListRequest { + /** + * Number of results to return per page. + * @type {number} + * @memberof ApiApiApiV0PaymentsOrdersHistoryList + */ + readonly limit?: number + + /** + * The initial index from which to return the results. + * @type {number} + * @memberof ApiApiApiV0PaymentsOrdersHistoryList + */ + readonly offset?: number +} + +/** + * Request parameters for apiV0PaymentsOrdersHistoryRetrieve operation in ApiApi. + * @export + * @interface ApiApiApiV0PaymentsOrdersHistoryRetrieveRequest + */ +export interface ApiApiApiV0PaymentsOrdersHistoryRetrieveRequest { + /** + * + * @type {string} + * @memberof ApiApiApiV0PaymentsOrdersHistoryRetrieve + */ + readonly id: string +} + /** * ApiApi - object-oriented interface * @export @@ -1076,7 +1493,7 @@ export class ApiApi extends BaseAPI { * @throws {RequiredError} * @memberof ApiApi */ - public apiV0PaymentsBasketsClearDestroy(options?: AxiosRequestConfig) { + public apiV0PaymentsBasketsClearDestroy(options?: RawAxiosRequestConfig) { return ApiApiFp(this.configuration).apiV0PaymentsBasketsClearDestroy(options).then((request) => request(this.axios, this.basePath)); } @@ -1087,7 +1504,7 @@ export class ApiApi extends BaseAPI { * @throws {RequiredError} * @memberof ApiApi */ - public apiV0PaymentsBasketsCreateFromProductCreate(requestParameters: ApiApiApiV0PaymentsBasketsCreateFromProductCreateRequest, options?: AxiosRequestConfig) { + public apiV0PaymentsBasketsCreateFromProductCreate(requestParameters: ApiApiApiV0PaymentsBasketsCreateFromProductCreateRequest, options?: RawAxiosRequestConfig) { return ApiApiFp(this.configuration).apiV0PaymentsBasketsCreateFromProductCreate(requestParameters.sku, requestParameters.system_slug, options).then((request) => request(this.axios, this.basePath)); } @@ -1098,7 +1515,7 @@ export class ApiApi extends BaseAPI { * @throws {RequiredError} * @memberof ApiApi */ - public apiV0PaymentsBasketsItemsCreate(requestParameters: ApiApiApiV0PaymentsBasketsItemsCreateRequest, options?: AxiosRequestConfig) { + public apiV0PaymentsBasketsItemsCreate(requestParameters: ApiApiApiV0PaymentsBasketsItemsCreateRequest, options?: RawAxiosRequestConfig) { return ApiApiFp(this.configuration).apiV0PaymentsBasketsItemsCreate(requestParameters.basket, requestParameters.BasketItem, options).then((request) => request(this.axios, this.basePath)); } @@ -1109,7 +1526,7 @@ export class ApiApi extends BaseAPI { * @throws {RequiredError} * @memberof ApiApi */ - public apiV0PaymentsBasketsItemsDestroy(requestParameters: ApiApiApiV0PaymentsBasketsItemsDestroyRequest, options?: AxiosRequestConfig) { + public apiV0PaymentsBasketsItemsDestroy(requestParameters: ApiApiApiV0PaymentsBasketsItemsDestroyRequest, options?: RawAxiosRequestConfig) { return ApiApiFp(this.configuration).apiV0PaymentsBasketsItemsDestroy(requestParameters.basket, requestParameters.id, options).then((request) => request(this.axios, this.basePath)); } @@ -1120,7 +1537,7 @@ export class ApiApi extends BaseAPI { * @throws {RequiredError} * @memberof ApiApi */ - public apiV0PaymentsBasketsItemsList(requestParameters: ApiApiApiV0PaymentsBasketsItemsListRequest, options?: AxiosRequestConfig) { + public apiV0PaymentsBasketsItemsList(requestParameters: ApiApiApiV0PaymentsBasketsItemsListRequest, options?: RawAxiosRequestConfig) { return ApiApiFp(this.configuration).apiV0PaymentsBasketsItemsList(requestParameters.basket, requestParameters.limit, requestParameters.offset, options).then((request) => request(this.axios, this.basePath)); } @@ -1131,7 +1548,7 @@ export class ApiApi extends BaseAPI { * @throws {RequiredError} * @memberof ApiApi */ - public apiV0PaymentsBasketsList(requestParameters: ApiApiApiV0PaymentsBasketsListRequest = {}, options?: AxiosRequestConfig) { + public apiV0PaymentsBasketsList(requestParameters: ApiApiApiV0PaymentsBasketsListRequest = {}, options?: RawAxiosRequestConfig) { return ApiApiFp(this.configuration).apiV0PaymentsBasketsList(requestParameters.limit, requestParameters.offset, options).then((request) => request(this.axios, this.basePath)); } @@ -1142,7 +1559,7 @@ export class ApiApi extends BaseAPI { * @throws {RequiredError} * @memberof ApiApi */ - public apiV0PaymentsBasketsRetrieve(requestParameters: ApiApiApiV0PaymentsBasketsRetrieveRequest, options?: AxiosRequestConfig) { + public apiV0PaymentsBasketsRetrieve(requestParameters: ApiApiApiV0PaymentsBasketsRetrieveRequest, options?: RawAxiosRequestConfig) { return ApiApiFp(this.configuration).apiV0PaymentsBasketsRetrieve(requestParameters.username, options).then((request) => request(this.axios, this.basePath)); } @@ -1152,7 +1569,7 @@ export class ApiApi extends BaseAPI { * @throws {RequiredError} * @memberof ApiApi */ - public apiV0PaymentsCheckoutCallbackCreate(options?: AxiosRequestConfig) { + public apiV0PaymentsCheckoutCallbackCreate(options?: RawAxiosRequestConfig) { return ApiApiFp(this.configuration).apiV0PaymentsCheckoutCallbackCreate(options).then((request) => request(this.axios, this.basePath)); } @@ -1162,12 +1579,35 @@ export class ApiApi extends BaseAPI { * @throws {RequiredError} * @memberof ApiApi */ - public apiV0PaymentsCheckoutStartCheckoutCreate(options?: AxiosRequestConfig) { + public apiV0PaymentsCheckoutStartCheckoutCreate(options?: RawAxiosRequestConfig) { return ApiApiFp(this.configuration).apiV0PaymentsCheckoutStartCheckoutCreate(options).then((request) => request(this.axios, this.basePath)); } + + /** + * + * @param {ApiApiApiV0PaymentsOrdersHistoryListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ApiApi + */ + public apiV0PaymentsOrdersHistoryList(requestParameters: ApiApiApiV0PaymentsOrdersHistoryListRequest = {}, options?: RawAxiosRequestConfig) { + return ApiApiFp(this.configuration).apiV0PaymentsOrdersHistoryList(requestParameters.limit, requestParameters.offset, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @param {ApiApiApiV0PaymentsOrdersHistoryRetrieveRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ApiApi + */ + public apiV0PaymentsOrdersHistoryRetrieve(requestParameters: ApiApiApiV0PaymentsOrdersHistoryRetrieveRequest, options?: RawAxiosRequestConfig) { + return ApiApiFp(this.configuration).apiV0PaymentsOrdersHistoryRetrieve(requestParameters.id, options).then((request) => request(this.axios, this.basePath)); + } } + /** * IntegratedSystemApi - axios parameter creator * @export @@ -1180,7 +1620,7 @@ export const IntegratedSystemApiAxiosParamCreator = function (configuration?: Co * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemCreate: async (IntegratedSystem: IntegratedSystem, options: AxiosRequestConfig = {}): Promise => { + integratedSystemCreate: async (IntegratedSystem: IntegratedSystem, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'IntegratedSystem' is not null or undefined assertParamExists('integratedSystemCreate', 'IntegratedSystem', IntegratedSystem) const localVarPath = `/integrated_system/`; @@ -1217,7 +1657,7 @@ export const IntegratedSystemApiAxiosParamCreator = function (configuration?: Co * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemDestroy: async (id: number, options: AxiosRequestConfig = {}): Promise => { + integratedSystemDestroy: async (id: number, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('integratedSystemDestroy', 'id', id) const localVarPath = `/integrated_system/{id}/` @@ -1253,7 +1693,7 @@ export const IntegratedSystemApiAxiosParamCreator = function (configuration?: Co * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemList: async (limit?: number, offset?: number, options: AxiosRequestConfig = {}): Promise => { + integratedSystemList: async (limit?: number, offset?: number, options: RawAxiosRequestConfig = {}): Promise => { const localVarPath = `/integrated_system/`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1294,7 +1734,7 @@ export const IntegratedSystemApiAxiosParamCreator = function (configuration?: Co * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemPartialUpdate: async (id: number, PatchedIntegratedSystem?: PatchedIntegratedSystem, options: AxiosRequestConfig = {}): Promise => { + integratedSystemPartialUpdate: async (id: number, PatchedIntegratedSystem?: PatchedIntegratedSystem, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('integratedSystemPartialUpdate', 'id', id) const localVarPath = `/integrated_system/{id}/` @@ -1332,7 +1772,7 @@ export const IntegratedSystemApiAxiosParamCreator = function (configuration?: Co * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemRetrieve: async (id: number, options: AxiosRequestConfig = {}): Promise => { + integratedSystemRetrieve: async (id: number, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('integratedSystemRetrieve', 'id', id) const localVarPath = `/integrated_system/{id}/` @@ -1368,7 +1808,7 @@ export const IntegratedSystemApiAxiosParamCreator = function (configuration?: Co * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemUpdate: async (id: number, IntegratedSystem: IntegratedSystem, options: AxiosRequestConfig = {}): Promise => { + integratedSystemUpdate: async (id: number, IntegratedSystem: IntegratedSystem, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('integratedSystemUpdate', 'id', id) // verify required parameter 'IntegratedSystem' is not null or undefined @@ -1418,9 +1858,11 @@ export const IntegratedSystemApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async integratedSystemCreate(IntegratedSystem: IntegratedSystem, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async integratedSystemCreate(IntegratedSystem: IntegratedSystem, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.integratedSystemCreate(IntegratedSystem, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['IntegratedSystemApi.integratedSystemCreate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for IntegratedSystem model. @@ -1428,9 +1870,11 @@ export const IntegratedSystemApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async integratedSystemDestroy(id: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async integratedSystemDestroy(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.integratedSystemDestroy(id, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['IntegratedSystemApi.integratedSystemDestroy']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for IntegratedSystem model. @@ -1439,9 +1883,11 @@ export const IntegratedSystemApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async integratedSystemList(limit?: number, offset?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async integratedSystemList(limit?: number, offset?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.integratedSystemList(limit, offset, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['IntegratedSystemApi.integratedSystemList']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for IntegratedSystem model. @@ -1450,9 +1896,11 @@ export const IntegratedSystemApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async integratedSystemPartialUpdate(id: number, PatchedIntegratedSystem?: PatchedIntegratedSystem, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async integratedSystemPartialUpdate(id: number, PatchedIntegratedSystem?: PatchedIntegratedSystem, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.integratedSystemPartialUpdate(id, PatchedIntegratedSystem, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['IntegratedSystemApi.integratedSystemPartialUpdate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for IntegratedSystem model. @@ -1460,9 +1908,11 @@ export const IntegratedSystemApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async integratedSystemRetrieve(id: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async integratedSystemRetrieve(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.integratedSystemRetrieve(id, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['IntegratedSystemApi.integratedSystemRetrieve']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for IntegratedSystem model. @@ -1471,9 +1921,11 @@ export const IntegratedSystemApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async integratedSystemUpdate(id: number, IntegratedSystem: IntegratedSystem, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async integratedSystemUpdate(id: number, IntegratedSystem: IntegratedSystem, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.integratedSystemUpdate(id, IntegratedSystem, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['IntegratedSystemApi.integratedSystemUpdate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, } }; @@ -1491,7 +1943,7 @@ export const IntegratedSystemApiFactory = function (configuration?: Configuratio * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemCreate(requestParameters: IntegratedSystemApiIntegratedSystemCreateRequest, options?: AxiosRequestConfig): AxiosPromise { + integratedSystemCreate(requestParameters: IntegratedSystemApiIntegratedSystemCreateRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.integratedSystemCreate(requestParameters.IntegratedSystem, options).then((request) => request(axios, basePath)); }, /** @@ -1500,7 +1952,7 @@ export const IntegratedSystemApiFactory = function (configuration?: Configuratio * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemDestroy(requestParameters: IntegratedSystemApiIntegratedSystemDestroyRequest, options?: AxiosRequestConfig): AxiosPromise { + integratedSystemDestroy(requestParameters: IntegratedSystemApiIntegratedSystemDestroyRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.integratedSystemDestroy(requestParameters.id, options).then((request) => request(axios, basePath)); }, /** @@ -1509,7 +1961,7 @@ export const IntegratedSystemApiFactory = function (configuration?: Configuratio * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemList(requestParameters: IntegratedSystemApiIntegratedSystemListRequest = {}, options?: AxiosRequestConfig): AxiosPromise { + integratedSystemList(requestParameters: IntegratedSystemApiIntegratedSystemListRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.integratedSystemList(requestParameters.limit, requestParameters.offset, options).then((request) => request(axios, basePath)); }, /** @@ -1518,7 +1970,7 @@ export const IntegratedSystemApiFactory = function (configuration?: Configuratio * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemPartialUpdate(requestParameters: IntegratedSystemApiIntegratedSystemPartialUpdateRequest, options?: AxiosRequestConfig): AxiosPromise { + integratedSystemPartialUpdate(requestParameters: IntegratedSystemApiIntegratedSystemPartialUpdateRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.integratedSystemPartialUpdate(requestParameters.id, requestParameters.PatchedIntegratedSystem, options).then((request) => request(axios, basePath)); }, /** @@ -1527,7 +1979,7 @@ export const IntegratedSystemApiFactory = function (configuration?: Configuratio * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemRetrieve(requestParameters: IntegratedSystemApiIntegratedSystemRetrieveRequest, options?: AxiosRequestConfig): AxiosPromise { + integratedSystemRetrieve(requestParameters: IntegratedSystemApiIntegratedSystemRetrieveRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.integratedSystemRetrieve(requestParameters.id, options).then((request) => request(axios, basePath)); }, /** @@ -1536,7 +1988,7 @@ export const IntegratedSystemApiFactory = function (configuration?: Configuratio * @param {*} [options] Override http request option. * @throws {RequiredError} */ - integratedSystemUpdate(requestParameters: IntegratedSystemApiIntegratedSystemUpdateRequest, options?: AxiosRequestConfig): AxiosPromise { + integratedSystemUpdate(requestParameters: IntegratedSystemApiIntegratedSystemUpdateRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.integratedSystemUpdate(requestParameters.id, requestParameters.IntegratedSystem, options).then((request) => request(axios, basePath)); }, }; @@ -1661,7 +2113,7 @@ export class IntegratedSystemApi extends BaseAPI { * @throws {RequiredError} * @memberof IntegratedSystemApi */ - public integratedSystemCreate(requestParameters: IntegratedSystemApiIntegratedSystemCreateRequest, options?: AxiosRequestConfig) { + public integratedSystemCreate(requestParameters: IntegratedSystemApiIntegratedSystemCreateRequest, options?: RawAxiosRequestConfig) { return IntegratedSystemApiFp(this.configuration).integratedSystemCreate(requestParameters.IntegratedSystem, options).then((request) => request(this.axios, this.basePath)); } @@ -1672,7 +2124,7 @@ export class IntegratedSystemApi extends BaseAPI { * @throws {RequiredError} * @memberof IntegratedSystemApi */ - public integratedSystemDestroy(requestParameters: IntegratedSystemApiIntegratedSystemDestroyRequest, options?: AxiosRequestConfig) { + public integratedSystemDestroy(requestParameters: IntegratedSystemApiIntegratedSystemDestroyRequest, options?: RawAxiosRequestConfig) { return IntegratedSystemApiFp(this.configuration).integratedSystemDestroy(requestParameters.id, options).then((request) => request(this.axios, this.basePath)); } @@ -1683,7 +2135,7 @@ export class IntegratedSystemApi extends BaseAPI { * @throws {RequiredError} * @memberof IntegratedSystemApi */ - public integratedSystemList(requestParameters: IntegratedSystemApiIntegratedSystemListRequest = {}, options?: AxiosRequestConfig) { + public integratedSystemList(requestParameters: IntegratedSystemApiIntegratedSystemListRequest = {}, options?: RawAxiosRequestConfig) { return IntegratedSystemApiFp(this.configuration).integratedSystemList(requestParameters.limit, requestParameters.offset, options).then((request) => request(this.axios, this.basePath)); } @@ -1694,7 +2146,7 @@ export class IntegratedSystemApi extends BaseAPI { * @throws {RequiredError} * @memberof IntegratedSystemApi */ - public integratedSystemPartialUpdate(requestParameters: IntegratedSystemApiIntegratedSystemPartialUpdateRequest, options?: AxiosRequestConfig) { + public integratedSystemPartialUpdate(requestParameters: IntegratedSystemApiIntegratedSystemPartialUpdateRequest, options?: RawAxiosRequestConfig) { return IntegratedSystemApiFp(this.configuration).integratedSystemPartialUpdate(requestParameters.id, requestParameters.PatchedIntegratedSystem, options).then((request) => request(this.axios, this.basePath)); } @@ -1705,7 +2157,7 @@ export class IntegratedSystemApi extends BaseAPI { * @throws {RequiredError} * @memberof IntegratedSystemApi */ - public integratedSystemRetrieve(requestParameters: IntegratedSystemApiIntegratedSystemRetrieveRequest, options?: AxiosRequestConfig) { + public integratedSystemRetrieve(requestParameters: IntegratedSystemApiIntegratedSystemRetrieveRequest, options?: RawAxiosRequestConfig) { return IntegratedSystemApiFp(this.configuration).integratedSystemRetrieve(requestParameters.id, options).then((request) => request(this.axios, this.basePath)); } @@ -1716,12 +2168,13 @@ export class IntegratedSystemApi extends BaseAPI { * @throws {RequiredError} * @memberof IntegratedSystemApi */ - public integratedSystemUpdate(requestParameters: IntegratedSystemApiIntegratedSystemUpdateRequest, options?: AxiosRequestConfig) { + public integratedSystemUpdate(requestParameters: IntegratedSystemApiIntegratedSystemUpdateRequest, options?: RawAxiosRequestConfig) { return IntegratedSystemApiFp(this.configuration).integratedSystemUpdate(requestParameters.id, requestParameters.IntegratedSystem, options).then((request) => request(this.axios, this.basePath)); } } + /** * ProductApi - axios parameter creator * @export @@ -1734,7 +2187,7 @@ export const ProductApiAxiosParamCreator = function (configuration?: Configurati * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productCreate: async (Product: Product, options: AxiosRequestConfig = {}): Promise => { + productCreate: async (Product: Product, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'Product' is not null or undefined assertParamExists('productCreate', 'Product', Product) const localVarPath = `/product/`; @@ -1771,7 +2224,7 @@ export const ProductApiAxiosParamCreator = function (configuration?: Configurati * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productDestroy: async (id: number, options: AxiosRequestConfig = {}): Promise => { + productDestroy: async (id: number, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('productDestroy', 'id', id) const localVarPath = `/product/{id}/` @@ -1809,7 +2262,7 @@ export const ProductApiAxiosParamCreator = function (configuration?: Configurati * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productList: async (limit?: number, name?: string, offset?: number, system__slug?: string, options: AxiosRequestConfig = {}): Promise => { + productList: async (limit?: number, name?: string, offset?: number, system__slug?: string, options: RawAxiosRequestConfig = {}): Promise => { const localVarPath = `/product/`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1858,7 +2311,7 @@ export const ProductApiAxiosParamCreator = function (configuration?: Configurati * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productPartialUpdate: async (id: number, PatchedProduct?: PatchedProduct, options: AxiosRequestConfig = {}): Promise => { + productPartialUpdate: async (id: number, PatchedProduct?: PatchedProduct, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('productPartialUpdate', 'id', id) const localVarPath = `/product/{id}/` @@ -1896,7 +2349,7 @@ export const ProductApiAxiosParamCreator = function (configuration?: Configurati * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productRetrieve: async (id: number, options: AxiosRequestConfig = {}): Promise => { + productRetrieve: async (id: number, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('productRetrieve', 'id', id) const localVarPath = `/product/{id}/` @@ -1932,7 +2385,7 @@ export const ProductApiAxiosParamCreator = function (configuration?: Configurati * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productUpdate: async (id: number, Product: Product, options: AxiosRequestConfig = {}): Promise => { + productUpdate: async (id: number, Product: Product, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('productUpdate', 'id', id) // verify required parameter 'Product' is not null or undefined @@ -1982,9 +2435,11 @@ export const ProductApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async productCreate(Product: Product, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async productCreate(Product: Product, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.productCreate(Product, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ProductApi.productCreate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for Product model. @@ -1992,9 +2447,11 @@ export const ProductApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async productDestroy(id: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async productDestroy(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.productDestroy(id, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ProductApi.productDestroy']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for Product model. @@ -2005,9 +2462,11 @@ export const ProductApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async productList(limit?: number, name?: string, offset?: number, system__slug?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async productList(limit?: number, name?: string, offset?: number, system__slug?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.productList(limit, name, offset, system__slug, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ProductApi.productList']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for Product model. @@ -2016,9 +2475,11 @@ export const ProductApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async productPartialUpdate(id: number, PatchedProduct?: PatchedProduct, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async productPartialUpdate(id: number, PatchedProduct?: PatchedProduct, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.productPartialUpdate(id, PatchedProduct, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ProductApi.productPartialUpdate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for Product model. @@ -2026,9 +2487,11 @@ export const ProductApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async productRetrieve(id: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async productRetrieve(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.productRetrieve(id, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ProductApi.productRetrieve']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, /** * Viewset for Product model. @@ -2037,9 +2500,11 @@ export const ProductApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async productUpdate(id: number, Product: Product, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async productUpdate(id: number, Product: Product, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.productUpdate(id, Product, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + const index = configuration?.serverIndex ?? 0; + const operationBasePath = operationServerMap['ProductApi.productUpdate']?.[index]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); }, } }; @@ -2057,7 +2522,7 @@ export const ProductApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productCreate(requestParameters: ProductApiProductCreateRequest, options?: AxiosRequestConfig): AxiosPromise { + productCreate(requestParameters: ProductApiProductCreateRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.productCreate(requestParameters.Product, options).then((request) => request(axios, basePath)); }, /** @@ -2066,7 +2531,7 @@ export const ProductApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productDestroy(requestParameters: ProductApiProductDestroyRequest, options?: AxiosRequestConfig): AxiosPromise { + productDestroy(requestParameters: ProductApiProductDestroyRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.productDestroy(requestParameters.id, options).then((request) => request(axios, basePath)); }, /** @@ -2075,7 +2540,7 @@ export const ProductApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productList(requestParameters: ProductApiProductListRequest = {}, options?: AxiosRequestConfig): AxiosPromise { + productList(requestParameters: ProductApiProductListRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.productList(requestParameters.limit, requestParameters.name, requestParameters.offset, requestParameters.system__slug, options).then((request) => request(axios, basePath)); }, /** @@ -2084,7 +2549,7 @@ export const ProductApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productPartialUpdate(requestParameters: ProductApiProductPartialUpdateRequest, options?: AxiosRequestConfig): AxiosPromise { + productPartialUpdate(requestParameters: ProductApiProductPartialUpdateRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.productPartialUpdate(requestParameters.id, requestParameters.PatchedProduct, options).then((request) => request(axios, basePath)); }, /** @@ -2093,7 +2558,7 @@ export const ProductApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productRetrieve(requestParameters: ProductApiProductRetrieveRequest, options?: AxiosRequestConfig): AxiosPromise { + productRetrieve(requestParameters: ProductApiProductRetrieveRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.productRetrieve(requestParameters.id, options).then((request) => request(axios, basePath)); }, /** @@ -2102,7 +2567,7 @@ export const ProductApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - productUpdate(requestParameters: ProductApiProductUpdateRequest, options?: AxiosRequestConfig): AxiosPromise { + productUpdate(requestParameters: ProductApiProductUpdateRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.productUpdate(requestParameters.id, requestParameters.Product, options).then((request) => request(axios, basePath)); }, }; @@ -2241,7 +2706,7 @@ export class ProductApi extends BaseAPI { * @throws {RequiredError} * @memberof ProductApi */ - public productCreate(requestParameters: ProductApiProductCreateRequest, options?: AxiosRequestConfig) { + public productCreate(requestParameters: ProductApiProductCreateRequest, options?: RawAxiosRequestConfig) { return ProductApiFp(this.configuration).productCreate(requestParameters.Product, options).then((request) => request(this.axios, this.basePath)); } @@ -2252,7 +2717,7 @@ export class ProductApi extends BaseAPI { * @throws {RequiredError} * @memberof ProductApi */ - public productDestroy(requestParameters: ProductApiProductDestroyRequest, options?: AxiosRequestConfig) { + public productDestroy(requestParameters: ProductApiProductDestroyRequest, options?: RawAxiosRequestConfig) { return ProductApiFp(this.configuration).productDestroy(requestParameters.id, options).then((request) => request(this.axios, this.basePath)); } @@ -2263,7 +2728,7 @@ export class ProductApi extends BaseAPI { * @throws {RequiredError} * @memberof ProductApi */ - public productList(requestParameters: ProductApiProductListRequest = {}, options?: AxiosRequestConfig) { + public productList(requestParameters: ProductApiProductListRequest = {}, options?: RawAxiosRequestConfig) { return ProductApiFp(this.configuration).productList(requestParameters.limit, requestParameters.name, requestParameters.offset, requestParameters.system__slug, options).then((request) => request(this.axios, this.basePath)); } @@ -2274,7 +2739,7 @@ export class ProductApi extends BaseAPI { * @throws {RequiredError} * @memberof ProductApi */ - public productPartialUpdate(requestParameters: ProductApiProductPartialUpdateRequest, options?: AxiosRequestConfig) { + public productPartialUpdate(requestParameters: ProductApiProductPartialUpdateRequest, options?: RawAxiosRequestConfig) { return ProductApiFp(this.configuration).productPartialUpdate(requestParameters.id, requestParameters.PatchedProduct, options).then((request) => request(this.axios, this.basePath)); } @@ -2285,7 +2750,7 @@ export class ProductApi extends BaseAPI { * @throws {RequiredError} * @memberof ProductApi */ - public productRetrieve(requestParameters: ProductApiProductRetrieveRequest, options?: AxiosRequestConfig) { + public productRetrieve(requestParameters: ProductApiProductRetrieveRequest, options?: RawAxiosRequestConfig) { return ProductApiFp(this.configuration).productRetrieve(requestParameters.id, options).then((request) => request(this.axios, this.basePath)); } @@ -2296,7 +2761,7 @@ export class ProductApi extends BaseAPI { * @throws {RequiredError} * @memberof ProductApi */ - public productUpdate(requestParameters: ProductApiProductUpdateRequest, options?: AxiosRequestConfig) { + public productUpdate(requestParameters: ProductApiProductUpdateRequest, options?: RawAxiosRequestConfig) { return ProductApiFp(this.configuration).productUpdate(requestParameters.id, requestParameters.Product, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/frontends/api/src/generated/base.ts b/frontends/api/src/generated/v0/base.ts similarity index 79% rename from frontends/api/src/generated/base.ts rename to frontends/api/src/generated/v0/base.ts index d524b79f..a5cca328 100644 --- a/frontends/api/src/generated/base.ts +++ b/frontends/api/src/generated/v0/base.ts @@ -16,7 +16,7 @@ import type { Configuration } from './configuration'; // Some imports not used depending on template conditions // @ts-ignore -import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios'; +import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios'; import globalAxios from 'axios'; export const BASE_PATH = "http://localhost".replace(/\/+$/, ""); @@ -39,7 +39,7 @@ export const COLLECTION_FORMATS = { */ export interface RequestArgs { url: string; - options: AxiosRequestConfig; + options: RawAxiosRequestConfig; } /** @@ -53,7 +53,7 @@ export class BaseAPI { constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) { if (configuration) { this.configuration = configuration; - this.basePath = configuration.basePath || this.basePath; + this.basePath = configuration.basePath ?? basePath; } } }; @@ -70,3 +70,17 @@ export class RequiredError extends Error { this.name = "RequiredError" } } + +interface ServerMap { + [key: string]: { + url: string, + description: string, + }[]; +} + +/** + * + * @export + */ +export const operationServerMap: ServerMap = { +} diff --git a/frontends/api/src/generated/common.ts b/frontends/api/src/generated/v0/common.ts similarity index 96% rename from frontends/api/src/generated/common.ts rename to frontends/api/src/generated/v0/common.ts index 0f86b2c8..b1f27a05 100644 --- a/frontends/api/src/generated/common.ts +++ b/frontends/api/src/generated/v0/common.ts @@ -144,7 +144,7 @@ export const toPathString = function (url: URL) { */ export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) { return >(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { - const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || basePath) + axiosArgs.url}; + const axiosRequestArgs = {...axiosArgs.options, url: (axios.defaults.baseURL ? '' : configuration?.basePath ?? basePath) + axiosArgs.url}; return axios.request(axiosRequestArgs); }; } diff --git a/frontends/api/src/generated/configuration.ts b/frontends/api/src/generated/v0/configuration.ts similarity index 94% rename from frontends/api/src/generated/configuration.ts rename to frontends/api/src/generated/v0/configuration.ts index 0dc39217..bbca9a31 100644 --- a/frontends/api/src/generated/configuration.ts +++ b/frontends/api/src/generated/v0/configuration.ts @@ -19,6 +19,7 @@ export interface ConfigurationParameters { password?: string; accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); basePath?: string; + serverIndex?: number; baseOptions?: any; formDataCtor?: new () => any; } @@ -58,6 +59,13 @@ export class Configuration { * @memberof Configuration */ basePath?: string; + /** + * override server index + * + * @type {number} + * @memberof Configuration + */ + serverIndex?: number; /** * base options for axios calls * @@ -80,6 +88,7 @@ export class Configuration { this.password = param.password; this.accessToken = param.accessToken; this.basePath = param.basePath; + this.serverIndex = param.serverIndex; this.baseOptions = param.baseOptions; this.formDataCtor = param.formDataCtor; } diff --git a/frontends/api/src/generated/git_push.sh b/frontends/api/src/generated/v0/git_push.sh similarity index 100% rename from frontends/api/src/generated/git_push.sh rename to frontends/api/src/generated/v0/git_push.sh diff --git a/frontends/api/src/generated/index.ts b/frontends/api/src/generated/v0/index.ts similarity index 100% rename from frontends/api/src/generated/index.ts rename to frontends/api/src/generated/v0/index.ts diff --git a/openapi/__init__.py b/openapi/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/openapi/apps.py b/openapi/apps.py new file mode 100644 index 00000000..bc3b31db --- /dev/null +++ b/openapi/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class OpenapiConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "openapi" diff --git a/openapi/exceptions.py b/openapi/exceptions.py new file mode 100644 index 00000000..de890d71 --- /dev/null +++ b/openapi/exceptions.py @@ -0,0 +1,5 @@ +"""OpenAPI exception""" + + +class EnumDescriptionError(Exception): + """Failed to compute a description""" diff --git a/openapi/hooks.py b/openapi/hooks.py new file mode 100644 index 00000000..29d81050 --- /dev/null +++ b/openapi/hooks.py @@ -0,0 +1,72 @@ +"""Extensions for OpenAPI schema""" + +import re + +from openapi.exceptions import EnumDescriptionError + +ENUM_DESCRIPTION_RE = re.compile(r"\w*\*\s`(?P.*)`\s\-\s(?P.*)") + + +def _iter_described_enums(schema, *, name=None, is_root=True): + """ + Create an iterator over all enums with descriptions + """ + if is_root: + for item_name, item in schema.items(): + yield from _iter_described_enums(item, name=item_name, is_root=False) + elif isinstance(schema, list): + for item in schema: + yield from _iter_described_enums(item, name=name, is_root=is_root) + elif isinstance(schema, dict): + if "enum" in schema and "description" in schema: + yield name, schema + + yield from _iter_described_enums( + schema.get("properties", []), name=name, is_root=is_root + ) + yield from _iter_described_enums( + schema.get("oneOf", []), name=name, is_root=is_root + ) + yield from _iter_described_enums( + schema.get("allOf", []), name=name, is_root=is_root + ) + yield from _iter_described_enums( + schema.get("anyOf", []), name=name, is_root=is_root + ) + + +def postprocess_x_enum_descriptions(result, generator, request, public): # noqa: ARG001 + """ + Take the drf-spectacular generated descriptions and + puts it into the x-enum-descriptions property. + """ + + # your modifications to the schema in parameter result + schemas = result.get("components", {}).get("schemas", {}) + + for name, schema in _iter_described_enums(schemas): + lines = schema["description"].splitlines() + descriptions_by_value = {} + for line in lines: + match = ENUM_DESCRIPTION_RE.match(line) + if match is None: + continue + + key = match["key"] + description = match["description"] + + # sometimes there are descriptions for empty values + # that aren't present in `"enums"` + if key in schema["enum"]: + descriptions_by_value[key] = description + + if len(descriptions_by_value.values()) != len(schema["enum"]): + msg = f"Unable to find descriptions for all enum values: {name}" + raise EnumDescriptionError(msg) + + if descriptions_by_value: + schema["x-enum-descriptions"] = [ + descriptions_by_value[value] for value in schema["enum"] + ] + + return result diff --git a/openapi/management/__init__.py b/openapi/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/openapi/management/commands/__init__.py b/openapi/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/openapi/management/commands/generate_openapi_spec.py b/openapi/management/commands/generate_openapi_spec.py new file mode 100644 index 00000000..ca0b0c4c --- /dev/null +++ b/openapi/management/commands/generate_openapi_spec.py @@ -0,0 +1,50 @@ +""" +Management command to generate OpenAPI specs from our APIs. +""" + +from pathlib import Path + +from django.conf import settings +from django.core import management +from django.core.management import BaseCommand + + +class Command(BaseCommand): + """Generate OpenAPI specs for our APIs.""" + + help = "Generate OpenAPI specs for our APIs." + + def add_arguments(self, parser): + """Add arguments to the command""" + + parser.add_argument( + "--directory", + dest="directory", + default="openapi/specs/", + help="Directory into which output is written", + ) + parser.add_argument( + "--fail-on-warn", + dest="fail-on-warn", + action="store_true", + default=False, + help="Fail the command if there are any warnings", + ) + + super().add_arguments(parser) + + def handle(self, **options): + """Run the command""" + + directory = options["directory"] + for version in settings.REST_FRAMEWORK["ALLOWED_VERSIONS"]: + filename = version + ".yaml" + filepath = Path(directory) / filename + management.call_command( + "spectacular", + urlconf="unified_ecommerce.urls", + file=filepath, + validate=True, + api_version=version, + fail_on_warn=options["fail-on-warn"], + ) diff --git a/unified_ecommerce/settings_spectacular.py b/openapi/settings_spectacular.py similarity index 52% rename from unified_ecommerce/settings_spectacular.py rename to openapi/settings_spectacular.py index abc56ce9..8c0030e0 100644 --- a/unified_ecommerce/settings_spectacular.py +++ b/openapi/settings_spectacular.py @@ -1,6 +1,5 @@ """ Django settings specific to DRF Spectacular -to offload from the main settings.py """ open_spectacular_settings = { @@ -8,7 +7,13 @@ "DESCRIPTION": "MIT public API", "VERSION": "0.0.1", "SERVE_INCLUDE_SCHEMA": False, - "SERVE_URLCONF": "unified_ecommerce.urls_spectacular", + "SERVE_URLCONF": "unified_ecommerce.urls", "ENUM_GENERATE_CHOICE_DESCRIPTION": True, "COMPONENT_SPLIT_REQUEST": True, + "AUTHENTICATION_WHITELIST": [], + "SCHEMA_PATH_PREFIX": "/api/v[0-9]", + "POSTPROCESSING_HOOKS": [ + "drf_spectacular.hooks.postprocess_schema_enums", + "openapi.hooks.postprocess_x_enum_descriptions", + ], } diff --git a/openapi/specs/v0.yaml b/openapi/specs/v0.yaml new file mode 100644 index 00000000..4d093f26 --- /dev/null +++ b/openapi/specs/v0.yaml @@ -0,0 +1,1067 @@ +openapi: 3.0.3 +info: + title: MIT OL Unified Ecommerce API + version: 0.0.1 (v0) + description: MIT public API +paths: + /api/v0/meta/integrated_system/: + get: + operationId: meta_integrated_system_list + description: Viewset for IntegratedSystem model. + parameters: + - name: limit + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: offset + required: false + in: query + description: The initial index from which to return the results. + schema: + type: integer + tags: + - meta + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedIntegratedSystemList' + description: '' + post: + operationId: meta_integrated_system_create + description: Viewset for IntegratedSystem model. + tags: + - meta + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IntegratedSystemRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/IntegratedSystemRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/IntegratedSystemRequest' + required: true + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/IntegratedSystem' + description: '' + /api/v0/meta/integrated_system/{id}/: + get: + operationId: meta_integrated_system_retrieve + description: Viewset for IntegratedSystem model. + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this integrated system. + required: true + tags: + - meta + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/IntegratedSystem' + description: '' + put: + operationId: meta_integrated_system_update + description: Viewset for IntegratedSystem model. + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this integrated system. + required: true + tags: + - meta + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IntegratedSystemRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/IntegratedSystemRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/IntegratedSystemRequest' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/IntegratedSystem' + description: '' + patch: + operationId: meta_integrated_system_partial_update + description: Viewset for IntegratedSystem model. + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this integrated system. + required: true + tags: + - meta + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedIntegratedSystemRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PatchedIntegratedSystemRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/PatchedIntegratedSystemRequest' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/IntegratedSystem' + description: '' + delete: + operationId: meta_integrated_system_destroy + description: Viewset for IntegratedSystem model. + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this integrated system. + required: true + tags: + - meta + responses: + '204': + description: No response body + /api/v0/meta/product/: + get: + operationId: meta_product_list + description: Viewset for Product model. + parameters: + - name: limit + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - in: query + name: name + schema: + type: string + - name: offset + required: false + in: query + description: The initial index from which to return the results. + schema: + type: integer + - in: query + name: system__slug + schema: + type: string + tags: + - meta + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedProductList' + description: '' + post: + operationId: meta_product_create + description: Viewset for Product model. + tags: + - meta + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProductRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ProductRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/ProductRequest' + required: true + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/Product' + description: '' + /api/v0/meta/product/{id}/: + get: + operationId: meta_product_retrieve + description: Viewset for Product model. + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this product. + required: true + tags: + - meta + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Product' + description: '' + put: + operationId: meta_product_update + description: Viewset for Product model. + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this product. + required: true + tags: + - meta + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProductRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ProductRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/ProductRequest' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Product' + description: '' + patch: + operationId: meta_product_partial_update + description: Viewset for Product model. + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this product. + required: true + tags: + - meta + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedProductRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PatchedProductRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/PatchedProductRequest' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Product' + description: '' + delete: + operationId: meta_product_destroy + description: Viewset for Product model. + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this product. + required: true + tags: + - meta + responses: + '204': + description: No response body + /api/v0/payments/baskets/: + get: + operationId: payments_baskets_list + description: API view set for Basket + parameters: + - name: limit + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: offset + required: false + in: query + description: The initial index from which to return the results. + schema: + type: integer + tags: + - payments + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedBasketList' + description: '' + /api/v0/payments/baskets/{basket}/items/: + get: + operationId: payments_baskets_items_list + description: API view set for BasketItem + parameters: + - in: path + name: basket + schema: + type: string + required: true + - name: limit + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: offset + required: false + in: query + description: The initial index from which to return the results. + schema: + type: integer + tags: + - payments + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedBasketItemList' + description: '' + post: + operationId: payments_baskets_items_create + description: |- + Create a new basket item. + + Args: + request (HttpRequest): HTTP request + + Returns: + Response: HTTP response + parameters: + - in: path + name: basket + schema: + type: string + required: true + - in: query + name: product + schema: + type: integer + tags: + - payments + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BasketItemRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/BasketItemRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/BasketItemRequest' + required: true + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/BasketItem' + description: '' + /api/v0/payments/baskets/{basket}/items/{id}/: + delete: + operationId: payments_baskets_items_destroy + description: API view set for BasketItem + parameters: + - in: path + name: basket + schema: + type: string + required: true + - in: path + name: id + schema: + type: string + required: true + tags: + - payments + responses: + '204': + description: No response body + /api/v0/payments/baskets/{username}/: + get: + operationId: payments_baskets_retrieve + description: API view set for Basket + parameters: + - in: path + name: username + schema: + type: string + required: true + tags: + - payments + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Basket' + description: '' + /api/v0/payments/baskets/clear/: + delete: + operationId: payments_baskets_clear_destroy + description: |- + Clear the basket for the current user. + + Returns: + Response: HTTP response + tags: + - payments + responses: + '204': + description: No response body + /api/v0/payments/baskets/create_from_product/{system_slug}/{sku}/: + post: + operationId: payments_baskets_create_from_product_create + description: |- + Create a new basket item from a product for the currently logged in user. Reuse + the existing basket object if it exists. + + If the checkout flag is set in the POST data, then this will create the + basket, then immediately flip the user to the checkout interstitial (which + then redirects to the payment gateway). + + Args: + system_slug (str): system slug + sku (str): product slug + + POST Args: + quantity (int): quantity of the product to add to the basket (defaults to 1) + checkout (bool): redirect to checkout interstitial (defaults to False) + + Returns: + Response: HTTP response + parameters: + - in: path + name: sku + schema: + type: string + required: true + - in: path + name: system_slug + schema: + type: string + required: true + tags: + - payments + responses: + '200': + description: No response body + /api/v0/payments/checkout/callback/: + post: + operationId: payments_checkout_callback_create + description: |- + Handle webhook call from the payment gateway when the user has + completed a transaction. + + Returns: + - HTTP_200_OK if the Order is found. + + Raises: + - Http404 if the Order is not found. + tags: + - payments + responses: + '200': + content: + application/json: + schema: + type: object + additionalProperties: {} + description: Unspecified response body + description: '' + /api/v0/payments/checkout/start_checkout/: + post: + operationId: payments_checkout_start_checkout_create + description: |- + Start the checkout process. This assembles the basket items + into an Order with Lines for each item, applies the attached basket + discounts, and then calls the payment gateway to prepare for payment. + + This is expected to be called from within the Ecommerce cart app, not + from an integrated system. + + Returns: + - JSON payload from the ol-django payment gateway app. The payment + gateway returns data necessary to construct a form that will + ultimately POST to the actual payment processor. + tags: + - payments + responses: + '200': + description: No response body + /api/v0/payments/orders/history/: + get: + operationId: payments_orders_history_list + description: Provides APIs for displaying the users's order history. + parameters: + - name: limit + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: offset + required: false + in: query + description: The initial index from which to return the results. + schema: + type: integer + tags: + - payments + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedOrderHistoryList' + description: '' + /api/v0/payments/orders/history/{id}/: + get: + operationId: payments_orders_history_retrieve + description: Provides APIs for displaying the users's order history. + parameters: + - in: path + name: id + schema: + type: string + required: true + tags: + - payments + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/OrderHistory' + description: '' +components: + schemas: + Basket: + type: object + description: Basket model serializer + properties: + id: + type: integer + readOnly: true + user: + type: integer + basket_items: + type: string + readOnly: true + required: + - basket_items + - id + - user + BasketItem: + type: object + description: BasketItem model serializer + properties: + basket: + type: integer + product: + type: integer + id: + type: integer + readOnly: true + required: + - basket + - id + - product + BasketItemRequest: + type: object + description: BasketItem model serializer + properties: + basket: + type: integer + product: + type: integer + required: + - basket + - product + IntegratedSystem: + type: object + description: Serializer for IntegratedSystem model. + properties: + id: + type: integer + readOnly: true + name: + type: string + maxLength: 255 + slug: + type: string + nullable: true + maxLength: 80 + description: + type: string + required: + - id + - name + IntegratedSystemRequest: + type: object + description: Serializer for IntegratedSystem model. + properties: + name: + type: string + minLength: 1 + maxLength: 255 + slug: + type: string + nullable: true + maxLength: 80 + description: + type: string + required: + - name + Line: + type: object + description: Serializes a line item for an order. + properties: + id: + type: integer + readOnly: true + quantity: + type: integer + maximum: 2147483647 + minimum: 0 + item_description: + type: string + readOnly: true + unit_price: + type: string + format: decimal + pattern: ^-?\d{0,7}(?:\.\d{0,2})?$ + total_price: + type: string + format: decimal + pattern: ^-?\d{0,7}(?:\.\d{0,2})?$ + product: + $ref: '#/components/schemas/Product' + required: + - id + - item_description + - product + - quantity + - total_price + - unit_price + Nested: + type: object + properties: + id: + type: integer + readOnly: true + password: + type: string + maxLength: 128 + last_login: + type: string + format: date-time + nullable: true + is_superuser: + type: boolean + title: Superuser status + description: Designates that this user has all permissions without explicitly + assigning them. + username: + type: string + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + pattern: ^[\w.@+-]+$ + maxLength: 150 + first_name: + type: string + maxLength: 150 + last_name: + type: string + maxLength: 150 + email: + type: string + format: email + title: Email address + maxLength: 254 + is_staff: + type: boolean + title: Staff status + description: Designates whether the user can log into this admin site. + is_active: + type: boolean + title: Active + description: Designates whether this user should be treated as active. Unselect + this instead of deleting accounts. + date_joined: + type: string + format: date-time + groups: + type: array + items: + type: integer + description: The groups this user belongs to. A user will get all permissions + granted to each of their groups. + user_permissions: + type: array + items: + type: integer + description: Specific permissions for this user. + required: + - id + - password + - username + OrderHistory: + type: object + description: Serializer for order history. + properties: + id: + type: integer + readOnly: true + state: + $ref: '#/components/schemas/StateEnum' + reference_number: + type: string + maxLength: 255 + purchaser: + allOf: + - $ref: '#/components/schemas/Nested' + readOnly: true + total_price_paid: + type: string + format: decimal + pattern: ^-?\d{0,15}(?:\.\d{0,5})?$ + lines: + type: array + items: + $ref: '#/components/schemas/Line' + created_on: + type: string + format: date-time + readOnly: true + updated_on: + type: string + format: date-time + readOnly: true + required: + - created_on + - id + - lines + - purchaser + - total_price_paid + - updated_on + PaginatedBasketItemList: + type: object + required: + - count + - results + properties: + count: + type: integer + example: 123 + next: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=400&limit=100 + previous: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=200&limit=100 + results: + type: array + items: + $ref: '#/components/schemas/BasketItem' + PaginatedBasketList: + type: object + required: + - count + - results + properties: + count: + type: integer + example: 123 + next: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=400&limit=100 + previous: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=200&limit=100 + results: + type: array + items: + $ref: '#/components/schemas/Basket' + PaginatedIntegratedSystemList: + type: object + required: + - count + - results + properties: + count: + type: integer + example: 123 + next: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=400&limit=100 + previous: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=200&limit=100 + results: + type: array + items: + $ref: '#/components/schemas/IntegratedSystem' + PaginatedOrderHistoryList: + type: object + required: + - count + - results + properties: + count: + type: integer + example: 123 + next: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=400&limit=100 + previous: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=200&limit=100 + results: + type: array + items: + $ref: '#/components/schemas/OrderHistory' + PaginatedProductList: + type: object + required: + - count + - results + properties: + count: + type: integer + example: 123 + next: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=400&limit=100 + previous: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=200&limit=100 + results: + type: array + items: + $ref: '#/components/schemas/Product' + PatchedIntegratedSystemRequest: + type: object + description: Serializer for IntegratedSystem model. + properties: + name: + type: string + minLength: 1 + maxLength: 255 + slug: + type: string + nullable: true + maxLength: 80 + description: + type: string + PatchedProductRequest: + type: object + description: Serializer for Product model. + properties: + sku: + type: string + minLength: 1 + description: SKU of the product. + maxLength: 255 + name: + type: string + minLength: 1 + description: Short name of the product, displayed in carts/etc. + maxLength: 255 + price: + type: string + format: decimal + pattern: ^-?\d{0,5}(?:\.\d{0,2})?$ + description: Price (decimal to two places) + description: + type: string + minLength: 1 + description: Long description of the product. + system_data: + nullable: true + description: System-specific data for the product (in JSON). + system: + type: integer + description: Owner system of the product. + Product: + type: object + description: Serializer for Product model. + properties: + id: + type: integer + readOnly: true + deleted_on: + type: string + format: date-time + readOnly: true + nullable: true + deleted_by_cascade: + type: boolean + readOnly: true + created_on: + type: string + format: date-time + readOnly: true + updated_on: + type: string + format: date-time + readOnly: true + sku: + type: string + description: SKU of the product. + maxLength: 255 + name: + type: string + description: Short name of the product, displayed in carts/etc. + maxLength: 255 + price: + type: string + format: decimal + pattern: ^-?\d{0,5}(?:\.\d{0,2})?$ + description: Price (decimal to two places) + description: + type: string + description: Long description of the product. + system_data: + nullable: true + description: System-specific data for the product (in JSON). + system: + type: integer + description: Owner system of the product. + required: + - created_on + - deleted_by_cascade + - deleted_on + - description + - id + - name + - price + - sku + - system + - updated_on + ProductRequest: + type: object + description: Serializer for Product model. + properties: + sku: + type: string + minLength: 1 + description: SKU of the product. + maxLength: 255 + name: + type: string + minLength: 1 + description: Short name of the product, displayed in carts/etc. + maxLength: 255 + price: + type: string + format: decimal + pattern: ^-?\d{0,5}(?:\.\d{0,2})?$ + description: Price (decimal to two places) + description: + type: string + minLength: 1 + description: Long description of the product. + system_data: + nullable: true + description: System-specific data for the product (in JSON). + system: + type: integer + description: Owner system of the product. + required: + - description + - name + - price + - sku + - system + StateEnum: + enum: + - pending + - fulfilled + - canceled + - refunded + - declined + - errored + - review + type: string + description: |- + * `pending` - Pending + * `fulfilled` - Fulfilled + * `canceled` - Canceled + * `refunded` - Refunded + * `declined` - Declined + * `errored` - Errored + * `review` - Review + x-enum-descriptions: + - Pending + - Fulfilled + - Canceled + - Refunded + - Declined + - Errored + - Review diff --git a/openapi/urls.py b/openapi/urls.py new file mode 100644 index 00000000..5b90b786 --- /dev/null +++ b/openapi/urls.py @@ -0,0 +1,26 @@ +""" +URL Configuration for schema & documentation views +""" + +from django.urls import path +from drf_spectacular.views import ( + SpectacularAPIView, + SpectacularRedocView, + SpectacularSwaggerView, +) + +urlpatterns = [ + path( + "api/v0/schema/", SpectacularAPIView.as_view(api_version="v0"), name="v0_schema" + ), + path( + "api/v0/schema/swagger-ui/", + SpectacularSwaggerView.as_view(url_name="v0_schema"), + name="v0_swagger_ui", + ), + path( + "api/v0/schema/redoc/", + SpectacularRedocView.as_view(url_name="v0_schema"), + name="v0_redoc", + ), +] diff --git a/payments/models.py b/payments/models.py index 919825cb..e9568627 100644 --- a/payments/models.py +++ b/payments/models.py @@ -4,6 +4,7 @@ import logging import re import uuid +from decimal import Decimal from django.conf import settings from django.contrib.auth import get_user_model @@ -554,27 +555,27 @@ class Meta: ] @property - def item_description(self): + def item_description(self) -> str: """Return the item description""" return self.product_version.field_dict["description"] @property - def unit_price(self): + def unit_price(self) -> Decimal: """Return the price of the product""" return self.product_version.field_dict["price"] @cached_property - def total_price(self): + def total_price(self) -> Decimal: """Return the price of the product""" return self.unit_price * self.quantity @cached_property - def discounted_price(self): + def discounted_price(self) -> Decimal: """Return the price of the product with discounts""" return self.total_price @cached_property - def product(self): + def product(self) -> Product: """Return the product associated with the line""" return Product.resolve_product_version( Product.all_objects.get(pk=self.product_version.field_dict["id"]), diff --git a/payments/serializers/v0/__init__.py b/payments/serializers/v0/__init__.py index ad084f2b..2009e3c7 100644 --- a/payments/serializers/v0/__init__.py +++ b/payments/serializers/v0/__init__.py @@ -1,8 +1,10 @@ """Serializers for payments.""" from dataclasses import dataclass +from decimal import Decimal from django.contrib.auth import get_user_model +from drf_spectacular.utils import extend_schema_field from rest_framework import serializers from rest_framework_dataclasses.serializers import DataclassSerializer @@ -58,24 +60,6 @@ class WebhookBase: class BasketItemSerializer(serializers.ModelSerializer): """BasketItem model serializer""" - def perform_create(self, validated_data): - """ - Create a BasketItem instance based on the validated data. - - Args: - validated_data (dict): The validated data with which to create the - BasketIteminstance. - - Returns: - BasketItem: The created BasketItem instance. - """ - - basket = Basket.objects.get(user=validated_data["user"]) - # Product queryset returns active Products by default - product = Product.objects.get(id=validated_data["product"]) - item, _ = BasketItem.objects.get_or_create(basket=basket, product=product) - return item - class Meta: """Meta options for BasketItemSerializer""" @@ -92,7 +76,8 @@ class BasketSerializer(serializers.ModelSerializer): basket_items = serializers.SerializerMethodField() - def get_basket_items(self, instance): + @extend_schema_field(BasketItemSerializer(many=True)) + def get_basket_items(self, instance: Basket) -> list[BasketItemSerializer]: """Get items in the basket""" return [ BasketItemSerializer(instance=basket, context=self.context).data @@ -115,7 +100,7 @@ class BasketItemWithProductSerializer(serializers.ModelSerializer): product = serializers.SerializerMethodField() - def get_product(self, instance): + def get_product(self, instance) -> ProductSerializer: """Get the product associated with the basket item""" return ProductSerializer(instance=instance.product, context=self.context).data @@ -135,14 +120,14 @@ class BasketWithProductSerializer(serializers.ModelSerializer): discounted_price = serializers.SerializerMethodField() discounts = serializers.SerializerMethodField() - def get_basket_items(self, instance): + def get_basket_items(self, instance) -> list[BasketItemWithProductSerializer]: """Get the items in the basket""" return [ BasketItemWithProductSerializer(instance=basket, context=self.context).data for basket in instance.basket_items.all() ] - def get_total_price(self, instance): + def get_total_price(self, instance) -> Decimal: """Get the total price for the basket""" return sum( basket_item.base_price for basket_item in instance.basket_items.all() @@ -222,9 +207,13 @@ class Meta: class OrderHistorySerializer(serializers.ModelSerializer): + """Serializer for order history.""" + lines = LineSerializer(many=True) class Meta: + """Meta options for OrderHistorySerializer""" + fields = [ "id", "state", diff --git a/payments/urls.py b/payments/urls.py index 1cc72f03..0dc0eb24 100644 --- a/payments/urls.py +++ b/payments/urls.py @@ -1,5 +1,9 @@ """URLs for the payments app.""" +from django.urls import include, re_path + from payments.views.v0.urls import urlpatterns as v0_urls -urlpatterns = v0_urls +urlpatterns = [ + re_path(r"^api/v0/payments/", include((v0_urls, "v0"))), +] diff --git a/payments/views/v0/__init__.py b/payments/views/v0/__init__.py index 96d36718..d34bdd22 100644 --- a/payments/views/v0/__init__.py +++ b/payments/views/v0/__init__.py @@ -8,6 +8,7 @@ from django.shortcuts import redirect from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt +from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema from rest_framework import mixins, status from rest_framework.decorators import action, api_view, permission_classes from rest_framework.generics import ListCreateAPIView @@ -105,9 +106,19 @@ def create(self, request): ) +@extend_schema( + description=( + "Creates or updates a basket for the current user, " + "adding the selected product." + ), + auth=IsAuthenticated, + methods=["POST"], + request=None, + responses=BasketSerializer, +) @api_view(["POST"]) @permission_classes([IsAuthenticated]) -def create_basket_from_product(request, system_slug, sku): +def create_basket_from_product(request, system_slug: str, sku: str): """ Create a new basket item from a product for the currently logged in user. Reuse the existing basket object if it exists. @@ -153,6 +164,13 @@ def create_basket_from_product(request, system_slug, sku): ) +@extend_schema( + description="Clears the basket for the current user.", + auth=IsAuthenticated, + methods=["DELETE"], + versions=["v0"], + responses=OpenApiResponse(Response(None, status=status.HTTP_204_NO_CONTENT)), +) @api_view(["DELETE"]) @permission_classes([IsAuthenticated]) def clear_basket(request): @@ -173,10 +191,16 @@ def clear_basket(request): class CheckoutApiViewSet(ViewSet): - """Handles checkout.""" + """ + Handles checkout. + + This is excluded from the APIs, but we may want to have this return a proper + API response at some point. + """ permission_classes = (IsAuthenticated,) + @extend_schema(exclude=True) @action( detail=False, methods=["post"], name="Start Checkout", url_name="start_checkout" ) @@ -212,6 +236,7 @@ class BackofficeCallbackView(APIView): authentication_classes = [] # disables authentication permission_classes = [] # disables permission + @extend_schema(exclude=True) def post(self, request): """ Handle webhook call from the payment gateway when the user has @@ -239,11 +264,20 @@ def post(self, request): return Response(status=status.HTTP_200_OK) +@extend_schema( + request=None, + responses=OrderHistorySerializer, + parameters=[OpenApiParameter(name="id", type=int, location=OpenApiParameter.PATH)], +) class OrderHistoryViewSet(ReadOnlyModelViewSet): + """Provides APIs for displaying the users's order history.""" + serializer_class = OrderHistorySerializer permission_classes = [IsAuthenticated] def get_queryset(self): + """Return the queryset for completed orders.""" + return ( Order.objects.filter(purchaser=self.request.user) .filter(state__in=[Order.STATE.FULFILLED, Order.STATE.REFUNDED]) diff --git a/payments/views/v0/urls.py b/payments/views/v0/urls.py index 0929c960..327af3ee 100644 --- a/payments/views/v0/urls.py +++ b/payments/views/v0/urls.py @@ -4,7 +4,6 @@ from payments.views.v0 import ( BackofficeCallbackView, - BasketItemViewSet, BasketViewSet, CheckoutApiViewSet, OrderHistoryViewSet, @@ -16,12 +15,6 @@ router = SimpleRouterWithNesting() basket_router = router.register(r"baskets", BasketViewSet, basename="basket") -basket_router.register( - r"items", - BasketItemViewSet, - basename="basket-items", - parents_query_lookups=["basket"], -) router.register(r"orders/history", OrderHistoryViewSet, basename="orderhistory_api") diff --git a/scripts/generate_openapi.sh b/scripts/generate_openapi.sh index 7ea214ee..562cc3db 100755 --- a/scripts/generate_openapi.sh +++ b/scripts/generate_openapi.sh @@ -10,21 +10,18 @@ fi # Generate OpenAPI Schema ################################################## docker compose run --no-deps --rm web \ - ./manage.py spectacular \ - --urlconf unified_ecommerce.urls_spectacular \ - --file ./openapi.yaml \ - --validate + ./manage.py generate_openapi_spec ################################################## # Generate API Client ################################################## -GENERATOR_VERSION=v6.6.0 +GENERATOR_VERSION=v7.2.0 docker run --rm -v "${PWD}:/local" -w /local openapitools/openapi-generator-cli:${GENERATOR_VERSION} \ - generate -c scripts/openapi-configs/typescript-axios.yaml + generate -c scripts/openapi-configs/typescript-axios-v0.yaml # We expect pre-commit to exit with a non-zero status since it is reformatting # the generated code. -git ls-files frontends/api/src/generated | xargs pre-commit run --files openapi.yaml || +git ls-files frontends/api/src/generated | xargs pre-commit run --files || echo "OpenAPI generation complete." diff --git a/scripts/openapi-configs/templates/modelEnum.mustache b/scripts/openapi-configs/templates/modelEnum.mustache new file mode 100644 index 00000000..0d5e2798 --- /dev/null +++ b/scripts/openapi-configs/templates/modelEnum.mustache @@ -0,0 +1,25 @@ +/** + * {{{description}}} + * @export + * @enum {string} + */ +{{#isBoolean}} +export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}} +{{/isBoolean}} + +export const {{classname}}Descriptions = { +{{#allowableValues}} + {{#enumVars}} + {{{value}}}: "{{{enumDescription}}}", + {{/enumVars}} +{{/allowableValues}} +} as const; + +{{^isBoolean}} +{{^stringEnums}} +{{>modelObjectEnum}} +{{/stringEnums}} +{{#stringEnums}} +{{>modelStringEnum}} +{{/stringEnums}} +{{/isBoolean}} diff --git a/scripts/openapi-configs/typescript-axios.yaml b/scripts/openapi-configs/typescript-axios-v0.yaml similarity index 64% rename from scripts/openapi-configs/typescript-axios.yaml rename to scripts/openapi-configs/typescript-axios-v0.yaml index c94b0ecc..38e149e1 100644 --- a/scripts/openapi-configs/typescript-axios.yaml +++ b/scripts/openapi-configs/typescript-axios-v0.yaml @@ -1,7 +1,9 @@ generatorName: typescript-axios -outputDir: frontends/api/src/generated +outputDir: frontends/api/src/generated/v0 inputSpec: openapi.yaml ignoreFileOverride: frontends/api/.openapi-generator-ignore +templateDir: scripts/openapi-configs/templates additionalProperties: paramNaming: original useSingleRequestParameter: true + supportsES6: false diff --git a/scripts/test/openapi_spec_check.sh b/scripts/test/openapi_spec_check.sh index 188fce71..08bae8c3 100755 --- a/scripts/test/openapi_spec_check.sh +++ b/scripts/test/openapi_spec_check.sh @@ -1,11 +1,13 @@ #!/usr/bin/env bash -TMPFILE=$(mktemp) +set -eo pipefail -./manage.py spectacular \ - --urlconf=unified_ecommerce.urls_spectacular \ - --file $TMPFILE +TMPDIR="$(mktemp -d)" +SPECS_DIR=./openapi/specs/ -diff $TMPFILE ./openapi.yaml +./manage.py generate_openapi_spec \ + --directory=$TMPDIR --fail-on-warn + +diff $TMPDIR $SPECS_DIR if [ $? -eq 0 ]; then echo "OpenAPI spec is up to date!" diff --git a/system_meta/urls.py b/system_meta/urls.py index d486c020..ff9c8e39 100644 --- a/system_meta/urls.py +++ b/system_meta/urls.py @@ -8,11 +8,15 @@ ProductViewSet, ) -router = routers.DefaultRouter() +v0_router = routers.DefaultRouter() -router.register(r"integrated_system", IntegratedSystemViewSet) -router.register(r"product", ProductViewSet) +v0_router.register( + r"^meta/integrated_system", + IntegratedSystemViewSet, + basename="meta_integratedsystems_api", +) +v0_router.register(r"^meta/product", ProductViewSet, basename="meta_products_api") urlpatterns = [ - re_path("^", include(router.urls)), + re_path("^api/v0/", include((v0_router.urls, "v0"))), ] diff --git a/unified_ecommerce/permissions.py b/unified_ecommerce/permissions.py index 1c30574b..6839803c 100644 --- a/unified_ecommerce/permissions.py +++ b/unified_ecommerce/permissions.py @@ -12,9 +12,6 @@ def has_permission(self, request, view): # noqa: ARG002 or if the user is logged in. Otherwise, return False. """ - if request.method in permissions.SAFE_METHODS or ( + return request.method in permissions.SAFE_METHODS or ( request.user.is_authenticated and request.user.is_staff - ): - return True - - return False + ) diff --git a/unified_ecommerce/settings.py b/unified_ecommerce/settings.py index 071a5e6a..6a7ffa41 100644 --- a/unified_ecommerce/settings.py +++ b/unified_ecommerce/settings.py @@ -22,6 +22,7 @@ from django.core.exceptions import ImproperlyConfigured from mitol.common.envs import get_bool, get_int, get_string, import_settings_modules +from openapi.settings_spectacular import open_spectacular_settings from unified_ecommerce.envs import get_list_of_str from unified_ecommerce.sentry import init_sentry from unified_ecommerce.settings_celery import * # noqa: F403 @@ -97,6 +98,7 @@ "payments", "cart", "mitol.payment_gateway.apps.PaymentGatewayApp", + "openapi", ] MIDDLEWARE = [ @@ -437,7 +439,11 @@ "rest_framework.renderers.MultiPartRenderer", ], "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", + "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.NamespaceVersioning", "ORDERING_PARAM": "sortby", + "ALLOWED_VERSIONS": [ + "v0", + ], } USE_X_FORWARDED_PORT = get_bool("USE_X_FORWARDED_PORT", False) # noqa: FBT003 @@ -479,3 +485,5 @@ KEYCLOAK_REALM = get_string("KEYCLOAK_REALM", False) # noqa: FBT003 KEYCLOAK_ADMIN_URL = get_string("KEYCLOAK_ADMIN_URL", False) # noqa: FBT003 KEYCLOAK_ADMIN_SECURE = get_bool("KEYCLOAK_ADMIN_SECURE", True) # noqa: FBT003 + +SPECTACULAR_SETTINGS = open_spectacular_settings diff --git a/unified_ecommerce/urls.py b/unified_ecommerce/urls.py index 9c9f7ad6..47497d80 100644 --- a/unified_ecommerce/urls.py +++ b/unified_ecommerce/urls.py @@ -20,36 +20,21 @@ from django.conf.urls.static import static from django.contrib import admin from django.urls import include, path, re_path -from drf_spectacular.views import ( - SpectacularAPIView, - SpectacularRedocView, - SpectacularSwaggerView, -) urlpatterns = [ path("", include("cart.urls")), path("", include("django.contrib.auth.urls")), path("admin/", admin.site.urls), path("hijack/", include("hijack.urls")), - path("api/schema/", SpectacularAPIView.as_view(), name="schema"), - # Optional UI: - path( - "api/schema/swagger-ui/", - SpectacularSwaggerView.as_view(url_name="schema"), - name="swagger-ui", - ), - path( - "api/schema/redoc/", - SpectacularRedocView.as_view(url_name="schema"), - name="redoc", - ), # OAuth2 Paths path("o/", include("oauth2_provider.urls", namespace="oauth2_provider")), # App Paths - re_path(r"^api/v0/meta/", include("system_meta.urls")), + re_path(r"", include("openapi.urls")), # Private Paths re_path(r"^_/v0/meta/", include("system_meta.private_urls")), - re_path(r"^api/v0/payments/", include("payments.urls")), + # API Paths + re_path(r"", include("payments.urls")), + re_path(r"", include("system_meta.urls")), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) if settings.DEBUG: diff --git a/unified_ecommerce/urls_spectacular.py b/unified_ecommerce/urls_spectacular.py deleted file mode 100644 index 3540b646..00000000 --- a/unified_ecommerce/urls_spectacular.py +++ /dev/null @@ -1,8 +0,0 @@ -"""project URL Configuration""" - -from django.urls import include, re_path - -urlpatterns = [ - re_path(r"", include("system_meta.urls")), - re_path(r"^api/v0/payments/", include("payments.urls")), -] diff --git a/unified_ecommerce/viewsets.py b/unified_ecommerce/viewsets.py index 32de394e..5e026da9 100644 --- a/unified_ecommerce/viewsets.py +++ b/unified_ecommerce/viewsets.py @@ -32,8 +32,6 @@ def get_serializer_class(self): if hasattr(self, "request") and ( self.request.user.is_staff or self.request.user.is_superuser ): - log.debug("get_serializer_class returning the Admin one") return self.read_write_serializer_class - log.debug("get_serializer_class returning the regular one") return self.read_only_serializer_class