diff --git a/README.md b/README.md index 3449d2a..f3f3912 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ Use these annotations to allow the tool to authenticate automatically: - `x-act-auth-field`: Defines the relevant fields for authentication and must be set to one of the following valid types: | Type | Description | - |--------------|------------------------------------------------------------------------------------------------------| + | ------------ | ---------------------------------------------------------------------------------------------------- | | `identifier` | Specifies the field in the request body that contains the user identifier (e.g., username or email). | | `password` | Defines the field in the request body that holds the user's password. | | `token` | Specifies the field in the response body where the authentication token is returned. | diff --git a/demo-application/public/openapi.yml b/demo-application/public/openapi.yml index 24d19df..ee96b41 100644 --- a/demo-application/public/openapi.yml +++ b/demo-application/public/openapi.yml @@ -209,6 +209,52 @@ paths: security: - bearerHttpAuthentication: [ ] - cookieAuthentication: [ ] + /admin/usersByQueryString: + get: + summary: Einzelner Benutzer + description: Gibt einen spezifischen Benutzer anhand der ID zurück. + parameters: + - name: id + in: query + required: true + description: User-ID + schema: + type: integer + example: 1 + x-act: + resource-name: User + resource-access: read + responses: + '200': + description: Erfolgreiche Antwort + content: + application/json: + schema: + type: object + properties: + id: + type: integer + example: 1 + name: + type: string + example: Max Mustermann + email: + type: string + example: max@beispiel.de + '404': + description: Benutzer nicht gefunden + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: Benutzer nicht gefunden. + security: + - cookieAuthentication: [ ] + - bearerHttpAuthentication: [ ] + - basicHttpAuthentication: [ ] /admin/users/{id}: get: summary: Einzelner Benutzer diff --git a/demo-application/start/routes.ts b/demo-application/start/routes.ts index 92fbef0..fe4432e 100644 --- a/demo-application/start/routes.ts +++ b/demo-application/start/routes.ts @@ -56,6 +56,12 @@ router router.get('/users/:id', async ({ params }) => { return User.findOrFail(params.id) }) + + router.get('/usersByQueryString', async ({ request }) => { + const { id } = request.qs() + + return User.findOrFail(id) + }) }) .use(middlewareAuth) .prefix('/admin') diff --git a/src/core/parsers/openapi-parser.ts b/src/core/parsers/openapi-parser.ts index 0cf5410..71b3687 100644 --- a/src/core/parsers/openapi-parser.ts +++ b/src/core/parsers/openapi-parser.ts @@ -94,7 +94,8 @@ export class OpenAPIParser { const securitySchemes = operation.getSecurityWithTypes(); const hasCombinedSecuritySchemes = securitySchemes.some( - (securitySchemeItem) => securitySchemeItem.length > 1, + (securitySchemeItem) => + Array.isArray(securitySchemeItem) && securitySchemeItem.length > 1, ); if (hasCombinedSecuritySchemes) { @@ -576,19 +577,19 @@ Path '${operation.path}' must be annotated properly.`, } /** - * Expands a URL template with the given parameters + * Expands a URL template with the given path parameters * * @param urlTemplateString The URL template as string to expand - * @param parameters The parameters to expand the URL template with + * @param pathParameters The path parameters to expand the URL template with * @returns The expanded path or URL as string */ static expandUrlTemplate( urlTemplateString: string, - parameters: Record, + pathParameters: Record, ): string { const urlTemplate = parseTemplate(urlTemplateString); - return urlTemplate.expand(parameters); + return urlTemplate.expand(pathParameters); } static combineUrl(baseUrl: string, path: string) { @@ -597,8 +598,8 @@ Path '${operation.path}' must be annotated properly.`, ); } - constructFullApiUrl(url: string) { - return OpenAPIParser.combineUrl(this.apiBaseUrl, url); + constructFullApiUrl(path: string) { + return OpenAPIParser.combineUrl(this.apiBaseUrl, path); } static pathContainsParameter(path: string, parameterName: string) { diff --git a/src/core/tests/test-utils.ts b/src/core/tests/test-utils.ts index be5384c..df11bda 100644 --- a/src/core/tests/test-utils.ts +++ b/src/core/tests/test-utils.ts @@ -157,26 +157,41 @@ export function createRequestData({ // resourceIdentifier can be undefined when resource access is create for instance // or when access for all resources of a type is described let requestBody: RequestBody; + let processedPath = path; + const queryParameters = new URLSearchParams(); - const expandedPath = - resourceIdentifier === undefined || - currentResource.parameterName === undefined || - currentResource.parameterLocation !== "path" - ? path - : OpenAPIParser.expandUrlTemplate(path, { + if ( + currentResource.parameterName !== undefined && + resourceIdentifier !== undefined + ) { + switch (currentResource.parameterLocation) { + case "path": { + processedPath = OpenAPIParser.expandUrlTemplate(path, { + [currentResource.parameterName]: resourceIdentifier, + }); + break; + } + case "query": { + queryParameters.set( + currentResource.parameterName, + resourceIdentifier.toString(), + ); + break; + } + case "body": { + // todo: this only works for params on the top level of the request body + requestBody = { [currentResource.parameterName]: resourceIdentifier, - }); // todo: for multiple resources and therefore parameters, multiple keys in object -> dynamic mapping required + }; + break; + } + } + } - const url = openApiParser.constructFullApiUrl(expandedPath); + const url = openApiParser.constructFullApiUrl(processedPath); - // todo: this only works for params on the top level of the request body - if ( - currentResource.parameterLocation === "body" && - currentResource.parameterName !== undefined - ) { - requestBody = { - [currentResource.parameterName]: resourceIdentifier, - }; + if (queryParameters.size > 0) { + url.search = queryParameters.toString(); } return {