diff options
author | Christian Fehmer <[email protected]> | 2024-09-10 11:35:57 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2024-09-10 11:35:57 +0200 |
commit | c7b3e2c916ee11c163feb60096caf9df942427d7 (patch) | |
tree | 932ef5a058601aa07ecacc994bd82c76aa78f39e /backend/scripts | |
parent | 14277538c307a5b2a0d03b183418e45304278846 (diff) | |
download | monkeytype-c7b3e2c916ee11c163feb60096caf9df942427d7.tar.gz monkeytype-c7b3e2c916ee11c163feb60096caf9df942427d7.zip |
impr: move permission checks to contracts (@fehmer, @miodec) (#5848)
!nuf
Diffstat (limited to 'backend/scripts')
-rw-r--r-- | backend/scripts/openapi.ts | 87 | ||||
-rw-r--r-- | backend/scripts/tsconfig.json | 11 |
2 files changed, 65 insertions, 33 deletions
diff --git a/backend/scripts/openapi.ts b/backend/scripts/openapi.ts index ffa5648df..83c78277a 100644 --- a/backend/scripts/openapi.ts +++ b/backend/scripts/openapi.ts @@ -2,14 +2,14 @@ import { generateOpenApi } from "@ts-rest/open-api"; import { contract } from "@monkeytype/contracts/index"; import { writeFileSync, mkdirSync } from "fs"; import { - ApeKeyRateLimit, EndpointMetadata, + Permission, } from "@monkeytype/contracts/schemas/api"; -import type { OpenAPIObject } from "openapi3-ts"; +import type { OpenAPIObject, OperationObject } from "openapi3-ts"; import { + RateLimitIds, getLimits, - limits, - RateLimit, + RateLimiterId, Window, } from "@monkeytype/contracts/rate-limit/index"; import { formatDuration } from "date-fns"; @@ -143,55 +143,76 @@ export function getOpenApi(): OpenAPIObject { operationMapper: (operation, route) => { const metadata = route.metadata as EndpointMetadata; - addRateLimit(operation, metadata); + if (!operation.description?.trim()?.endsWith(".")) + operation.description += "."; + operation.description += "\n\n"; - const result = { - ...operation, - ...addAuth(metadata), - ...addTags(metadata), - }; + addAuth(operation, metadata); + addRateLimit(operation, metadata); + addTags(operation, metadata); - return result; + return operation; }, } ); return openApiDocument; } -function addAuth(metadata: EndpointMetadata | undefined): object { - const auth = metadata?.["authenticationOptions"] ?? {}; +function addAuth( + operation: OperationObject, + metadata: EndpointMetadata | undefined +): void { + const auth = metadata?.authenticationOptions ?? {}; + const permissions = getRequiredPermissions(metadata) ?? []; const security: SecurityRequirementObject[] = []; - if (!auth.isPublic === true && !auth.isPublicOnDev === true) { - security.push({ BearerAuth: [] }); + if (!auth.isPublic && !auth.isPublicOnDev) { + security.push({ BearerAuth: permissions }); if (auth.acceptApeKeys === true) { - security.push({ ApeKey: [] }); + security.push({ ApeKey: permissions }); } } const includeInPublic = auth.isPublic === true || auth.acceptApeKeys === true; - return { - "x-public": includeInPublic ? "yes" : "no", - security, - }; + operation["x-public"] = includeInPublic ? "yes" : "no"; + operation.security = security; + + if (permissions.length !== 0) { + operation.description += `**Required permissions:** ${permissions.join( + ", " + )}\n\n`; + } } -function addTags(metadata: EndpointMetadata | undefined): object { - if (metadata === undefined || metadata.openApiTags === undefined) return {}; - return { - tags: Array.isArray(metadata.openApiTags) - ? metadata.openApiTags - : [metadata.openApiTags], - }; +function getRequiredPermissions( + metadata: EndpointMetadata | undefined +): Permission[] | undefined { + if (metadata === undefined || metadata.requirePermission === undefined) + return undefined; + + if (Array.isArray(metadata.requirePermission)) + return metadata.requirePermission; + return [metadata.requirePermission]; } -function addRateLimit(operation, metadata: EndpointMetadata | undefined): void { +function addTags( + operation: OperationObject, + metadata: EndpointMetadata | undefined +): void { + if (metadata === undefined || metadata.openApiTags === undefined) return; + operation.tags = Array.isArray(metadata.openApiTags) + ? metadata.openApiTags + : [metadata.openApiTags]; +} + +function addRateLimit( + operation: OperationObject, + metadata: EndpointMetadata | undefined +): void { if (metadata === undefined || metadata.rateLimit === undefined) return; const okResponse = operation.responses["200"]; if (okResponse === undefined) return; - if (!operation.description.trim().endsWith(".")) operation.description += "."; - operation.description += getRateLimitDescription(metadata.rateLimit); okResponse["headers"] = { @@ -211,10 +232,10 @@ function addRateLimit(operation, metadata: EndpointMetadata | undefined): void { }; } -function getRateLimitDescription(limit: RateLimit | ApeKeyRateLimit): string { +function getRateLimitDescription(limit: RateLimiterId | RateLimitIds): string { const limits = getLimits(limit); - let result = ` This operation can be called up to ${ + let result = `**Rate limit:** This operation can be called up to ${ limits.limiter.max } times ${formatWindow(limits.limiter.window)} for regular users`; @@ -224,7 +245,7 @@ function getRateLimitDescription(limit: RateLimit | ApeKeyRateLimit): string { )} with ApeKeys`; } - return result + "."; + return result + ".\n\n"; } function formatWindow(window: Window): string { diff --git a/backend/scripts/tsconfig.json b/backend/scripts/tsconfig.json new file mode 100644 index 000000000..4de721467 --- /dev/null +++ b/backend/scripts/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "@monkeytype/typescript-config/base.json", + "compilerOptions": { + "target": "ES6" + }, + "ts-node": { + "files": true + }, + "files": ["../src/types/types.d.ts"], + "include": ["./**/*"] +} |