aboutsummaryrefslogtreecommitdiffhomepage
path: root/backend/scripts
diff options
context:
space:
mode:
authorChristian Fehmer <[email protected]>2024-09-10 11:35:57 +0200
committerGitHub <[email protected]>2024-09-10 11:35:57 +0200
commitc7b3e2c916ee11c163feb60096caf9df942427d7 (patch)
tree932ef5a058601aa07ecacc994bd82c76aa78f39e /backend/scripts
parent14277538c307a5b2a0d03b183418e45304278846 (diff)
downloadmonkeytype-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.ts87
-rw-r--r--backend/scripts/tsconfig.json11
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": ["./**/*"]
+}