Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upates poilicies script #300

Merged
merged 6 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ next-env.d.ts
/docs/policies/
src/components/bundles.json
/policies.*.json
scripts/update-policies.mjs.map
/temp
scripts/update-policies.mjs
/bundles.json
src/shiki
Expand Down
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
"scripts": {
"dev": "npm run ci:pre && next dev",
"build": "npm run ci:pre && next build",
"postinstall": "node ./scripts/update-bundles.mjs && node ./scripts/copy-shiki.mjs",
"postinstall": "npm run get-policies && npm run ci:shiki",
"get-policies": "sh ./scripts/get-policies.sh",
"postbuild": "next-sitemap",
"start": "npm run ci:pre && next start",
"start": "next start",
"lint": "next lint",
"format": "prettier --write .",
"ci:pre": "npm run ci:bundles && npm run ci:policies",
"ci:bundles": "node ./scripts/update-bundles.mjs",
"ci:policies": "node ./scripts/build.mjs && node ./scripts/update-policies.main.mjs"
"ci:shiki": "node ./scripts/copy-shiki.mjs",
"ci:policies": "node ./scripts/build.mjs && node --enable-source-maps ./scripts/update-policies.main.mjs"
},
"browserslist": "defaults, not ie <= 11",
"dependencies": {
Expand Down Expand Up @@ -46,6 +48,7 @@
"next-mdx-remote": "^4.4.1",
"next-sitemap": "^4.2.3",
"next-themes": "^0.2.1",
"posthog-js": "^1.96.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-highlight-words": "^0.20.0",
Expand All @@ -65,8 +68,8 @@
"video.js": "^8.3.0"
},
"devDependencies": {
"@types/json-schema": "^7.0.15",
"@playwright/test": "^1.40.1",
"@types/json-schema": "^7.0.13",
"@types/node": "^18.18.4",
"checkly": "^4.5.2",
"eslint": "^8.51.0",
Expand Down
14 changes: 14 additions & 0 deletions policies/ab-test-inbound/policy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";

export default async function (request: ZuploRequest, context: ZuploContext) {
// Generate a random number to segment the test groups
const score = Math.random();

if (score < 0.5) {
// Do something for half the requests
} else {
// Do something else for the other half
}

return request;
}
26 changes: 26 additions & 0 deletions policies/ab-test-outbound/policy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";

export default async function (
response: Response,
request: ZuploRequest,
context: ZuploContext,
) {
// Generate a random number to segment the test groups
const score = Math.random();

// Get the outgoing response body
const data = await response.json();

// Modify the body based on the random value
if (score < 0.5) {
data.testEnabled = true;
} else {
data.testEnabled = false;
}

// Stringify the data object
const body = JSON.stringify(data);

// Return a new response with the updated body
return new Response(body, response);
}
32 changes: 32 additions & 0 deletions policies/acl-policy-inbound/policy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { HttpProblems, ZuploContext, ZuploRequest } from "@zuplo/runtime";

interface PolicyOptions {
users: string[];
}

export default async function (
request: ZuploRequest,
context: ZuploContext,
options: PolicyOptions,
policyName: string,
) {
// Check that an authenticated user is set
// NOTE: This policy requires an authentication policy to run before
if (!request.user) {
context.log.error(
"User is not authenticated. A authorization policy must come before the ACL policy.",
);
return HttpProblems.unauthorized(request, context);
}

// Check that the user has one of the allowed roles
if (!options.users.includes(request.user.sub)) {
context.log.error(
`The user '${request.user.sub}' is not authorized to perform this action.`,
);
return HttpProblems.forbidden(request, context);
}

// If they made it here, they are authorized
return request;
}
2 changes: 1 addition & 1 deletion policies/amberflo-metering-inbound/doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default async function (
request: ZuploRequest,
context: ZuploContext,
options: MyPolicyOptionsType,
policyName: string,
policyName: string
) {
AmberfloMeteringPolicy.setRequestProperties(context, {
customerId: request.user.sub,
Expand Down
7 changes: 2 additions & 5 deletions policies/amberflo-metering-inbound/intro.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
Amberflo ([amberflo.io](https://www.amberflo.io/)) is a usage metering and
billing service. This policy allows you to meter API calls going through Zuplo
and send them to your Amberflo account using your Amberflo API key.
Amberflo [amberflo.com](https://www.amberflo.io) is a usage metering and billing service. This policy allows you to meter API calls going through Zuplo and send them to your Amberflo account using your Amberflo API key.

Add the policy to each route you want to meter. Note you can specify the Meter
API Name and Meter Value (meter increment) at the policy level.
Add the policy to each route you want to meter. Note you can specify the Meter API Name and Meter Value (meter increment) at the policy level.
62 changes: 44 additions & 18 deletions policies/amberflo-metering-inbound/schema.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"$schema": "https://json-schema.org/draft-07/schema",
"$id": "http://zuplo.com/schemas/policies/open-id-jwt-auth-inbound.json",
"$id": "http://zuplo.com/schemas/policies/auth0-jwt-auth-inbound.json",
"type": "object",
"title": "Amberflo Metering / Billing",
"isPreview": false,
"description": "Amberflo is a usage metering and billing service. This policy allows you to send metering calls for each API to their meter ingest endpoint.",
"isDeprecated": false,
"isPaidAddOn": false,
"isUnlisted": false,
"description": "Amberflo is a usage metering and billing service. This policy allows you to send metering calls for each API to their meter ingest endpoint.\n\n",
"required": ["handler"],
"properties": {
"handler": {
Expand All @@ -21,56 +23,80 @@
"description": "The module containing the policy"
},
"options": {
"title": "AmberfloMeteringInboundPolicyOptions",
"type": "object",
"description": "The options for this policy. Many of them can be overridden at the code level in a request using the `AmberfloMeteringPolicy.setRequestProperties` method.",
"required": ["apiKey"],
"additionalProperties": false,
"properties": {
"apiKey": {
"type": "string",
"description": "The API key to use when sending metering calls to Amberflo"
"examples": ["$env(AMBERFLO_API_KEY)"],
"description": "The API key to use when sending metering calls to Amberflo."
},
"meterApiName": {
"type": "string",
"description": "The name of the meter to use when sending metering calls to Amberflo (overridable in code)"
"examples": ["$env(AMBERFLO_METER_API_NAME)"],
"description": "The name of the meter to use when sending metering calls to Amberflo (overridable in code)."
},
"meterValue": {
"type": "number",
"description": "The value to use when sending metering calls to Amberflo (overridable in code)"
"examples": ["$env(AMBERFLO_METER_VALUE)"],
"description": "The value to use when sending metering calls to Amberflo (overridable in code)."
},
"customerIdPropertyPath": {
"type": "string",
"description": "The path to the property on `request.user`contains the customer ID. For example `.data.accountNumber` would read the `request.user.data.accountNumber` property."
"examples": [".sub"],
"default": ".sub",
"description": "The path to the property on `request.user`<!-- -->contains the customer ID. For example `.data.accountNumber` would read the `request.user.data.accountNumber` property."
},
"customerId": {
"type": "string",
"description": "The default customerId for all metering calls - overridable in code and by `customerIdPropertyPath`"
"description": "The default customerId for all metering calls - overridable in code and by `customerIdPropertyPath`<!-- -->."
},
"dimensions": {
"type": "object",
"description": "A dictionary of dimensions to be sent to Amberflo (extensible in code)"
"additionalProperties": {
"type": "string"
},
"description": "A dictionary of dimensions to be sent to Amberflo (extensible in code)."
},
"statusCodes": {
"type": "string",
"description": "A list of successful status codes and ranges \"200-299, 304\" that should trigger a metering call to Amberflo - defaults to `result.ok` (200-299) if not set."
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "number"
}
}
],
"description": "A list of successful status codes and ranges \"200-299, 304\" that should trigger a metering call to Amberflo.",
"default": "200-299"
},
"url": {
"type": "string",
"description": "Optional, the URL to send metering events to (defaults to https://app.amberflo.io/ingest). This is useful for testing purposes."
"default": " https://app.amberflo.io/ingest",
"description": "The URL to send metering events. This is useful for testing purposes."
}
}
}
},
"examples": [
{
"_name": "basic",
"module": "$import(@zuplo/runtime)",
"export": "AmberfloMeteringInboundPolicy",
"module": "$import(@zuplo/runtime)",
"options": {
"apiKey": "YOUR_API_KEY",
"customerIdPropertyPath": ".data.accountNumber",
"meterApiName": "api-calls",
"meterValue": 1,
"statusCodes": "200-299, 304"
"apiKey": "$env(AMBERFLO_API_KEY)",
"customerIdPropertyPath": ".sub",
"dimensions": {},
"meterApiName": "$env(AMBERFLO_METER_API_NAME)",
"meterValue": "$env(AMBERFLO_METER_VALUE)",
"statusCodes": "200-299",
"url": " https://app.amberflo.io/ingest"
}
}
]
Expand Down
9 changes: 2 additions & 7 deletions policies/api-key-auth-inbound/intro.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
**This policy is deprecated. Use the new
[API Key Authentication policy instead](https://zuplo.com/docs/policies/api-key-inbound)**
**This policy is deprecated.** Please use the new [API Key Authentication](https://zuplo.com/docs/policies/api-key-inbound) policy instead. This policy will continue to work but will be removed in a future version of Zuplo.

This policy uses the managed API key storage provided by Zuplo.
`allowUnauthenticatedRequests` defaults to false and rejects any request without
a valid API key (returning a `401 - Unauthorized` response). You can override
(set `"allowUnauthenticatedRequests" : true`) this to support multiple
authentication methods or support both authenticated and anonymous requests.
This policy uses the managed API key storage provided by Zuplo. `allowUnauthenticatedRequests` defaults to false and rejects any request without a valid API key (returning a `401 - Unauthorized` response). You can override (set `"allowUnauthenticatedRequests" : true`<!-- -->) this to support multiple authentication methods or support both authenticated and anonymous requests.
15 changes: 11 additions & 4 deletions policies/api-key-auth-inbound/schema.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"$schema": "https://json-schema.org/draft-07/schema",
"$id": "http://zuplo.com/schemas/policies/api-key-auth-inbound.json",
"$id": "http://zuplo.com/schemas/policies/auth0-jwt-auth-inbound.json",
"type": "object",
"title": "Legacy API Key Authentication (deprecated)",
"isPreview": false,
"title": "API Key Authentication",
"isDeprecated": true,
"description": "Deprecated - Please use the new 'API Key Authentication' policy instead. This policy will continue to work but will be removed in a future version of Zuplo.",
"isPaidAddOn": false,
"isUnlisted": true,
"description": "Authenticates requests based on API Keys using Zuplo API Management. You can learn more about the Zuplo API Key Service \\[here\\](https://zuplo.com/docs/articles/api-key-api\\#buckets)\n\n",
"required": ["handler"],
"properties": {
"handler": {
Expand All @@ -22,10 +23,16 @@
"description": "The module containing the policy"
},
"options": {
"title": "ApiAuthKeyInboundPolicyOptions",
"type": "object",
"description": "The options for this policy",
"additionalProperties": false,
"required": [],
"deprecated": true,
"properties": {
"allowUnauthenticatedRequests": {
"type": "boolean",
"default": false,
"description": "If 'true' allows the request to continue even if authenticated. When 'false' (the default) any unauthenticated request is automatically rejected with a 401"
}
}
Expand Down
Loading