@simple-auth-kit/cli 1.5.1 → 1.6.1
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/package.json +1 -1
- package/registry/combos/express-drizzle/shared/src/{ability.ts → ability/ability.ts} +8 -2
- package/registry/combos/express-drizzle/shared/src/{permission-cache.ts → cache/permission-cache.ts} +25 -9
- package/registry/combos/express-drizzle/shared/src/{rate-limit.store.ts → cache/rate-limit.store.ts} +4 -1
- package/registry/combos/{express-prisma/shared/src → express-drizzle/shared/src/config}/auth.config.ts +1 -1
- package/registry/combos/express-drizzle/shared/src/{db.ts → config/db.ts} +1 -1
- package/registry/combos/express-drizzle/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
- package/registry/combos/express-drizzle/shared/src/{id.helper.ts → helpers/id.helper.ts} +6 -2
- package/registry/combos/{nestjs-drizzle/shared/src → express-drizzle/shared/src/helpers}/pagination.ts +17 -3
- package/registry/combos/express-drizzle/shared/src/middleware/auth-core-error.middleware.ts +6 -8
- package/registry/combos/express-drizzle/shared/src/middleware/auth.middleware.ts +6 -8
- package/registry/combos/{express-prisma/shared/src → express-drizzle/shared/src/openapi}/openapi-fragment.ts +13 -4
- package/registry/combos/express-drizzle/shared/src/{openapi-spec.ts → openapi/openapi-spec.ts} +251 -52
- package/registry/combos/express-drizzle/shared/src/repositories/oauth.repository.ts +2 -2
- package/registry/combos/express-drizzle/shared/src/repositories/password-reset.repository.ts +2 -4
- package/registry/combos/express-drizzle/shared/src/repositories/session.repository.ts +3 -3
- package/registry/combos/express-drizzle/shared/src/request-context.ts +1 -1
- package/registry/combos/express-drizzle/shared/src/route-tiers.ts +52 -11
- package/registry/combos/express-drizzle/shared/src/routers/auth.router.ts +2 -2
- package/registry/combos/express-drizzle/test/bootstrap.ts +4 -2
- package/registry/combos/express-drizzle/test/prove-cycle.ts +1095 -308
- package/registry/combos/express-drizzle/variants/base/src/create-auth-app.ts +5 -5
- package/registry/combos/express-drizzle/variants/base/src/index.ts +8 -0
- package/registry/combos/express-drizzle/variants/base/src/middleware/authz.middleware.ts +2 -2
- package/registry/combos/express-drizzle/variants/base/src/openapi/openapi-admin.ts +1082 -0
- package/registry/combos/express-drizzle/variants/base/src/rbac.defaults.ts +60 -17
- package/registry/combos/express-drizzle/variants/base/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/express-drizzle/variants/base/src/repositories/rbac.repository.ts +5 -5
- package/registry/combos/express-drizzle/variants/base/src/routers/admin.router.ts +18 -22
- package/registry/combos/express-drizzle/variants/base/src/seed.ts +76 -17
- package/registry/combos/express-drizzle/variants/base/src/services/auth.service.ts +7 -9
- package/registry/combos/express-drizzle/variants/base/test/variant-hooks.ts +167 -45
- package/registry/combos/express-drizzle/variants/workspaces/src/create-auth-app.ts +5 -5
- package/registry/combos/express-drizzle/variants/workspaces/src/index.ts +8 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/middleware/authz.middleware.ts +3 -3
- package/registry/combos/express-drizzle/variants/workspaces/src/openapi/openapi-admin.ts +1176 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/openapi-workspace.ts +1 -1
- package/registry/combos/express-drizzle/variants/workspaces/src/rbac.defaults.ts +66 -19
- package/registry/combos/express-drizzle/variants/workspaces/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/express-drizzle/variants/workspaces/src/repositories/rbac.repository.ts +5 -5
- package/registry/combos/express-drizzle/variants/workspaces/src/repositories/workspace.repository.ts +9 -11
- package/registry/combos/express-drizzle/variants/workspaces/src/routers/admin.router.ts +18 -22
- package/registry/combos/express-drizzle/variants/workspaces/src/routers/workspace.router.ts +1 -1
- package/registry/combos/express-drizzle/variants/workspaces/src/seed.ts +168 -35
- package/registry/combos/express-drizzle/variants/workspaces/src/services/auth.service.ts +7 -9
- package/registry/combos/express-drizzle/variants/workspaces/test/variant-hooks.ts +539 -133
- package/registry/combos/express-prisma/shared/src/{ability.ts → ability/ability.ts} +8 -2
- package/registry/combos/express-prisma/shared/src/{permission-cache.ts → cache/permission-cache.ts} +25 -9
- package/registry/combos/express-prisma/shared/src/{rate-limit.store.ts → cache/rate-limit.store.ts} +4 -1
- package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/config}/auth.config.ts +1 -1
- package/registry/combos/express-prisma/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
- package/registry/combos/{nestjs-prisma/shared/src → express-prisma/shared/src/helpers}/id.helper.ts +6 -2
- package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/helpers}/pagination.ts +17 -3
- package/registry/combos/express-prisma/shared/src/middleware/auth-core-error.middleware.ts +6 -8
- package/registry/combos/express-prisma/shared/src/middleware/auth.middleware.ts +6 -8
- package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/openapi}/openapi-fragment.ts +13 -4
- package/registry/combos/express-prisma/shared/src/{openapi-spec.ts → openapi/openapi-spec.ts} +313 -55
- package/registry/combos/express-prisma/shared/src/repositories/oauth.repository.ts +2 -2
- package/registry/combos/express-prisma/shared/src/repositories/password-reset.repository.ts +2 -4
- package/registry/combos/express-prisma/shared/src/repositories/session.repository.ts +2 -2
- package/registry/combos/express-prisma/shared/src/request-context.ts +1 -1
- package/registry/combos/express-prisma/shared/src/route-tiers.ts +52 -11
- package/registry/combos/express-prisma/shared/src/routers/auth.router.ts +2 -2
- package/registry/combos/express-prisma/test/bootstrap.ts +7 -3
- package/registry/combos/express-prisma/test/prove-cycle.ts +1095 -308
- package/registry/combos/express-prisma/variants/base/src/create-auth-app.ts +6 -6
- package/registry/combos/express-prisma/variants/base/src/index.ts +8 -0
- package/registry/combos/express-prisma/variants/base/src/middleware/authz.middleware.ts +2 -2
- package/registry/combos/express-prisma/variants/base/src/openapi/openapi-admin.ts +1102 -0
- package/registry/combos/express-prisma/variants/base/src/rbac.defaults.ts +1 -1
- package/registry/combos/express-prisma/variants/base/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/express-prisma/variants/base/src/repositories/rbac.repository.ts +4 -4
- package/registry/combos/express-prisma/variants/base/src/routers/admin.router.ts +18 -22
- package/registry/combos/express-prisma/variants/base/src/seed.ts +1 -1
- package/registry/combos/express-prisma/variants/base/src/services/auth.service.ts +6 -8
- package/registry/combos/express-prisma/variants/base/test/variant-hooks.ts +176 -47
- package/registry/combos/express-prisma/variants/workspaces/src/create-auth-app.ts +6 -6
- package/registry/combos/express-prisma/variants/workspaces/src/index.ts +8 -0
- package/registry/combos/express-prisma/variants/workspaces/src/middleware/authz.middleware.ts +3 -3
- package/registry/combos/express-prisma/variants/workspaces/src/openapi/openapi-admin.ts +1218 -0
- package/registry/combos/express-prisma/variants/workspaces/src/openapi-workspace.ts +1 -1
- package/registry/combos/express-prisma/variants/workspaces/src/rbac.defaults.ts +1 -1
- package/registry/combos/express-prisma/variants/workspaces/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/express-prisma/variants/workspaces/src/repositories/rbac.repository.ts +4 -4
- package/registry/combos/express-prisma/variants/workspaces/src/repositories/workspace.repository.ts +2 -2
- package/registry/combos/express-prisma/variants/workspaces/src/routers/admin.router.ts +18 -22
- package/registry/combos/express-prisma/variants/workspaces/src/routers/workspace.router.ts +1 -1
- package/registry/combos/express-prisma/variants/workspaces/src/seed.ts +1 -1
- package/registry/combos/express-prisma/variants/workspaces/src/services/auth.service.ts +6 -8
- package/registry/combos/express-prisma/variants/workspaces/test/variant-hooks.ts +538 -134
- package/registry/combos/nestjs-drizzle/shared/src/{guards → ability}/ability.guard.ts +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/{ability.ts → ability/ability.ts} +8 -2
- package/registry/combos/nestjs-drizzle/shared/src/{permission-cache.ts → cache/permission-cache.ts} +27 -10
- package/registry/combos/{nestjs-prisma/shared/src → nestjs-drizzle/shared/src/cache}/rate-limit.store.ts +4 -1
- package/registry/combos/nestjs-drizzle/shared/src/{auth.config.ts → config/auth.config.ts} +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/{db.ts → config/db.ts} +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
- package/registry/combos/nestjs-drizzle/shared/src/controllers/auth.controller.ts +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/guards/auth.guard.ts +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/{id.helper.ts → helpers/id.helper.ts} +6 -2
- package/registry/combos/{express-prisma/shared/src → nestjs-drizzle/shared/src/helpers}/pagination.ts +17 -3
- package/registry/combos/nestjs-drizzle/shared/src/repositories/oauth.repository.ts +2 -2
- package/registry/combos/nestjs-drizzle/shared/src/repositories/password-reset.repository.ts +8 -12
- package/registry/combos/nestjs-drizzle/shared/src/repositories/session.repository.ts +3 -3
- package/registry/combos/nestjs-drizzle/shared/src/repositories/two-factor.repository.ts +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/request-context.ts +1 -1
- package/registry/combos/nestjs-drizzle/test/bootstrap.ts +1 -1
- package/registry/combos/nestjs-drizzle/test/prove-cycle.ts +1 -1
- package/registry/combos/nestjs-drizzle/variants/base/src/auth.module.ts +10 -6
- package/registry/combos/nestjs-drizzle/variants/base/src/controllers/admin.controller.ts +1 -1
- package/registry/combos/nestjs-drizzle/variants/base/src/guards/authz.guard.ts +2 -2
- package/registry/combos/nestjs-drizzle/variants/base/src/index.ts +9 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/rbac.defaults.ts +58 -16
- package/registry/combos/nestjs-drizzle/variants/base/src/repositories/audit-log.repository.ts +3 -3
- package/registry/combos/nestjs-drizzle/variants/base/src/repositories/rbac.repository.ts +4 -4
- package/registry/combos/nestjs-drizzle/variants/base/src/seed.ts +76 -17
- package/registry/combos/nestjs-drizzle/variants/base/src/services/auth.service.ts +7 -9
- package/registry/combos/nestjs-drizzle/variants/base/test/variant-hooks.ts +167 -45
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.module.ts +10 -6
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/controllers/admin.controller.ts +1 -1
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/controllers/workspace.controller.ts +1 -1
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/guards/authz.guard.ts +2 -2
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/index.ts +9 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/rbac.defaults.ts +64 -18
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/repositories/audit-log.repository.ts +3 -3
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/repositories/rbac.repository.ts +4 -4
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/repositories/workspace.repository.ts +8 -10
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/seed.ts +171 -36
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/services/auth.service.ts +7 -9
- package/registry/combos/nestjs-drizzle/variants/workspaces/test/variant-hooks.ts +539 -133
- package/registry/combos/nestjs-prisma/shared/src/{guards → ability}/ability.guard.ts +1 -1
- package/registry/combos/nestjs-prisma/shared/src/{ability.ts → ability/ability.ts} +8 -2
- package/registry/combos/nestjs-prisma/shared/src/{permission-cache.ts → cache/permission-cache.ts} +27 -10
- package/registry/combos/{nestjs-drizzle/shared/src → nestjs-prisma/shared/src/cache}/rate-limit.store.ts +4 -1
- package/registry/combos/nestjs-prisma/shared/src/{auth.config.ts → config/auth.config.ts} +1 -1
- package/registry/combos/nestjs-prisma/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
- package/registry/combos/nestjs-prisma/shared/src/controllers/auth.controller.ts +1 -1
- package/registry/combos/nestjs-prisma/shared/src/guards/auth.guard.ts +1 -1
- package/registry/combos/{express-prisma/shared/src → nestjs-prisma/shared/src/helpers}/id.helper.ts +6 -2
- package/registry/combos/nestjs-prisma/shared/src/{pagination.ts → helpers/pagination.ts} +17 -3
- package/registry/combos/nestjs-prisma/shared/src/repositories/oauth.repository.ts +1 -1
- package/registry/combos/nestjs-prisma/shared/src/repositories/password-reset.repository.ts +2 -4
- package/registry/combos/nestjs-prisma/shared/src/repositories/session.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/shared/src/request-context.ts +1 -1
- package/registry/combos/nestjs-prisma/test/bootstrap.ts +1 -1
- package/registry/combos/nestjs-prisma/test/prove-cycle.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/auth.module.ts +10 -6
- package/registry/combos/nestjs-prisma/variants/base/src/controllers/admin.controller.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/gateways/audit-log.gateway.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/guards/authz.guard.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/base/src/index.ts +9 -0
- package/registry/combos/nestjs-prisma/variants/base/src/{docs.ts → openapi/docs.ts} +23 -6
- package/registry/combos/nestjs-prisma/variants/base/src/rbac.defaults.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/country.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/customer.repository.ts +6 -5
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/language.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/rbac.repository.ts +3 -3
- package/registry/combos/nestjs-prisma/variants/base/src/seed.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/services/auth.service.ts +6 -8
- package/registry/combos/nestjs-prisma/variants/base/test/variant-hooks.ts +176 -47
- package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.module.ts +10 -6
- package/registry/combos/nestjs-prisma/variants/workspaces/src/controllers/admin.controller.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/controllers/workspace.controller.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/guards/authz.guard.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/workspaces/src/index.ts +9 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.defaults.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/country.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/customer.repository.ts +6 -5
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/language.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/rbac.repository.ts +3 -3
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/workspace.repository.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/seed.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/services/auth.service.ts +6 -8
- package/registry/combos/nestjs-prisma/variants/workspaces/test/variant-hooks.ts +538 -134
- package/registry/combos/express-drizzle/variants/base/src/openapi-admin.ts +0 -565
- package/registry/combos/express-drizzle/variants/workspaces/src/openapi-admin.ts +0 -596
- package/registry/combos/express-prisma/variants/base/src/openapi-admin.ts +0 -569
- package/registry/combos/express-prisma/variants/workspaces/src/openapi-admin.ts +0 -601
- /package/registry/combos/express-drizzle/shared/src/{http-error.ts → errors/http-error.ts} +0 -0
- /package/registry/combos/express-prisma/shared/src/{http-error.ts → errors/http-error.ts} +0 -0
|
@@ -1,565 +0,0 @@
|
|
|
1
|
-
// The administration half of the OpenAPI document, merged into the assembled spec by
|
|
2
|
-
// openapi-spec.ts. Mirrors the reference combo's `dto/admin.dto.ts`: the identity endpoints are
|
|
3
|
-
// documented once, in the shared half, and everything administration adds lives here.
|
|
4
|
-
//
|
|
5
|
-
// Administration is deployment-wide, so nothing below names a narrower scope: an admin here is
|
|
6
|
-
// an admin of everything.
|
|
7
|
-
//
|
|
8
|
-
// Every path is gated on exactly one key from `rbac.defaults.ts` and there is no role-based
|
|
9
|
-
// bypass, which is why the 403s say which permission was missing rather than "admin role
|
|
10
|
-
// required": holding a role called "admin" that carries nothing gets the same answer as holding
|
|
11
|
-
// no role at all.
|
|
12
|
-
import { errorResponse, missingPermission, requiresPermission, type OpenApiFragment } from "./openapi-fragment.js";
|
|
13
|
-
|
|
14
|
-
export const adminSpec: OpenApiFragment = {
|
|
15
|
-
tags: [],
|
|
16
|
-
|
|
17
|
-
scopeParameters: [],
|
|
18
|
-
|
|
19
|
-
schemas: {
|
|
20
|
-
PermissionSummary: {
|
|
21
|
-
type: "object",
|
|
22
|
-
properties: {
|
|
23
|
-
id: { type: "string" },
|
|
24
|
-
slug: {
|
|
25
|
-
type: "string",
|
|
26
|
-
description: "The ability itself: `ability(slug)` on the server, `ability.can(slug, ABILITY_SUBJECT)` in a client.",
|
|
27
|
-
example: "users:read",
|
|
28
|
-
},
|
|
29
|
-
displayName: { type: "string", example: "List users" },
|
|
30
|
-
description: { type: "string", nullable: true },
|
|
31
|
-
group: { type: "string", description: "Console grouping — a permission matrix renders one section per group.", example: "Users" },
|
|
32
|
-
groupOrder: { type: "integer" },
|
|
33
|
-
order: { type: "integer" },
|
|
34
|
-
isActive: {
|
|
35
|
-
type: "boolean",
|
|
36
|
-
description: "false takes the permission out of every ability that would otherwise carry it, without unpicking a single grant.",
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
PermissionListResponse: {
|
|
41
|
-
type: "object",
|
|
42
|
-
properties: { permissions: { type: "array", items: { $ref: "#/components/schemas/PermissionSummary" } } },
|
|
43
|
-
},
|
|
44
|
-
DefinePermissionRequest: {
|
|
45
|
-
type: "object",
|
|
46
|
-
required: ["slug"],
|
|
47
|
-
properties: {
|
|
48
|
-
slug: { type: "string", example: "billing:manage" },
|
|
49
|
-
displayName: { type: "string", description: "Defaults to the slug when creating." },
|
|
50
|
-
description: { type: "string", nullable: true },
|
|
51
|
-
group: { type: "string", description: 'Defaults to "Custom" when creating.' },
|
|
52
|
-
groupOrder: { type: "integer" },
|
|
53
|
-
order: { type: "integer" },
|
|
54
|
-
isActive: { type: "boolean" },
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
RoleListResponse: {
|
|
58
|
-
type: "object",
|
|
59
|
-
properties: { roles: { type: "array", items: { $ref: "#/components/schemas/RoleSummary" } } },
|
|
60
|
-
},
|
|
61
|
-
CreateRoleRequest: {
|
|
62
|
-
type: "object",
|
|
63
|
-
required: ["slug"],
|
|
64
|
-
properties: {
|
|
65
|
-
slug: { type: "string", description: "Stable identifier. Grants and assignments are keyed on it.", example: "billing-manager" },
|
|
66
|
-
displayName: { type: "string", description: "Human label for the console. Defaults to the slug.", example: "Billing manager" },
|
|
67
|
-
description: { type: "string", nullable: true },
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
AttachPermissionRequest: {
|
|
71
|
-
type: "object",
|
|
72
|
-
required: ["permission"],
|
|
73
|
-
properties: {
|
|
74
|
-
permission: { type: "string", example: "billing:manage" },
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
AssignRoleRequest: {
|
|
78
|
-
type: "object",
|
|
79
|
-
required: ["role"],
|
|
80
|
-
properties: {
|
|
81
|
-
role: { type: "string", description: "Role slug", example: "billing-manager" },
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
GrantPermissionRequest: {
|
|
85
|
-
type: "object",
|
|
86
|
-
required: ["permission"],
|
|
87
|
-
properties: {
|
|
88
|
-
permission: { type: "string", example: "billing:manage" },
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
CreateUserRequest: {
|
|
92
|
-
type: "object",
|
|
93
|
-
required: ["email", "password"],
|
|
94
|
-
description: "No invitation email — the account is usable immediately with the password given here.",
|
|
95
|
-
properties: {
|
|
96
|
-
email: { type: "string", example: "alice@example.com" },
|
|
97
|
-
password: { type: "string", description: "Set directly — there is no invitation email, the account is usable immediately." },
|
|
98
|
-
firstName: { type: "string" },
|
|
99
|
-
lastName: { type: "string" },
|
|
100
|
-
displayName: { type: "string" },
|
|
101
|
-
phone: { type: "string" },
|
|
102
|
-
username: { type: "string" },
|
|
103
|
-
roles: { type: "array", items: { type: "string" }, description: "Role slugs to assign. Defaults to whichever roles are flagged isDefault, same as a self-signup." },
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
UpdateUserRequest: {
|
|
107
|
-
type: "object",
|
|
108
|
-
description: "Profile fields only — email is the login identifier and is not editable here. Any field may be sent as `null` to clear it.",
|
|
109
|
-
properties: {
|
|
110
|
-
firstName: { type: "string", nullable: true },
|
|
111
|
-
lastName: { type: "string", nullable: true },
|
|
112
|
-
displayName: { type: "string", nullable: true },
|
|
113
|
-
phone: { type: "string", nullable: true },
|
|
114
|
-
username: { type: "string", nullable: true },
|
|
115
|
-
photo: { type: "string", nullable: true },
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
UpdateRoleRequest: {
|
|
119
|
-
type: "object",
|
|
120
|
-
properties: {
|
|
121
|
-
name: { type: "string" },
|
|
122
|
-
displayName: { type: "string" },
|
|
123
|
-
description: { type: "string", nullable: true },
|
|
124
|
-
isActive: { type: "boolean", description: "false suspends the role without deleting it; every assignment pointing at it survives." },
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
DeleteReasonRequest: {
|
|
128
|
-
type: "object",
|
|
129
|
-
properties: {
|
|
130
|
-
reason: { type: "string", description: "Free-text note recorded alongside the soft-delete, for whoever reads the row later." },
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
RoleSummary: {
|
|
134
|
-
type: "object",
|
|
135
|
-
required: ["id", "slug", "displayName", "isDefault", "isActive"],
|
|
136
|
-
properties: {
|
|
137
|
-
id: { type: "string" },
|
|
138
|
-
slug: { type: "string", example: "billing-manager" },
|
|
139
|
-
displayName: { type: "string", example: "Billing manager" },
|
|
140
|
-
isDefault: { type: "boolean", description: "Given to every new principal. The signup/membership default is this row, not a name spelled in code." },
|
|
141
|
-
isActive: { type: "boolean", description: "false suspends the role without deleting it; every assignment pointing at it survives." },
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
UserSummary: {
|
|
145
|
-
type: "object",
|
|
146
|
-
required: ["id", "uuid", "email", "blocked", "isActive", "twoFactorEnabled", "roles", "createdBy", "updatedBy", "createdAt", "updatedAt"],
|
|
147
|
-
properties: {
|
|
148
|
-
id: { type: "string" },
|
|
149
|
-
uuid: { type: "string" },
|
|
150
|
-
email: { type: "string" },
|
|
151
|
-
firstName: { type: "string", nullable: true, description: "Unique across the deployment." },
|
|
152
|
-
lastName: { type: "string", nullable: true, description: "Unique across the deployment." },
|
|
153
|
-
displayName: { type: "string", nullable: true },
|
|
154
|
-
phone: { type: "string", nullable: true, description: "Unique across the deployment." },
|
|
155
|
-
username: { type: "string", nullable: true, description: "Unique across the deployment." },
|
|
156
|
-
photo: { type: "string", nullable: true },
|
|
157
|
-
lastLogin: { type: "string", format: "date-time", nullable: true, description: "ISO 8601. Set on every successful signup/login/OAuth callback, never on a token refresh." },
|
|
158
|
-
blocked: { type: "boolean", description: "Security/moderation block — distinct from isActive, see the model note." },
|
|
159
|
-
isActive: { type: "boolean", description: "Routine administrative on/off toggle — distinct from blocked, see the model note." },
|
|
160
|
-
twoFactorEnabled: { type: "boolean" },
|
|
161
|
-
roles: { type: "array", items: { type: "string" } },
|
|
162
|
-
createdBy: { type: "string", nullable: true, description: "User id of whoever created this account, if it wasn't a self-signup." },
|
|
163
|
-
updatedBy: { type: "string", nullable: true, description: "User id of whoever last edited this account's profile." },
|
|
164
|
-
createdAt: { type: "string", format: "date-time" },
|
|
165
|
-
updatedAt: { type: "string", format: "date-time" },
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
PageMeta: {
|
|
169
|
-
type: "object",
|
|
170
|
-
required: ["page", "limit", "total", "pageCount", "hasPreviousPage", "hasNextPage"],
|
|
171
|
-
properties: {
|
|
172
|
-
page: { type: "integer", description: "1-indexed" },
|
|
173
|
-
limit: { type: "integer" },
|
|
174
|
-
total: { type: "integer" },
|
|
175
|
-
pageCount: { type: "integer" },
|
|
176
|
-
hasPreviousPage: { type: "boolean" },
|
|
177
|
-
hasNextPage: { type: "boolean" },
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
UserListResponse: {
|
|
181
|
-
type: "object",
|
|
182
|
-
required: ["items", "meta"],
|
|
183
|
-
properties: {
|
|
184
|
-
items: { type: "array", items: { $ref: "#/components/schemas/UserSummary" } },
|
|
185
|
-
meta: { $ref: "#/components/schemas/PageMeta" },
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
AuditLogEntry: {
|
|
189
|
-
type: "object",
|
|
190
|
-
required: ["id", "userId", "name", "action", "info", "remarks", "createdAt", "updatedAt"],
|
|
191
|
-
properties: {
|
|
192
|
-
id: { type: "string" },
|
|
193
|
-
userId: { type: "string", nullable: true, description: "Who the event is about; null when it is not attributable to one user" },
|
|
194
|
-
name: { type: "string", description: "Human-readable label for `action`", example: "Role assigned" },
|
|
195
|
-
action: { type: "string", description: "AuditEvent discriminant", example: "role_assigned" },
|
|
196
|
-
info: { type: "object", description: "The rest of the event's fields" },
|
|
197
|
-
remarks: { type: "string", nullable: true },
|
|
198
|
-
createdAt: { type: "string", format: "date-time" },
|
|
199
|
-
updatedAt: { type: "string", format: "date-time" },
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
AuditLogListResponse: {
|
|
203
|
-
type: "object",
|
|
204
|
-
required: ["items", "meta"],
|
|
205
|
-
properties: {
|
|
206
|
-
items: { type: "array", items: { $ref: "#/components/schemas/AuditLogEntry" } },
|
|
207
|
-
meta: { $ref: "#/components/schemas/PageMeta" },
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
|
|
212
|
-
paths: {
|
|
213
|
-
"/auth/admin/users": {
|
|
214
|
-
get: {
|
|
215
|
-
tags: ["auth"],
|
|
216
|
-
summary: "[admin] List users",
|
|
217
|
-
description: requiresPermission("users:read"),
|
|
218
|
-
security: [{ bearerAuth: [] }],
|
|
219
|
-
parameters: [
|
|
220
|
-
{ name: "search", in: "query", required: false, schema: { type: "string" }, description: "Email substring match" },
|
|
221
|
-
{ name: "page", in: "query", required: false, schema: { type: "integer" }, description: "1-indexed. Defaults to 1." },
|
|
222
|
-
{ name: "limit", in: "query", required: false, schema: { type: "integer" }, description: "Defaults to 25, capped at 100." },
|
|
223
|
-
],
|
|
224
|
-
responses: {
|
|
225
|
-
"200": { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/UserListResponse" } } } },
|
|
226
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
227
|
-
"403": missingPermission("users:read"),
|
|
228
|
-
},
|
|
229
|
-
},
|
|
230
|
-
post: {
|
|
231
|
-
tags: ["auth"],
|
|
232
|
-
summary: "[admin] Create a user directly",
|
|
233
|
-
description: requiresPermission("users:manage") + " No invitation email — the account is usable immediately with the password given here.",
|
|
234
|
-
security: [{ bearerAuth: [] }],
|
|
235
|
-
requestBody: {
|
|
236
|
-
required: true,
|
|
237
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/CreateUserRequest" } } },
|
|
238
|
-
},
|
|
239
|
-
responses: {
|
|
240
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/UserSummary" } } } },
|
|
241
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
242
|
-
"403": missingPermission("users:manage"),
|
|
243
|
-
"409": errorResponse("Email already registered"),
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
"/auth/admin/users/{userId}": {
|
|
248
|
-
get: {
|
|
249
|
-
tags: ["auth"],
|
|
250
|
-
summary: "[admin] Fetch a single user",
|
|
251
|
-
description: requiresPermission("users:read"),
|
|
252
|
-
security: [{ bearerAuth: [] }],
|
|
253
|
-
parameters: [{ name: "userId", in: "path", required: true, schema: { type: "string" } }],
|
|
254
|
-
responses: {
|
|
255
|
-
"200": { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/UserSummary" } } } },
|
|
256
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
257
|
-
"403": missingPermission("users:read"),
|
|
258
|
-
"404": errorResponse("User not found"),
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
patch: {
|
|
262
|
-
tags: ["auth"],
|
|
263
|
-
summary: "[admin] Edit a user's profile",
|
|
264
|
-
description: requiresPermission("users:manage") + " Profile fields only — email is the login identifier and is not editable here.",
|
|
265
|
-
security: [{ bearerAuth: [] }],
|
|
266
|
-
parameters: [{ name: "userId", in: "path", required: true, schema: { type: "string" } }],
|
|
267
|
-
requestBody: {
|
|
268
|
-
required: true,
|
|
269
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/UpdateUserRequest" } } },
|
|
270
|
-
},
|
|
271
|
-
responses: {
|
|
272
|
-
"200": { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/UserSummary" } } } },
|
|
273
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
274
|
-
"403": missingPermission("users:manage"),
|
|
275
|
-
"404": errorResponse("User not found"),
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
delete: {
|
|
279
|
-
tags: ["auth"],
|
|
280
|
-
summary: "[admin] Delete a user",
|
|
281
|
-
description:
|
|
282
|
-
requiresPermission("users:manage") +
|
|
283
|
-
" Soft-delete: the row survives for audit purposes, stops appearing in listings, and can no longer authenticate.",
|
|
284
|
-
security: [{ bearerAuth: [] }],
|
|
285
|
-
parameters: [{ name: "userId", in: "path", required: true, schema: { type: "string" } }],
|
|
286
|
-
requestBody: {
|
|
287
|
-
required: false,
|
|
288
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/DeleteReasonRequest" } } },
|
|
289
|
-
},
|
|
290
|
-
responses: {
|
|
291
|
-
"200": { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
292
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
293
|
-
"403": missingPermission("users:manage", "cannot delete your own account"),
|
|
294
|
-
"404": errorResponse("User not found"),
|
|
295
|
-
},
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
"/auth/admin/audit-log": {
|
|
299
|
-
get: {
|
|
300
|
-
tags: ["auth"],
|
|
301
|
-
summary: "[admin] List audit log entries, newest first",
|
|
302
|
-
description: requiresPermission("audit-log:read"),
|
|
303
|
-
security: [{ bearerAuth: [] }],
|
|
304
|
-
parameters: [
|
|
305
|
-
{ name: "userId", in: "query", required: false, schema: { type: "string" } },
|
|
306
|
-
{ name: "action", in: "query", required: false, schema: { type: "string" }, description: "AuditEvent discriminant, e.g. 'role_assigned'" },
|
|
307
|
-
{ name: "since", in: "query", required: false, schema: { type: "string", format: "date-time" } },
|
|
308
|
-
{ name: "until", in: "query", required: false, schema: { type: "string", format: "date-time" } },
|
|
309
|
-
{ name: "page", in: "query", required: false, schema: { type: "integer" }, description: "1-indexed. Defaults to 1." },
|
|
310
|
-
{ name: "limit", in: "query", required: false, schema: { type: "integer" }, description: "Defaults to 25, capped at 100." },
|
|
311
|
-
],
|
|
312
|
-
responses: {
|
|
313
|
-
"200": { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/AuditLogListResponse" } } } },
|
|
314
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
315
|
-
"403": missingPermission("audit-log:read"),
|
|
316
|
-
},
|
|
317
|
-
},
|
|
318
|
-
},
|
|
319
|
-
"/auth/admin/permissions": {
|
|
320
|
-
get: {
|
|
321
|
-
tags: ["auth"],
|
|
322
|
-
summary: "[admin] List the permission catalog",
|
|
323
|
-
description:
|
|
324
|
-
requiresPermission("permissions:read") +
|
|
325
|
-
" Grouped and ordered for a permission matrix. This is the whole vocabulary of the deployment — there is nothing about authorization outside these rows.",
|
|
326
|
-
security: [{ bearerAuth: [] }],
|
|
327
|
-
responses: {
|
|
328
|
-
"200": { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/PermissionListResponse" } } } },
|
|
329
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
330
|
-
"403": missingPermission("permissions:read"),
|
|
331
|
-
},
|
|
332
|
-
},
|
|
333
|
-
post: {
|
|
334
|
-
tags: ["auth"],
|
|
335
|
-
summary: "[admin] Define or edit a permission",
|
|
336
|
-
description:
|
|
337
|
-
requiresPermission("permissions:define") +
|
|
338
|
-
" Upserted on `slug`, which is the stable identifier grants and revocations use — renaming the display name never breaks a grant." +
|
|
339
|
-
" `isActive: false` takes the permission out of every ability that carries it, in one write, effective on the next request.",
|
|
340
|
-
security: [{ bearerAuth: [] }],
|
|
341
|
-
requestBody: {
|
|
342
|
-
required: true,
|
|
343
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/DefinePermissionRequest" } } },
|
|
344
|
-
},
|
|
345
|
-
responses: {
|
|
346
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/PermissionSummary" } } } },
|
|
347
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
348
|
-
"403": missingPermission("permissions:define"),
|
|
349
|
-
},
|
|
350
|
-
},
|
|
351
|
-
},
|
|
352
|
-
"/auth/admin/roles": {
|
|
353
|
-
get: {
|
|
354
|
-
tags: ["auth"],
|
|
355
|
-
summary: "[admin] List the roles this deployment defines",
|
|
356
|
-
description: requiresPermission("roles:manage"),
|
|
357
|
-
security: [{ bearerAuth: [] }],
|
|
358
|
-
responses: {
|
|
359
|
-
"200": { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/RoleListResponse" } } } },
|
|
360
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
361
|
-
"403": missingPermission("roles:manage"),
|
|
362
|
-
},
|
|
363
|
-
},
|
|
364
|
-
post: {
|
|
365
|
-
tags: ["auth"],
|
|
366
|
-
summary: "[admin] Create a role",
|
|
367
|
-
description: requiresPermission("roles:manage"),
|
|
368
|
-
security: [{ bearerAuth: [] }],
|
|
369
|
-
requestBody: {
|
|
370
|
-
required: true,
|
|
371
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/CreateRoleRequest" } } },
|
|
372
|
-
},
|
|
373
|
-
responses: {
|
|
374
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/RoleSummary" } } } },
|
|
375
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
376
|
-
"403": missingPermission("roles:manage"),
|
|
377
|
-
},
|
|
378
|
-
},
|
|
379
|
-
},
|
|
380
|
-
"/auth/admin/roles/{roleId}": {
|
|
381
|
-
patch: {
|
|
382
|
-
tags: ["auth"],
|
|
383
|
-
summary: "[admin] Edit a role",
|
|
384
|
-
description: requiresPermission("roles:manage"),
|
|
385
|
-
security: [{ bearerAuth: [] }],
|
|
386
|
-
parameters: [{ name: "roleId", in: "path", required: true, schema: { type: "string" } }],
|
|
387
|
-
requestBody: {
|
|
388
|
-
required: true,
|
|
389
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/UpdateRoleRequest" } } },
|
|
390
|
-
},
|
|
391
|
-
responses: {
|
|
392
|
-
"200": { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/RoleSummary" } } } },
|
|
393
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
394
|
-
"403": missingPermission("roles:manage"),
|
|
395
|
-
"404": errorResponse("Role not found"),
|
|
396
|
-
},
|
|
397
|
-
},
|
|
398
|
-
delete: {
|
|
399
|
-
tags: ["auth"],
|
|
400
|
-
summary: "[admin] Delete a role",
|
|
401
|
-
description: requiresPermission("roles:manage") + " Soft-delete: existing assignments are left in place rather than cascade-deleted, and the role simply stops being resolved.",
|
|
402
|
-
security: [{ bearerAuth: [] }],
|
|
403
|
-
parameters: [{ name: "roleId", in: "path", required: true, schema: { type: "string" } }],
|
|
404
|
-
requestBody: {
|
|
405
|
-
required: false,
|
|
406
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/DeleteReasonRequest" } } },
|
|
407
|
-
},
|
|
408
|
-
responses: {
|
|
409
|
-
"200": { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
410
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
411
|
-
"403": missingPermission("roles:manage"),
|
|
412
|
-
"404": errorResponse("Role not found"),
|
|
413
|
-
},
|
|
414
|
-
},
|
|
415
|
-
},
|
|
416
|
-
"/auth/admin/roles/{roleId}/permissions": {
|
|
417
|
-
post: {
|
|
418
|
-
tags: ["auth"],
|
|
419
|
-
summary: "[admin] Attach a permission to a role",
|
|
420
|
-
description: requiresPermission("roles:manage"),
|
|
421
|
-
security: [{ bearerAuth: [] }],
|
|
422
|
-
parameters: [{ name: "roleId", in: "path", required: true, schema: { type: "string" } }],
|
|
423
|
-
requestBody: {
|
|
424
|
-
required: true,
|
|
425
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/AttachPermissionRequest" } } },
|
|
426
|
-
},
|
|
427
|
-
responses: {
|
|
428
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
429
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
430
|
-
"403": missingPermission("roles:manage"),
|
|
431
|
-
"404": errorResponse("Role not found"),
|
|
432
|
-
},
|
|
433
|
-
},
|
|
434
|
-
},
|
|
435
|
-
"/auth/admin/users/{userId}/roles": {
|
|
436
|
-
post: {
|
|
437
|
-
tags: ["auth"],
|
|
438
|
-
summary: "[admin] Assign a role to a user",
|
|
439
|
-
description: requiresPermission("roles:assign"),
|
|
440
|
-
security: [{ bearerAuth: [] }],
|
|
441
|
-
parameters: [{ name: "userId", in: "path", required: true, schema: { type: "string" } }],
|
|
442
|
-
requestBody: {
|
|
443
|
-
required: true,
|
|
444
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/AssignRoleRequest" } } },
|
|
445
|
-
},
|
|
446
|
-
responses: {
|
|
447
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
448
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
449
|
-
"403": missingPermission("roles:assign"),
|
|
450
|
-
"404": errorResponse("Role not found"),
|
|
451
|
-
},
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
|
-
"/auth/admin/users/{userId}/roles/{roleSlug}/revoke": {
|
|
455
|
-
post: {
|
|
456
|
-
tags: ["auth"],
|
|
457
|
-
summary: "[admin] Revoke a role from a user",
|
|
458
|
-
description: requiresPermission("roles:assign"),
|
|
459
|
-
security: [{ bearerAuth: [] }],
|
|
460
|
-
parameters: [
|
|
461
|
-
{ name: "userId", in: "path", required: true, schema: { type: "string" } },
|
|
462
|
-
{ name: "roleSlug", in: "path", required: true, schema: { type: "string" } },
|
|
463
|
-
],
|
|
464
|
-
responses: {
|
|
465
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
466
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
467
|
-
"403": missingPermission("roles:assign", "cannot change your own roles"),
|
|
468
|
-
},
|
|
469
|
-
},
|
|
470
|
-
},
|
|
471
|
-
"/auth/admin/users/{userId}/permissions": {
|
|
472
|
-
post: {
|
|
473
|
-
tags: ["auth"],
|
|
474
|
-
summary: "[admin] Grant a permission directly to a user, bypassing roles",
|
|
475
|
-
description: requiresPermission("permissions:grant"),
|
|
476
|
-
security: [{ bearerAuth: [] }],
|
|
477
|
-
parameters: [{ name: "userId", in: "path", required: true, schema: { type: "string" } }],
|
|
478
|
-
requestBody: {
|
|
479
|
-
required: true,
|
|
480
|
-
content: { "application/json": { schema: { $ref: "#/components/schemas/GrantPermissionRequest" } } },
|
|
481
|
-
},
|
|
482
|
-
responses: {
|
|
483
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
484
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
485
|
-
"403": missingPermission("permissions:grant"),
|
|
486
|
-
},
|
|
487
|
-
},
|
|
488
|
-
},
|
|
489
|
-
"/auth/admin/users/{userId}/permissions/{permissionSlug}/revoke": {
|
|
490
|
-
post: {
|
|
491
|
-
tags: ["auth"],
|
|
492
|
-
summary: "[admin] Revoke a direct permission grant from a user",
|
|
493
|
-
description: requiresPermission("permissions:grant"),
|
|
494
|
-
security: [{ bearerAuth: [] }],
|
|
495
|
-
parameters: [
|
|
496
|
-
{ name: "userId", in: "path", required: true, schema: { type: "string" } },
|
|
497
|
-
{ name: "permissionSlug", in: "path", required: true, schema: { type: "string" } },
|
|
498
|
-
],
|
|
499
|
-
responses: {
|
|
500
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
501
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
502
|
-
"403": missingPermission("permissions:grant"),
|
|
503
|
-
},
|
|
504
|
-
},
|
|
505
|
-
},
|
|
506
|
-
"/auth/admin/users/{userId}/block": {
|
|
507
|
-
post: {
|
|
508
|
-
tags: ["auth"],
|
|
509
|
-
summary: "[admin] Block a user, revoking all their sessions immediately",
|
|
510
|
-
description: requiresPermission("users:block"),
|
|
511
|
-
security: [{ bearerAuth: [] }],
|
|
512
|
-
parameters: [{ name: "userId", in: "path", required: true, schema: { type: "string" } }],
|
|
513
|
-
responses: {
|
|
514
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
515
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
516
|
-
"403": missingPermission("users:block", "cannot block your own account"),
|
|
517
|
-
},
|
|
518
|
-
},
|
|
519
|
-
},
|
|
520
|
-
"/auth/admin/users/{userId}/unblock": {
|
|
521
|
-
post: {
|
|
522
|
-
tags: ["auth"],
|
|
523
|
-
summary: "[admin] Unblock a user",
|
|
524
|
-
description: requiresPermission("users:block"),
|
|
525
|
-
security: [{ bearerAuth: [] }],
|
|
526
|
-
parameters: [{ name: "userId", in: "path", required: true, schema: { type: "string" } }],
|
|
527
|
-
responses: {
|
|
528
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
529
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
530
|
-
"403": missingPermission("users:block"),
|
|
531
|
-
},
|
|
532
|
-
},
|
|
533
|
-
},
|
|
534
|
-
"/auth/admin/users/{userId}/deactivate": {
|
|
535
|
-
post: {
|
|
536
|
-
tags: ["auth"],
|
|
537
|
-
summary: "[admin] Deactivate a user, revoking all their sessions immediately",
|
|
538
|
-
description:
|
|
539
|
-
requiresPermission("users:block") +
|
|
540
|
-
" Distinct from block/unblock — a routine administrative toggle, not a security action. Both independently deny login.",
|
|
541
|
-
security: [{ bearerAuth: [] }],
|
|
542
|
-
parameters: [{ name: "userId", in: "path", required: true, schema: { type: "string" } }],
|
|
543
|
-
responses: {
|
|
544
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
545
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
546
|
-
"403": missingPermission("users:block", "cannot deactivate your own account"),
|
|
547
|
-
},
|
|
548
|
-
},
|
|
549
|
-
},
|
|
550
|
-
"/auth/admin/users/{userId}/activate": {
|
|
551
|
-
post: {
|
|
552
|
-
tags: ["auth"],
|
|
553
|
-
summary: "[admin] Reactivate a user",
|
|
554
|
-
description: requiresPermission("users:block"),
|
|
555
|
-
security: [{ bearerAuth: [] }],
|
|
556
|
-
parameters: [{ name: "userId", in: "path", required: true, schema: { type: "string" } }],
|
|
557
|
-
responses: {
|
|
558
|
-
"201": { description: "Created", content: { "application/json": { schema: { $ref: "#/components/schemas/OkResponse" } } } },
|
|
559
|
-
"401": errorResponse("Missing or invalid access token"),
|
|
560
|
-
"403": missingPermission("users:block"),
|
|
561
|
-
},
|
|
562
|
-
},
|
|
563
|
-
},
|
|
564
|
-
},
|
|
565
|
-
};
|