workos 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -6
- package/dist/bin.js +22 -1
- package/dist/bin.js.map +1 -1
- package/dist/check-coverage.ts +237 -0
- package/dist/commands/debug.js +0 -1
- package/dist/commands/debug.js.map +1 -1
- package/dist/commands/dev.d.ts +23 -0
- package/dist/commands/dev.js +139 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/emulate.d.ts +6 -0
- package/dist/commands/emulate.js +64 -0
- package/dist/commands/emulate.js.map +1 -0
- package/dist/commands/login.js +0 -4
- package/dist/commands/login.js.map +1 -1
- package/dist/emulate/core/id.d.ts +48 -0
- package/dist/emulate/core/id.js +73 -0
- package/dist/emulate/core/id.js.map +1 -0
- package/dist/emulate/core/index.d.ts +8 -0
- package/dist/emulate/core/index.js +8 -0
- package/dist/emulate/core/index.js.map +1 -0
- package/dist/emulate/core/jwt.d.ts +28 -0
- package/dist/emulate/core/jwt.js +78 -0
- package/dist/emulate/core/jwt.js.map +1 -0
- package/dist/emulate/core/middleware/auth.d.ts +15 -0
- package/dist/emulate/core/middleware/auth.js +17 -0
- package/dist/emulate/core/middleware/auth.js.map +1 -0
- package/dist/emulate/core/middleware/error-handler.d.ts +22 -0
- package/dist/emulate/core/middleware/error-handler.js +72 -0
- package/dist/emulate/core/middleware/error-handler.js.map +1 -0
- package/dist/emulate/core/pagination.d.ts +27 -0
- package/dist/emulate/core/pagination.js +43 -0
- package/dist/emulate/core/pagination.js.map +1 -0
- package/dist/emulate/core/plugin.d.ts +15 -0
- package/dist/emulate/core/plugin.js +2 -0
- package/dist/emulate/core/plugin.js.map +1 -0
- package/dist/emulate/core/server.d.ts +17 -0
- package/dist/emulate/core/server.js +90 -0
- package/dist/emulate/core/server.js.map +1 -0
- package/dist/emulate/core/store.d.ts +44 -0
- package/dist/emulate/core/store.js +169 -0
- package/dist/emulate/core/store.js.map +1 -0
- package/dist/emulate/index.d.ts +25 -0
- package/dist/emulate/index.js +47 -0
- package/dist/emulate/index.js.map +1 -0
- package/dist/emulate/workos/constants.d.ts +56 -0
- package/dist/emulate/workos/constants.js +56 -0
- package/dist/emulate/workos/constants.js.map +1 -0
- package/dist/emulate/workos/entities.d.ts +360 -0
- package/dist/emulate/workos/entities.js +2 -0
- package/dist/emulate/workos/entities.js.map +1 -0
- package/dist/emulate/workos/event-bus.d.ts +17 -0
- package/dist/emulate/workos/event-bus.js +70 -0
- package/dist/emulate/workos/event-bus.js.map +1 -0
- package/dist/emulate/workos/helpers.d.ts +72 -0
- package/dist/emulate/workos/helpers.js +211 -0
- package/dist/emulate/workos/helpers.js.map +1 -0
- package/dist/emulate/workos/index.d.ts +91 -0
- package/dist/emulate/workos/index.js +322 -0
- package/dist/emulate/workos/index.js.map +1 -0
- package/dist/emulate/workos/role-helpers.d.ts +21 -0
- package/dist/emulate/workos/role-helpers.js +130 -0
- package/dist/emulate/workos/role-helpers.js.map +1 -0
- package/dist/emulate/workos/routes/api-keys.d.ts +2 -0
- package/dist/emulate/workos/routes/api-keys.js +32 -0
- package/dist/emulate/workos/routes/api-keys.js.map +1 -0
- package/dist/emulate/workos/routes/audit-logs.d.ts +2 -0
- package/dist/emulate/workos/routes/audit-logs.js +104 -0
- package/dist/emulate/workos/routes/audit-logs.js.map +1 -0
- package/dist/emulate/workos/routes/auth-challenges.d.ts +2 -0
- package/dist/emulate/workos/routes/auth-challenges.js +51 -0
- package/dist/emulate/workos/routes/auth-challenges.js.map +1 -0
- package/dist/emulate/workos/routes/auth-factors.d.ts +2 -0
- package/dist/emulate/workos/routes/auth-factors.js +51 -0
- package/dist/emulate/workos/routes/auth-factors.js.map +1 -0
- package/dist/emulate/workos/routes/auth.d.ts +2 -0
- package/dist/emulate/workos/routes/auth.js +350 -0
- package/dist/emulate/workos/routes/auth.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-checks.d.ts +10 -0
- package/dist/emulate/workos/routes/authorization-checks.js +123 -0
- package/dist/emulate/workos/routes/authorization-checks.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-org-roles.d.ts +2 -0
- package/dist/emulate/workos/routes/authorization-org-roles.js +64 -0
- package/dist/emulate/workos/routes/authorization-org-roles.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-permissions.d.ts +2 -0
- package/dist/emulate/workos/routes/authorization-permissions.js +67 -0
- package/dist/emulate/workos/routes/authorization-permissions.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-resources.d.ts +2 -0
- package/dist/emulate/workos/routes/authorization-resources.js +117 -0
- package/dist/emulate/workos/routes/authorization-resources.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-roles.d.ts +2 -0
- package/dist/emulate/workos/routes/authorization-roles.js +13 -0
- package/dist/emulate/workos/routes/authorization-roles.js.map +1 -0
- package/dist/emulate/workos/routes/config.d.ts +2 -0
- package/dist/emulate/workos/routes/config.js +57 -0
- package/dist/emulate/workos/routes/config.js.map +1 -0
- package/dist/emulate/workos/routes/connect.d.ts +2 -0
- package/dist/emulate/workos/routes/connect.js +65 -0
- package/dist/emulate/workos/routes/connect.js.map +1 -0
- package/dist/emulate/workos/routes/connections.d.ts +2 -0
- package/dist/emulate/workos/routes/connections.js +73 -0
- package/dist/emulate/workos/routes/connections.js.map +1 -0
- package/dist/emulate/workos/routes/data-integrations.d.ts +2 -0
- package/dist/emulate/workos/routes/data-integrations.js +55 -0
- package/dist/emulate/workos/routes/data-integrations.js.map +1 -0
- package/dist/emulate/workos/routes/directories.d.ts +2 -0
- package/dist/emulate/workos/routes/directories.js +90 -0
- package/dist/emulate/workos/routes/directories.js.map +1 -0
- package/dist/emulate/workos/routes/email-verification.d.ts +2 -0
- package/dist/emulate/workos/routes/email-verification.js +49 -0
- package/dist/emulate/workos/routes/email-verification.js.map +1 -0
- package/dist/emulate/workos/routes/events.d.ts +2 -0
- package/dist/emulate/workos/routes/events.js +18 -0
- package/dist/emulate/workos/routes/events.js.map +1 -0
- package/dist/emulate/workos/routes/feature-flags.d.ts +2 -0
- package/dist/emulate/workos/routes/feature-flags.js +103 -0
- package/dist/emulate/workos/routes/feature-flags.js.map +1 -0
- package/dist/emulate/workos/routes/invitations.d.ts +2 -0
- package/dist/emulate/workos/routes/invitations.js +122 -0
- package/dist/emulate/workos/routes/invitations.js.map +1 -0
- package/dist/emulate/workos/routes/legacy-mfa.d.ts +2 -0
- package/dist/emulate/workos/routes/legacy-mfa.js +75 -0
- package/dist/emulate/workos/routes/legacy-mfa.js.map +1 -0
- package/dist/emulate/workos/routes/magic-auth.d.ts +2 -0
- package/dist/emulate/workos/routes/magic-auth.js +32 -0
- package/dist/emulate/workos/routes/magic-auth.js.map +1 -0
- package/dist/emulate/workos/routes/memberships.d.ts +2 -0
- package/dist/emulate/workos/routes/memberships.js +114 -0
- package/dist/emulate/workos/routes/memberships.js.map +1 -0
- package/dist/emulate/workos/routes/organization-domains.d.ts +2 -0
- package/dist/emulate/workos/routes/organization-domains.js +58 -0
- package/dist/emulate/workos/routes/organization-domains.js.map +1 -0
- package/dist/emulate/workos/routes/organizations.d.ts +2 -0
- package/dist/emulate/workos/routes/organizations.js +131 -0
- package/dist/emulate/workos/routes/organizations.js.map +1 -0
- package/dist/emulate/workos/routes/password-reset.d.ts +2 -0
- package/dist/emulate/workos/routes/password-reset.js +61 -0
- package/dist/emulate/workos/routes/password-reset.js.map +1 -0
- package/dist/emulate/workos/routes/pipes.d.ts +2 -0
- package/dist/emulate/workos/routes/pipes.js +82 -0
- package/dist/emulate/workos/routes/pipes.js.map +1 -0
- package/dist/emulate/workos/routes/portal.d.ts +2 -0
- package/dist/emulate/workos/routes/portal.js +18 -0
- package/dist/emulate/workos/routes/portal.js.map +1 -0
- package/dist/emulate/workos/routes/radar.d.ts +2 -0
- package/dist/emulate/workos/routes/radar.js +41 -0
- package/dist/emulate/workos/routes/radar.js.map +1 -0
- package/dist/emulate/workos/routes/sessions.d.ts +2 -0
- package/dist/emulate/workos/routes/sessions.js +51 -0
- package/dist/emulate/workos/routes/sessions.js.map +1 -0
- package/dist/emulate/workos/routes/sso.d.ts +2 -0
- package/dist/emulate/workos/routes/sso.js +161 -0
- package/dist/emulate/workos/routes/sso.js.map +1 -0
- package/dist/emulate/workos/routes/user-features.d.ts +2 -0
- package/dist/emulate/workos/routes/user-features.js +50 -0
- package/dist/emulate/workos/routes/user-features.js.map +1 -0
- package/dist/emulate/workos/routes/users.d.ts +2 -0
- package/dist/emulate/workos/routes/users.js +129 -0
- package/dist/emulate/workos/routes/users.js.map +1 -0
- package/dist/emulate/workos/routes/webhook-endpoints.d.ts +2 -0
- package/dist/emulate/workos/routes/webhook-endpoints.js +66 -0
- package/dist/emulate/workos/routes/webhook-endpoints.js.map +1 -0
- package/dist/emulate/workos/routes/widgets.d.ts +2 -0
- package/dist/emulate/workos/routes/widgets.js +27 -0
- package/dist/emulate/workos/routes/widgets.js.map +1 -0
- package/dist/emulate/workos/store.d.ts +48 -0
- package/dist/emulate/workos/store.js +102 -0
- package/dist/emulate/workos/store.js.map +1 -0
- package/dist/emulate/workos/webhook-signer.d.ts +1 -0
- package/dist/emulate/workos/webhook-signer.js +8 -0
- package/dist/emulate/workos/webhook-signer.js.map +1 -0
- package/dist/gen-routes-lib.spec.ts +659 -0
- package/dist/gen-routes-lib.ts +647 -0
- package/dist/gen-routes.ts +96 -0
- package/dist/lib/dev-command.d.ts +26 -0
- package/dist/lib/dev-command.js +122 -0
- package/dist/lib/dev-command.js.map +1 -0
- package/dist/lib/run-with-core.js +0 -3
- package/dist/lib/run-with-core.js.map +1 -1
- package/dist/lib/settings.js +1 -1
- package/dist/lib/settings.js.map +1 -1
- package/dist/utils/help-json.js +1 -0
- package/dist/utils/help-json.js.map +1 -1
- package/dist/utils/register-subcommand.d.ts +5 -2
- package/dist/utils/register-subcommand.js +16 -19
- package/dist/utils/register-subcommand.js.map +1 -1
- package/package.json +21 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-org-roles.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/authorization-org-roles.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, validationError, parseJsonBody } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatRole } from '../helpers.js';\nimport { findOrgRole, requireOrgRole, registerRoleRoutes } from '../role-helpers.js';\n\nexport function authorizationOrgRoleRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n const prefix = '/authorization/organizations/:orgId/roles';\n\n // Priority ordering — must be registered before :slug routes\n app.put(`${prefix}/priority`, async (c) => {\n const orgId = c.req.param('orgId');\n const body = await parseJsonBody(c);\n const slugs = body.slugs as string[];\n\n if (!Array.isArray(slugs)) {\n throw validationError('slugs must be an array', [{ field: 'slugs', code: 'invalid' }]);\n }\n\n // Fetch once, build slug map for O(1) lookups\n const orgRoles = ws.roles.findBy('organization_id', orgId).filter((r) => r.type === 'OrganizationRole');\n const rolesBySlug = new Map(orgRoles.map((r) => [r.slug, r]));\n\n for (let i = 0; i < slugs.length; i++) {\n const role = rolesBySlug.get(slugs[i]!);\n if (!role) throw notFound('Role');\n ws.roles.update(role.id, { priority: i });\n }\n\n // Re-fetch for updated priority values\n const updated = ws.roles\n .findBy('organization_id', orgId)\n .filter((r) => r.type === 'OrganizationRole')\n .sort((a, b) => a.priority - b.priority);\n\n return c.json({\n object: 'list',\n data: updated.map(formatRole),\n list_metadata: { before: null, after: null },\n });\n });\n\n registerRoleRoutes(ctx, {\n pathPrefix: prefix,\n roleType: 'OrganizationRole',\n requireRole: (ws, c) => requireOrgRole(ws, c.req.param('orgId'), c.req.param('slug')),\n findRole: (ws, c, slug) => findOrgRole(ws, c.req.param('orgId'), slug),\n listFilter: (c) => (r) => r.organization_id === c.req.param('orgId') && r.type === 'OrganizationRole',\n insertDefaults: (c) => ({ organization_id: c.req.param('orgId') }),\n duplicateMessage: 'Role with this slug already exists in this organization',\n validateBeforeCreate: (ws, c) => {\n const org = ws.organizations.get(c.req.param('orgId'));\n if (!org) throw notFound('Organization');\n },\n });\n\n // Org-specific: delete single permission from role\n app.delete(`${prefix}/:slug/permissions/:permissionSlug`, (c) => {\n const role = requireOrgRole(ws, c.req.param('orgId'), c.req.param('slug'));\n\n const perm = ws.permissions.findOneBy('slug', c.req.param('permissionSlug'));\n if (!perm) throw notFound('Permission');\n\n const rp = ws.rolePermissions.findBy('role_id', role.id).find((rp) => rp.permission_id === perm.id);\n if (!rp) throw notFound('RolePermission');\n\n ws.rolePermissions.delete(rp.id);\n return c.body(null, 204);\n });\n}\n"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { notFound, validationError, parseJsonBody, parseListParams } from '../../core/index.js';
|
|
2
|
+
import { getWorkOSStore } from '../store.js';
|
|
3
|
+
import { formatPermission, formatListResponse } from '../helpers.js';
|
|
4
|
+
export function authorizationPermissionRoutes(ctx) {
|
|
5
|
+
const { app, store } = ctx;
|
|
6
|
+
const ws = getWorkOSStore(store);
|
|
7
|
+
app.post('/authorization/permissions', async (c) => {
|
|
8
|
+
const body = await parseJsonBody(c);
|
|
9
|
+
const slug = body.slug;
|
|
10
|
+
const name = body.name;
|
|
11
|
+
if (!slug || typeof slug !== 'string') {
|
|
12
|
+
throw validationError('slug is required', [{ field: 'slug', code: 'required' }]);
|
|
13
|
+
}
|
|
14
|
+
if (!name || typeof name !== 'string') {
|
|
15
|
+
throw validationError('name is required', [{ field: 'name', code: 'required' }]);
|
|
16
|
+
}
|
|
17
|
+
const existing = ws.permissions.findOneBy('slug', slug);
|
|
18
|
+
if (existing) {
|
|
19
|
+
throw validationError('Permission with this slug already exists', [{ field: 'slug', code: 'duplicate' }]);
|
|
20
|
+
}
|
|
21
|
+
const permission = ws.permissions.insert({
|
|
22
|
+
object: 'permission',
|
|
23
|
+
slug,
|
|
24
|
+
name,
|
|
25
|
+
description: body.description ?? null,
|
|
26
|
+
});
|
|
27
|
+
return c.json(formatPermission(permission), 201);
|
|
28
|
+
});
|
|
29
|
+
app.get('/authorization/permissions', (c) => {
|
|
30
|
+
const url = new URL(c.req.url);
|
|
31
|
+
const params = parseListParams(url);
|
|
32
|
+
const result = ws.permissions.list(params);
|
|
33
|
+
return c.json(formatListResponse(result, formatPermission));
|
|
34
|
+
});
|
|
35
|
+
app.get('/authorization/permissions/:slug', (c) => {
|
|
36
|
+
const slug = c.req.param('slug');
|
|
37
|
+
const permission = ws.permissions.findOneBy('slug', slug);
|
|
38
|
+
if (!permission)
|
|
39
|
+
throw notFound('Permission');
|
|
40
|
+
return c.json(formatPermission(permission));
|
|
41
|
+
});
|
|
42
|
+
app.put('/authorization/permissions/:slug', async (c) => {
|
|
43
|
+
const slug = c.req.param('slug');
|
|
44
|
+
const permission = ws.permissions.findOneBy('slug', slug);
|
|
45
|
+
if (!permission)
|
|
46
|
+
throw notFound('Permission');
|
|
47
|
+
const body = await parseJsonBody(c);
|
|
48
|
+
const updates = {};
|
|
49
|
+
if ('name' in body)
|
|
50
|
+
updates.name = body.name;
|
|
51
|
+
if ('description' in body)
|
|
52
|
+
updates.description = body.description ?? null;
|
|
53
|
+
const updated = ws.permissions.update(permission.id, updates);
|
|
54
|
+
return c.json(formatPermission(updated));
|
|
55
|
+
});
|
|
56
|
+
app.delete('/authorization/permissions/:slug', (c) => {
|
|
57
|
+
const slug = c.req.param('slug');
|
|
58
|
+
const permission = ws.permissions.findOneBy('slug', slug);
|
|
59
|
+
if (!permission)
|
|
60
|
+
throw notFound('Permission');
|
|
61
|
+
// Cascade: remove from all role-permission joins
|
|
62
|
+
ws.rolePermissions.deleteBy('permission_id', permission.id);
|
|
63
|
+
ws.permissions.delete(permission.id);
|
|
64
|
+
return c.body(null, 204);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=authorization-permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-permissions.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/authorization-permissions.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, validationError, parseJsonBody, parseListParams } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatPermission, formatListResponse } from '../helpers.js';\n\nexport function authorizationPermissionRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n app.post('/authorization/permissions', async (c) => {\n const body = await parseJsonBody(c);\n const slug = body.slug as string;\n const name = body.name as string;\n\n if (!slug || typeof slug !== 'string') {\n throw validationError('slug is required', [{ field: 'slug', code: 'required' }]);\n }\n if (!name || typeof name !== 'string') {\n throw validationError('name is required', [{ field: 'name', code: 'required' }]);\n }\n\n const existing = ws.permissions.findOneBy('slug', slug);\n if (existing) {\n throw validationError('Permission with this slug already exists', [{ field: 'slug', code: 'duplicate' }]);\n }\n\n const permission = ws.permissions.insert({\n object: 'permission',\n slug,\n name,\n description: (body.description as string) ?? null,\n });\n\n return c.json(formatPermission(permission), 201);\n });\n\n app.get('/authorization/permissions', (c) => {\n const url = new URL(c.req.url);\n const params = parseListParams(url);\n\n const result = ws.permissions.list(params);\n return c.json(formatListResponse(result, formatPermission));\n });\n\n app.get('/authorization/permissions/:slug', (c) => {\n const slug = c.req.param('slug');\n const permission = ws.permissions.findOneBy('slug', slug);\n if (!permission) throw notFound('Permission');\n return c.json(formatPermission(permission));\n });\n\n app.put('/authorization/permissions/:slug', async (c) => {\n const slug = c.req.param('slug');\n const permission = ws.permissions.findOneBy('slug', slug);\n if (!permission) throw notFound('Permission');\n\n const body = await parseJsonBody(c);\n const updates: Record<string, unknown> = {};\n if ('name' in body) updates.name = body.name;\n if ('description' in body) updates.description = body.description ?? null;\n\n const updated = ws.permissions.update(permission.id, updates);\n return c.json(formatPermission(updated!));\n });\n\n app.delete('/authorization/permissions/:slug', (c) => {\n const slug = c.req.param('slug');\n const permission = ws.permissions.findOneBy('slug', slug);\n if (!permission) throw notFound('Permission');\n\n // Cascade: remove from all role-permission joins\n ws.rolePermissions.deleteBy('permission_id', permission.id);\n\n ws.permissions.delete(permission.id);\n return c.body(null, 204);\n });\n}\n"]}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { notFound, validationError, parseJsonBody, parseListParams } from '../../core/index.js';
|
|
2
|
+
import { getWorkOSStore } from '../store.js';
|
|
3
|
+
import { formatAuthorizationResource, formatMembership, formatListResponse } from '../helpers.js';
|
|
4
|
+
export function authorizationResourceRoutes(ctx) {
|
|
5
|
+
const { app, store } = ctx;
|
|
6
|
+
const ws = getWorkOSStore(store);
|
|
7
|
+
app.post('/authorization/resources', async (c) => {
|
|
8
|
+
const body = await parseJsonBody(c);
|
|
9
|
+
const resourceTypeSlug = body.resource_type_slug;
|
|
10
|
+
const externalId = body.external_id;
|
|
11
|
+
const organizationId = body.organization_id;
|
|
12
|
+
if (!resourceTypeSlug) {
|
|
13
|
+
throw validationError('resource_type_slug is required', [{ field: 'resource_type_slug', code: 'required' }]);
|
|
14
|
+
}
|
|
15
|
+
if (!externalId) {
|
|
16
|
+
throw validationError('external_id is required', [{ field: 'external_id', code: 'required' }]);
|
|
17
|
+
}
|
|
18
|
+
if (!organizationId) {
|
|
19
|
+
throw validationError('organization_id is required', [{ field: 'organization_id', code: 'required' }]);
|
|
20
|
+
}
|
|
21
|
+
const resource = ws.authorizationResources.insert({
|
|
22
|
+
object: 'authorization_resource',
|
|
23
|
+
resource_type_slug: resourceTypeSlug,
|
|
24
|
+
external_id: externalId,
|
|
25
|
+
organization_id: organizationId,
|
|
26
|
+
metadata: body.metadata ?? {},
|
|
27
|
+
});
|
|
28
|
+
return c.json(formatAuthorizationResource(resource), 201);
|
|
29
|
+
});
|
|
30
|
+
app.get('/authorization/resources', (c) => {
|
|
31
|
+
const url = new URL(c.req.url);
|
|
32
|
+
const params = parseListParams(url);
|
|
33
|
+
const organizationId = url.searchParams.get('organization_id') ?? undefined;
|
|
34
|
+
const resourceTypeSlug = url.searchParams.get('resource_type_slug') ?? undefined;
|
|
35
|
+
const result = ws.authorizationResources.list({
|
|
36
|
+
...params,
|
|
37
|
+
filter: (r) => {
|
|
38
|
+
if (organizationId && r.organization_id !== organizationId)
|
|
39
|
+
return false;
|
|
40
|
+
if (resourceTypeSlug && r.resource_type_slug !== resourceTypeSlug)
|
|
41
|
+
return false;
|
|
42
|
+
return true;
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
return c.json(formatListResponse(result, formatAuthorizationResource));
|
|
46
|
+
});
|
|
47
|
+
app.get('/authorization/resources/:resource_id', (c) => {
|
|
48
|
+
const resourceId = c.req.param('resource_id');
|
|
49
|
+
const resource = ws.authorizationResources.get(resourceId);
|
|
50
|
+
if (!resource)
|
|
51
|
+
throw notFound('AuthorizationResource');
|
|
52
|
+
return c.json(formatAuthorizationResource(resource));
|
|
53
|
+
});
|
|
54
|
+
app.put('/authorization/resources/:resource_id', async (c) => {
|
|
55
|
+
const resourceId = c.req.param('resource_id');
|
|
56
|
+
const resource = ws.authorizationResources.get(resourceId);
|
|
57
|
+
if (!resource)
|
|
58
|
+
throw notFound('AuthorizationResource');
|
|
59
|
+
const body = await parseJsonBody(c);
|
|
60
|
+
const updates = {};
|
|
61
|
+
if ('metadata' in body)
|
|
62
|
+
updates.metadata = body.metadata;
|
|
63
|
+
const updated = ws.authorizationResources.update(resourceId, updates);
|
|
64
|
+
return c.json(formatAuthorizationResource(updated));
|
|
65
|
+
});
|
|
66
|
+
app.delete('/authorization/resources/:resource_id', (c) => {
|
|
67
|
+
const resourceId = c.req.param('resource_id');
|
|
68
|
+
const resource = ws.authorizationResources.get(resourceId);
|
|
69
|
+
if (!resource)
|
|
70
|
+
throw notFound('AuthorizationResource');
|
|
71
|
+
ws.authorizationResources.delete(resourceId);
|
|
72
|
+
return c.body(null, 204);
|
|
73
|
+
});
|
|
74
|
+
// Memberships with access to a resource (by resource ID)
|
|
75
|
+
app.get('/authorization/resources/:resource_id/organization_memberships', (c) => {
|
|
76
|
+
const resourceId = c.req.param('resource_id');
|
|
77
|
+
const resource = ws.authorizationResources.get(resourceId);
|
|
78
|
+
if (!resource)
|
|
79
|
+
throw notFound('AuthorizationResource');
|
|
80
|
+
const memberships = ws.organizationMemberships.findBy('organization_id', resource.organization_id);
|
|
81
|
+
return c.json({
|
|
82
|
+
object: 'list',
|
|
83
|
+
data: memberships.map(formatMembership),
|
|
84
|
+
list_metadata: { before: null, after: null },
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
// Get resource by type + external ID within an org
|
|
88
|
+
app.get('/authorization/organizations/:orgId/resources/:type_slug/:external_id', (c) => {
|
|
89
|
+
const orgId = c.req.param('orgId');
|
|
90
|
+
const typeSlug = c.req.param('type_slug');
|
|
91
|
+
const externalId = c.req.param('external_id');
|
|
92
|
+
const resource = ws.authorizationResources
|
|
93
|
+
.findBy('organization_id', orgId)
|
|
94
|
+
.find((r) => r.resource_type_slug === typeSlug && r.external_id === externalId);
|
|
95
|
+
if (!resource)
|
|
96
|
+
throw notFound('AuthorizationResource');
|
|
97
|
+
return c.json(formatAuthorizationResource(resource));
|
|
98
|
+
});
|
|
99
|
+
// Memberships for resource by type + external ID within an org
|
|
100
|
+
app.get('/authorization/organizations/:orgId/resources/:type_slug/:external_id/organization_memberships', (c) => {
|
|
101
|
+
const orgId = c.req.param('orgId');
|
|
102
|
+
const typeSlug = c.req.param('type_slug');
|
|
103
|
+
const externalId = c.req.param('external_id');
|
|
104
|
+
const resource = ws.authorizationResources
|
|
105
|
+
.findBy('organization_id', orgId)
|
|
106
|
+
.find((r) => r.resource_type_slug === typeSlug && r.external_id === externalId);
|
|
107
|
+
if (!resource)
|
|
108
|
+
throw notFound('AuthorizationResource');
|
|
109
|
+
const memberships = ws.organizationMemberships.findBy('organization_id', resource.organization_id);
|
|
110
|
+
return c.json({
|
|
111
|
+
object: 'list',
|
|
112
|
+
data: memberships.map(formatMembership),
|
|
113
|
+
list_metadata: { before: null, after: null },
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=authorization-resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-resources.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/authorization-resources.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, validationError, parseJsonBody, parseListParams } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatAuthorizationResource, formatMembership, formatListResponse } from '../helpers.js';\n\nexport function authorizationResourceRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n app.post('/authorization/resources', async (c) => {\n const body = await parseJsonBody(c);\n\n const resourceTypeSlug = body.resource_type_slug as string;\n const externalId = body.external_id as string;\n const organizationId = body.organization_id as string;\n\n if (!resourceTypeSlug) {\n throw validationError('resource_type_slug is required', [{ field: 'resource_type_slug', code: 'required' }]);\n }\n if (!externalId) {\n throw validationError('external_id is required', [{ field: 'external_id', code: 'required' }]);\n }\n if (!organizationId) {\n throw validationError('organization_id is required', [{ field: 'organization_id', code: 'required' }]);\n }\n\n const resource = ws.authorizationResources.insert({\n object: 'authorization_resource',\n resource_type_slug: resourceTypeSlug,\n external_id: externalId,\n organization_id: organizationId,\n metadata: (body.metadata as Record<string, string>) ?? {},\n });\n\n return c.json(formatAuthorizationResource(resource), 201);\n });\n\n app.get('/authorization/resources', (c) => {\n const url = new URL(c.req.url);\n const params = parseListParams(url);\n const organizationId = url.searchParams.get('organization_id') ?? undefined;\n const resourceTypeSlug = url.searchParams.get('resource_type_slug') ?? undefined;\n\n const result = ws.authorizationResources.list({\n ...params,\n filter: (r) => {\n if (organizationId && r.organization_id !== organizationId) return false;\n if (resourceTypeSlug && r.resource_type_slug !== resourceTypeSlug) return false;\n return true;\n },\n });\n\n return c.json(formatListResponse(result, formatAuthorizationResource));\n });\n\n app.get('/authorization/resources/:resource_id', (c) => {\n const resourceId = c.req.param('resource_id');\n const resource = ws.authorizationResources.get(resourceId);\n if (!resource) throw notFound('AuthorizationResource');\n return c.json(formatAuthorizationResource(resource));\n });\n\n app.put('/authorization/resources/:resource_id', async (c) => {\n const resourceId = c.req.param('resource_id');\n const resource = ws.authorizationResources.get(resourceId);\n if (!resource) throw notFound('AuthorizationResource');\n\n const body = await parseJsonBody(c);\n const updates: Record<string, unknown> = {};\n if ('metadata' in body) updates.metadata = body.metadata;\n\n const updated = ws.authorizationResources.update(resourceId, updates);\n return c.json(formatAuthorizationResource(updated!));\n });\n\n app.delete('/authorization/resources/:resource_id', (c) => {\n const resourceId = c.req.param('resource_id');\n const resource = ws.authorizationResources.get(resourceId);\n if (!resource) throw notFound('AuthorizationResource');\n\n ws.authorizationResources.delete(resourceId);\n return c.body(null, 204);\n });\n\n // Memberships with access to a resource (by resource ID)\n app.get('/authorization/resources/:resource_id/organization_memberships', (c) => {\n const resourceId = c.req.param('resource_id');\n const resource = ws.authorizationResources.get(resourceId);\n if (!resource) throw notFound('AuthorizationResource');\n\n const memberships = ws.organizationMemberships.findBy('organization_id', resource.organization_id);\n return c.json({\n object: 'list',\n data: memberships.map(formatMembership),\n list_metadata: { before: null, after: null },\n });\n });\n\n // Get resource by type + external ID within an org\n app.get('/authorization/organizations/:orgId/resources/:type_slug/:external_id', (c) => {\n const orgId = c.req.param('orgId');\n const typeSlug = c.req.param('type_slug');\n const externalId = c.req.param('external_id');\n\n const resource = ws.authorizationResources\n .findBy('organization_id', orgId)\n .find((r) => r.resource_type_slug === typeSlug && r.external_id === externalId);\n if (!resource) throw notFound('AuthorizationResource');\n return c.json(formatAuthorizationResource(resource));\n });\n\n // Memberships for resource by type + external ID within an org\n app.get('/authorization/organizations/:orgId/resources/:type_slug/:external_id/organization_memberships', (c) => {\n const orgId = c.req.param('orgId');\n const typeSlug = c.req.param('type_slug');\n const externalId = c.req.param('external_id');\n\n const resource = ws.authorizationResources\n .findBy('organization_id', orgId)\n .find((r) => r.resource_type_slug === typeSlug && r.external_id === externalId);\n if (!resource) throw notFound('AuthorizationResource');\n\n const memberships = ws.organizationMemberships.findBy('organization_id', resource.organization_id);\n return c.json({\n object: 'list',\n data: memberships.map(formatMembership),\n list_metadata: { before: null, after: null },\n });\n });\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { findEnvRole, requireEnvRole, registerRoleRoutes } from '../role-helpers.js';
|
|
2
|
+
export function authorizationRoleRoutes(ctx) {
|
|
3
|
+
registerRoleRoutes(ctx, {
|
|
4
|
+
pathPrefix: '/authorization/roles',
|
|
5
|
+
roleType: 'EnvironmentRole',
|
|
6
|
+
requireRole: (ws, c) => requireEnvRole(ws, c.req.param('slug')),
|
|
7
|
+
findRole: (ws, _c, slug) => findEnvRole(ws, slug),
|
|
8
|
+
listFilter: () => (r) => r.type === 'EnvironmentRole',
|
|
9
|
+
insertDefaults: () => ({ organization_id: null }),
|
|
10
|
+
duplicateMessage: 'Role with this slug already exists',
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=authorization-roles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-roles.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/authorization-roles.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAErF,MAAM,UAAU,uBAAuB,CAAC,GAAiB;IACvD,kBAAkB,CAAC,GAAG,EAAE;QACtB,UAAU,EAAE,sBAAsB;QAClC,QAAQ,EAAE,iBAAiB;QAC3B,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/D,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC;QACjD,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB;QACrD,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;QACjD,gBAAgB,EAAE,oCAAoC;KACvD,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { RouteContext } from '../../core/index.js';\nimport { findEnvRole, requireEnvRole, registerRoleRoutes } from '../role-helpers.js';\n\nexport function authorizationRoleRoutes(ctx: RouteContext): void {\n registerRoleRoutes(ctx, {\n pathPrefix: '/authorization/roles',\n roleType: 'EnvironmentRole',\n requireRole: (ws, c) => requireEnvRole(ws, c.req.param('slug')),\n findRole: (ws, _c, slug) => findEnvRole(ws, slug),\n listFilter: () => (r) => r.type === 'EnvironmentRole',\n insertDefaults: () => ({ organization_id: null }),\n duplicateMessage: 'Role with this slug already exists',\n });\n}\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { parseJsonBody, WorkOSApiError, validationError } from '../../core/index.js';
|
|
2
|
+
import { getWorkOSStore } from '../store.js';
|
|
3
|
+
import { formatRedirectUri, formatCorsOrigin } from '../helpers.js';
|
|
4
|
+
import { STORE_KEYS } from '../constants.js';
|
|
5
|
+
export function configRoutes(ctx) {
|
|
6
|
+
const { app, store } = ctx;
|
|
7
|
+
const ws = getWorkOSStore(store);
|
|
8
|
+
app.post('/user_management/redirect_uris', async (c) => {
|
|
9
|
+
const body = await parseJsonBody(c);
|
|
10
|
+
const uri = body.uri;
|
|
11
|
+
if (!uri) {
|
|
12
|
+
throw validationError('uri is required', [{ field: 'uri', code: 'required' }]);
|
|
13
|
+
}
|
|
14
|
+
const existing = ws.redirectUris.findOneBy('uri', uri);
|
|
15
|
+
if (existing) {
|
|
16
|
+
throw new WorkOSApiError(422, 'Redirect URI already exists', 'redirect_uri_already_exists');
|
|
17
|
+
}
|
|
18
|
+
const redirectUri = ws.redirectUris.insert({
|
|
19
|
+
object: 'redirect_uri',
|
|
20
|
+
uri,
|
|
21
|
+
});
|
|
22
|
+
return c.json(formatRedirectUri(redirectUri), 201);
|
|
23
|
+
});
|
|
24
|
+
app.post('/user_management/cors_origins', async (c) => {
|
|
25
|
+
const body = await parseJsonBody(c);
|
|
26
|
+
const origin = body.origin;
|
|
27
|
+
if (!origin) {
|
|
28
|
+
throw validationError('origin is required', [{ field: 'origin', code: 'required' }]);
|
|
29
|
+
}
|
|
30
|
+
const existing = ws.corsOrigins.findOneBy('origin', origin);
|
|
31
|
+
if (existing) {
|
|
32
|
+
throw new WorkOSApiError(422, 'CORS origin already exists', 'cors_origin_already_exists');
|
|
33
|
+
}
|
|
34
|
+
const corsOrigin = ws.corsOrigins.insert({
|
|
35
|
+
object: 'cors_origin',
|
|
36
|
+
origin,
|
|
37
|
+
});
|
|
38
|
+
return c.json(formatCorsOrigin(corsOrigin), 201);
|
|
39
|
+
});
|
|
40
|
+
app.get('/user_management/jwt_template', (c) => {
|
|
41
|
+
const template = store.getData(STORE_KEYS.jwtTemplate) ?? {
|
|
42
|
+
object: 'jwt_template',
|
|
43
|
+
custom_claims: {},
|
|
44
|
+
};
|
|
45
|
+
return c.json(template);
|
|
46
|
+
});
|
|
47
|
+
app.put('/user_management/jwt_template', async (c) => {
|
|
48
|
+
const body = await parseJsonBody(c);
|
|
49
|
+
const template = {
|
|
50
|
+
object: 'jwt_template',
|
|
51
|
+
custom_claims: body.custom_claims ?? {},
|
|
52
|
+
};
|
|
53
|
+
store.setData(STORE_KEYS.jwtTemplate, template);
|
|
54
|
+
return c.json(template);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, parseJsonBody, WorkOSApiError, validationError } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatRedirectUri, formatCorsOrigin } from '../helpers.js';\nimport { STORE_KEYS } from '../constants.js';\n\nexport function configRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n app.post('/user_management/redirect_uris', async (c) => {\n const body = await parseJsonBody(c);\n const uri = body.uri as string | undefined;\n if (!uri) {\n throw validationError('uri is required', [{ field: 'uri', code: 'required' }]);\n }\n\n const existing = ws.redirectUris.findOneBy('uri', uri);\n if (existing) {\n throw new WorkOSApiError(422, 'Redirect URI already exists', 'redirect_uri_already_exists');\n }\n\n const redirectUri = ws.redirectUris.insert({\n object: 'redirect_uri',\n uri,\n });\n\n return c.json(formatRedirectUri(redirectUri), 201);\n });\n\n app.post('/user_management/cors_origins', async (c) => {\n const body = await parseJsonBody(c);\n const origin = body.origin as string | undefined;\n if (!origin) {\n throw validationError('origin is required', [{ field: 'origin', code: 'required' }]);\n }\n\n const existing = ws.corsOrigins.findOneBy('origin', origin);\n if (existing) {\n throw new WorkOSApiError(422, 'CORS origin already exists', 'cors_origin_already_exists');\n }\n\n const corsOrigin = ws.corsOrigins.insert({\n object: 'cors_origin',\n origin,\n });\n\n return c.json(formatCorsOrigin(corsOrigin), 201);\n });\n\n app.get('/user_management/jwt_template', (c) => {\n const template = store.getData<Record<string, unknown>>(STORE_KEYS.jwtTemplate) ?? {\n object: 'jwt_template',\n custom_claims: {},\n };\n return c.json(template);\n });\n\n app.put('/user_management/jwt_template', async (c) => {\n const body = await parseJsonBody(c);\n const template = {\n object: 'jwt_template',\n custom_claims: (body.custom_claims as Record<string, unknown>) ?? {},\n };\n store.setData(STORE_KEYS.jwtTemplate, template);\n return c.json(template);\n });\n}\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { notFound, parseJsonBody, validationError, parseListParams } from '../../core/index.js';
|
|
2
|
+
import { generateId } from '../../core/index.js';
|
|
3
|
+
import { getWorkOSStore } from '../store.js';
|
|
4
|
+
import { formatConnectApplication, formatClientSecret, generateVerificationToken, formatListResponse, } from '../helpers.js';
|
|
5
|
+
export function connectRoutes(ctx) {
|
|
6
|
+
const { app, store } = ctx;
|
|
7
|
+
const ws = getWorkOSStore(store);
|
|
8
|
+
// List applications
|
|
9
|
+
app.get('/connect/applications', (c) => {
|
|
10
|
+
const url = new URL(c.req.url);
|
|
11
|
+
const params = parseListParams(url);
|
|
12
|
+
const result = ws.connectApplications.list({ ...params });
|
|
13
|
+
return c.json(formatListResponse(result, formatConnectApplication));
|
|
14
|
+
});
|
|
15
|
+
// Create application
|
|
16
|
+
app.post('/connect/applications', async (c) => {
|
|
17
|
+
const body = await parseJsonBody(c);
|
|
18
|
+
const name = body.name;
|
|
19
|
+
if (!name || typeof name !== 'string' || name.trim().length === 0) {
|
|
20
|
+
throw validationError('name is required', [{ field: 'name', code: 'required' }]);
|
|
21
|
+
}
|
|
22
|
+
const application = ws.connectApplications.insert({
|
|
23
|
+
object: 'connect_application',
|
|
24
|
+
name: name.trim(),
|
|
25
|
+
redirect_uris: body.redirect_uris ?? [],
|
|
26
|
+
client_id: `client_${generateId('connect')}`,
|
|
27
|
+
logo_url: body.logo_url ?? null,
|
|
28
|
+
});
|
|
29
|
+
return c.json(formatConnectApplication(application), 201);
|
|
30
|
+
});
|
|
31
|
+
// Get application
|
|
32
|
+
app.get('/connect/applications/:id', (c) => {
|
|
33
|
+
const application = ws.connectApplications.get(c.req.param('id'));
|
|
34
|
+
if (!application)
|
|
35
|
+
throw notFound('ConnectApplication');
|
|
36
|
+
return c.json(formatConnectApplication(application));
|
|
37
|
+
});
|
|
38
|
+
// Create client secret
|
|
39
|
+
app.post('/connect/applications/:id/client_secrets', (c) => {
|
|
40
|
+
const application = ws.connectApplications.get(c.req.param('id'));
|
|
41
|
+
if (!application)
|
|
42
|
+
throw notFound('ConnectApplication');
|
|
43
|
+
const value = `secret_${generateVerificationToken()}`;
|
|
44
|
+
const secret = ws.clientSecrets.insert({
|
|
45
|
+
object: 'client_secret',
|
|
46
|
+
application_id: application.id,
|
|
47
|
+
value,
|
|
48
|
+
last_four: value.slice(-4),
|
|
49
|
+
});
|
|
50
|
+
// Return full value only on creation
|
|
51
|
+
return c.json({
|
|
52
|
+
...formatClientSecret(secret),
|
|
53
|
+
value: secret.value,
|
|
54
|
+
}, 201);
|
|
55
|
+
});
|
|
56
|
+
// Revoke client secret
|
|
57
|
+
app.delete('/connect/client_secrets/:id', (c) => {
|
|
58
|
+
const secret = ws.clientSecrets.get(c.req.param('id'));
|
|
59
|
+
if (!secret)
|
|
60
|
+
throw notFound('ClientSecret');
|
|
61
|
+
ws.clientSecrets.delete(secret.id);
|
|
62
|
+
return c.body(null, 204);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/connect.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, parseJsonBody, validationError, parseListParams } from '../../core/index.js';\nimport { generateId } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport {\n formatConnectApplication,\n formatClientSecret,\n generateVerificationToken,\n formatListResponse,\n} from '../helpers.js';\n\nexport function connectRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n // List applications\n app.get('/connect/applications', (c) => {\n const url = new URL(c.req.url);\n const params = parseListParams(url);\n const result = ws.connectApplications.list({ ...params });\n return c.json(formatListResponse(result, formatConnectApplication));\n });\n\n // Create application\n app.post('/connect/applications', async (c) => {\n const body = await parseJsonBody(c);\n const name = body.name as string | undefined;\n if (!name || typeof name !== 'string' || name.trim().length === 0) {\n throw validationError('name is required', [{ field: 'name', code: 'required' }]);\n }\n\n const application = ws.connectApplications.insert({\n object: 'connect_application',\n name: name.trim(),\n redirect_uris: (body.redirect_uris as string[]) ?? [],\n client_id: `client_${generateId('connect')}`,\n logo_url: (body.logo_url as string) ?? null,\n });\n\n return c.json(formatConnectApplication(application), 201);\n });\n\n // Get application\n app.get('/connect/applications/:id', (c) => {\n const application = ws.connectApplications.get(c.req.param('id'));\n if (!application) throw notFound('ConnectApplication');\n return c.json(formatConnectApplication(application));\n });\n\n // Create client secret\n app.post('/connect/applications/:id/client_secrets', (c) => {\n const application = ws.connectApplications.get(c.req.param('id'));\n if (!application) throw notFound('ConnectApplication');\n\n const value = `secret_${generateVerificationToken()}`;\n const secret = ws.clientSecrets.insert({\n object: 'client_secret',\n application_id: application.id,\n value,\n last_four: value.slice(-4),\n });\n\n // Return full value only on creation\n return c.json(\n {\n ...formatClientSecret(secret),\n value: secret.value,\n },\n 201,\n );\n });\n\n // Revoke client secret\n app.delete('/connect/client_secrets/:id', (c) => {\n const secret = ws.clientSecrets.get(c.req.param('id'));\n if (!secret) throw notFound('ClientSecret');\n ws.clientSecrets.delete(secret.id);\n return c.body(null, 204);\n });\n}\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { notFound, parseJsonBody, generateId, parseListParams } from '../../core/index.js';
|
|
2
|
+
import { getWorkOSStore } from '../store.js';
|
|
3
|
+
import { formatConnection, formatListResponse } from '../helpers.js';
|
|
4
|
+
export function connectionRoutes(ctx) {
|
|
5
|
+
const { app, store } = ctx;
|
|
6
|
+
const ws = getWorkOSStore(store);
|
|
7
|
+
app.post('/connections', async (c) => {
|
|
8
|
+
const body = await parseJsonBody(c);
|
|
9
|
+
const name = body.name;
|
|
10
|
+
const organizationId = body.organization_id;
|
|
11
|
+
const connectionType = body.connection_type ?? 'GenericSAML';
|
|
12
|
+
const domainsList = body.domains ?? [];
|
|
13
|
+
if (!organizationId) {
|
|
14
|
+
throw notFound('Organization');
|
|
15
|
+
}
|
|
16
|
+
const org = ws.organizations.get(organizationId);
|
|
17
|
+
if (!org)
|
|
18
|
+
throw notFound('Organization');
|
|
19
|
+
const domains = domainsList.map((d) => ({
|
|
20
|
+
object: 'connection_domain',
|
|
21
|
+
id: generateId('conn_domain'),
|
|
22
|
+
domain: d,
|
|
23
|
+
}));
|
|
24
|
+
const conn = ws.connections.insert({
|
|
25
|
+
object: 'connection',
|
|
26
|
+
organization_id: organizationId,
|
|
27
|
+
connection_type: connectionType,
|
|
28
|
+
name: name ?? `${org.name} SSO`,
|
|
29
|
+
state: 'active',
|
|
30
|
+
domains,
|
|
31
|
+
});
|
|
32
|
+
return c.json(formatConnection(conn), 201);
|
|
33
|
+
});
|
|
34
|
+
app.get('/connections', (c) => {
|
|
35
|
+
const url = new URL(c.req.url);
|
|
36
|
+
const params = parseListParams(url);
|
|
37
|
+
const orgFilter = url.searchParams.get('organization_id') ?? undefined;
|
|
38
|
+
const typeFilter = url.searchParams.get('connection_type') ?? undefined;
|
|
39
|
+
const domainFilter = url.searchParams.get('domain') ?? undefined;
|
|
40
|
+
const result = ws.connections.list({
|
|
41
|
+
...params,
|
|
42
|
+
filter: (conn) => {
|
|
43
|
+
if (orgFilter && conn.organization_id !== orgFilter)
|
|
44
|
+
return false;
|
|
45
|
+
if (typeFilter && conn.connection_type !== typeFilter)
|
|
46
|
+
return false;
|
|
47
|
+
if (domainFilter && !conn.domains.some((d) => d.domain === domainFilter))
|
|
48
|
+
return false;
|
|
49
|
+
return true;
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
return c.json(formatListResponse(result, formatConnection));
|
|
53
|
+
});
|
|
54
|
+
app.get('/connections/:id', (c) => {
|
|
55
|
+
const conn = ws.connections.get(c.req.param('id'));
|
|
56
|
+
if (!conn)
|
|
57
|
+
throw notFound('Connection');
|
|
58
|
+
return c.json(formatConnection(conn));
|
|
59
|
+
});
|
|
60
|
+
app.delete('/connections/:id', (c) => {
|
|
61
|
+
const conn = ws.connections.get(c.req.param('id'));
|
|
62
|
+
if (!conn)
|
|
63
|
+
throw notFound('Connection');
|
|
64
|
+
for (const auth of ws.ssoAuthorizations.all()) {
|
|
65
|
+
if (auth.connection_id === conn.id) {
|
|
66
|
+
ws.ssoAuthorizations.delete(auth.id);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
ws.connections.delete(conn.id);
|
|
70
|
+
return c.body(null, 204);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=connections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/connections.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, parseJsonBody, generateId, parseListParams } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatConnection, formatListResponse } from '../helpers.js';\nimport type { WorkOSConnectionType } from '../entities.js';\n\nexport function connectionRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n app.post('/connections', async (c) => {\n const body = await parseJsonBody(c);\n const name = body.name as string;\n const organizationId = body.organization_id as string;\n const connectionType = (body.connection_type as WorkOSConnectionType) ?? 'GenericSAML';\n const domainsList = (body.domains as string[]) ?? [];\n\n if (!organizationId) {\n throw notFound('Organization');\n }\n const org = ws.organizations.get(organizationId);\n if (!org) throw notFound('Organization');\n\n const domains = domainsList.map((d) => ({\n object: 'connection_domain' as const,\n id: generateId('conn_domain'),\n domain: d,\n }));\n\n const conn = ws.connections.insert({\n object: 'connection',\n organization_id: organizationId,\n connection_type: connectionType,\n name: name ?? `${org.name} SSO`,\n state: 'active',\n domains,\n });\n\n return c.json(formatConnection(conn), 201);\n });\n\n app.get('/connections', (c) => {\n const url = new URL(c.req.url);\n const params = parseListParams(url);\n const orgFilter = url.searchParams.get('organization_id') ?? undefined;\n const typeFilter = url.searchParams.get('connection_type') ?? undefined;\n const domainFilter = url.searchParams.get('domain') ?? undefined;\n\n const result = ws.connections.list({\n ...params,\n filter: (conn) => {\n if (orgFilter && conn.organization_id !== orgFilter) return false;\n if (typeFilter && conn.connection_type !== typeFilter) return false;\n if (domainFilter && !conn.domains.some((d) => d.domain === domainFilter)) return false;\n return true;\n },\n });\n\n return c.json(formatListResponse(result, formatConnection));\n });\n\n app.get('/connections/:id', (c) => {\n const conn = ws.connections.get(c.req.param('id'));\n if (!conn) throw notFound('Connection');\n return c.json(formatConnection(conn));\n });\n\n app.delete('/connections/:id', (c) => {\n const conn = ws.connections.get(c.req.param('id'));\n if (!conn) throw notFound('Connection');\n\n for (const auth of ws.ssoAuthorizations.all()) {\n if (auth.connection_id === conn.id) {\n ws.ssoAuthorizations.delete(auth.id);\n }\n }\n\n ws.connections.delete(conn.id);\n return c.body(null, 204);\n });\n}\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { parseJsonBody, WorkOSApiError } from '../../core/index.js';
|
|
2
|
+
import { getWorkOSStore } from '../store.js';
|
|
3
|
+
import { assertLocalRedirectUri, generateVerificationToken, expiresIn, isExpired } from '../helpers.js';
|
|
4
|
+
export function dataIntegrationRoutes(ctx) {
|
|
5
|
+
const { app, store } = ctx;
|
|
6
|
+
const ws = getWorkOSStore(store);
|
|
7
|
+
// Authorize (public endpoint — no auth required)
|
|
8
|
+
app.get('/data-integrations/:slug/authorize', (c) => {
|
|
9
|
+
const slug = c.req.param('slug');
|
|
10
|
+
const url = new URL(c.req.url);
|
|
11
|
+
const redirectUri = url.searchParams.get('redirect_uri');
|
|
12
|
+
const state = url.searchParams.get('state') ?? null;
|
|
13
|
+
if (!redirectUri) {
|
|
14
|
+
throw new WorkOSApiError(400, 'redirect_uri is required', 'invalid_request');
|
|
15
|
+
}
|
|
16
|
+
assertLocalRedirectUri(redirectUri);
|
|
17
|
+
const code = generateVerificationToken();
|
|
18
|
+
ws.dataIntegrationAuths.insert({
|
|
19
|
+
slug,
|
|
20
|
+
code,
|
|
21
|
+
redirect_uri: redirectUri,
|
|
22
|
+
state,
|
|
23
|
+
expires_at: expiresIn(10),
|
|
24
|
+
});
|
|
25
|
+
const redirect = new URL(redirectUri);
|
|
26
|
+
redirect.searchParams.set('code', code);
|
|
27
|
+
if (state)
|
|
28
|
+
redirect.searchParams.set('state', state);
|
|
29
|
+
return c.redirect(redirect.toString(), 302);
|
|
30
|
+
});
|
|
31
|
+
// Exchange code for token
|
|
32
|
+
app.post('/data-integrations/:slug/token', async (c) => {
|
|
33
|
+
const slug = c.req.param('slug');
|
|
34
|
+
const body = await parseJsonBody(c);
|
|
35
|
+
const code = body.code;
|
|
36
|
+
if (!code) {
|
|
37
|
+
throw new WorkOSApiError(400, 'code is required', 'invalid_request');
|
|
38
|
+
}
|
|
39
|
+
const auth = ws.dataIntegrationAuths.findOneBy('code', code);
|
|
40
|
+
if (!auth || auth.slug !== slug) {
|
|
41
|
+
throw new WorkOSApiError(400, 'Invalid authorization code', 'invalid_grant');
|
|
42
|
+
}
|
|
43
|
+
if (isExpired(auth.expires_at)) {
|
|
44
|
+
ws.dataIntegrationAuths.delete(auth.id);
|
|
45
|
+
throw new WorkOSApiError(400, 'Authorization code has expired', 'invalid_grant');
|
|
46
|
+
}
|
|
47
|
+
ws.dataIntegrationAuths.delete(auth.id);
|
|
48
|
+
return c.json({
|
|
49
|
+
access_token: `di_mock_${slug}_${generateVerificationToken().slice(0, 8)}`,
|
|
50
|
+
token_type: 'bearer',
|
|
51
|
+
expires_in: 3600,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=data-integrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-integrations.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/data-integrations.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, parseJsonBody, WorkOSApiError } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { assertLocalRedirectUri, generateVerificationToken, expiresIn, isExpired } from '../helpers.js';\n\nexport function dataIntegrationRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n // Authorize (public endpoint — no auth required)\n app.get('/data-integrations/:slug/authorize', (c) => {\n const slug = c.req.param('slug');\n const url = new URL(c.req.url);\n const redirectUri = url.searchParams.get('redirect_uri');\n const state = url.searchParams.get('state') ?? null;\n\n if (!redirectUri) {\n throw new WorkOSApiError(400, 'redirect_uri is required', 'invalid_request');\n }\n assertLocalRedirectUri(redirectUri);\n\n const code = generateVerificationToken();\n ws.dataIntegrationAuths.insert({\n slug,\n code,\n redirect_uri: redirectUri,\n state,\n expires_at: expiresIn(10),\n });\n\n const redirect = new URL(redirectUri);\n redirect.searchParams.set('code', code);\n if (state) redirect.searchParams.set('state', state);\n\n return c.redirect(redirect.toString(), 302);\n });\n\n // Exchange code for token\n app.post('/data-integrations/:slug/token', async (c) => {\n const slug = c.req.param('slug');\n const body = await parseJsonBody(c);\n const code = body.code as string | undefined;\n\n if (!code) {\n throw new WorkOSApiError(400, 'code is required', 'invalid_request');\n }\n\n const auth = ws.dataIntegrationAuths.findOneBy('code', code);\n if (!auth || auth.slug !== slug) {\n throw new WorkOSApiError(400, 'Invalid authorization code', 'invalid_grant');\n }\n\n if (isExpired(auth.expires_at)) {\n ws.dataIntegrationAuths.delete(auth.id);\n throw new WorkOSApiError(400, 'Authorization code has expired', 'invalid_grant');\n }\n\n ws.dataIntegrationAuths.delete(auth.id);\n\n return c.json({\n access_token: `di_mock_${slug}_${generateVerificationToken().slice(0, 8)}`,\n token_type: 'bearer',\n expires_in: 3600,\n });\n });\n}\n"]}
|