@neohm/nestend 3.1.2 → 3.1.4
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 +82 -66
- package/dist/admin/controllers/admin.role.controller.js +2 -2
- package/dist/admin/controllers/admin.role.controller.js.map +1 -1
- package/dist/admin/controllers/admin.scheduled.task.controller.d.ts +5 -2
- package/dist/admin/controllers/admin.scheduled.task.controller.d.ts.map +1 -1
- package/dist/admin/controllers/admin.scheduled.task.controller.js +23 -3
- package/dist/admin/controllers/admin.scheduled.task.controller.js.map +1 -1
- package/dist/admin/controllers/admin.tenant.controller.d.ts +5 -2
- package/dist/admin/controllers/admin.tenant.controller.d.ts.map +1 -1
- package/dist/admin/controllers/admin.tenant.controller.js +25 -5
- package/dist/admin/controllers/admin.tenant.controller.js.map +1 -1
- package/dist/admin/controllers/admin.tenant.user.controller.d.ts +30 -0
- package/dist/admin/controllers/admin.tenant.user.controller.d.ts.map +1 -0
- package/dist/admin/controllers/admin.tenant.user.controller.js +132 -0
- package/dist/admin/controllers/admin.tenant.user.controller.js.map +1 -0
- package/dist/admin/controllers/admin.user.controller.d.ts +6 -22
- package/dist/admin/controllers/admin.user.controller.d.ts.map +1 -1
- package/dist/admin/controllers/admin.user.controller.js +22 -81
- package/dist/admin/controllers/admin.user.controller.js.map +1 -1
- package/dist/admin/dtos/add.admin.role.dto.d.ts +4 -0
- package/dist/admin/dtos/add.admin.role.dto.d.ts.map +1 -0
- package/dist/admin/dtos/add.admin.role.dto.js +22 -0
- package/dist/admin/dtos/add.admin.role.dto.js.map +1 -0
- package/dist/admin/dtos/add.admin.user.dto.d.ts +1 -2
- package/dist/admin/dtos/add.admin.user.dto.d.ts.map +1 -1
- package/dist/admin/dtos/add.admin.user.dto.js +1 -6
- package/dist/admin/dtos/add.admin.user.dto.js.map +1 -1
- package/dist/admin/dtos/add.client.user.dto.d.ts +2 -0
- package/dist/admin/dtos/add.client.user.dto.d.ts.map +1 -1
- package/dist/admin/dtos/add.client.user.dto.js +11 -0
- package/dist/admin/dtos/add.client.user.dto.js.map +1 -1
- package/dist/admin/dtos/add.user.role.dto.d.ts +4 -0
- package/dist/admin/dtos/add.user.role.dto.d.ts.map +1 -0
- package/dist/admin/dtos/add.user.role.dto.js +22 -0
- package/dist/admin/dtos/add.user.role.dto.js.map +1 -0
- package/dist/admin/dtos/base.user.dto.d.ts +0 -1
- package/dist/admin/dtos/base.user.dto.d.ts.map +1 -1
- package/dist/admin/dtos/base.user.dto.js +0 -6
- package/dist/admin/dtos/base.user.dto.js.map +1 -1
- package/dist/admin/es6.classes.d.ts +3 -2
- package/dist/admin/es6.classes.d.ts.map +1 -1
- package/dist/admin/es6.classes.js +2 -0
- package/dist/admin/es6.classes.js.map +1 -1
- package/dist/admin/libraries/admin.user.data.processor.d.ts +3 -0
- package/dist/admin/libraries/admin.user.data.processor.d.ts.map +1 -1
- package/dist/admin/libraries/admin.user.data.processor.js +38 -2
- package/dist/admin/libraries/admin.user.data.processor.js.map +1 -1
- package/dist/admin/libraries/bulk.user.data.processor.d.ts.map +1 -1
- package/dist/admin/libraries/bulk.user.data.processor.js +0 -1
- package/dist/admin/libraries/bulk.user.data.processor.js.map +1 -1
- package/dist/admin/libraries/client.user.data.processor.d.ts +6 -0
- package/dist/admin/libraries/client.user.data.processor.d.ts.map +1 -1
- package/dist/admin/libraries/client.user.data.processor.js +74 -4
- package/dist/admin/libraries/client.user.data.processor.js.map +1 -1
- package/dist/admin/libraries/scheduled.task.list.processor.d.ts.map +1 -1
- package/dist/admin/libraries/scheduled.task.list.processor.js +4 -0
- package/dist/admin/libraries/scheduled.task.list.processor.js.map +1 -1
- package/dist/auth/controllers/auth.controller.js +1 -1
- package/dist/index.d.ts +82 -179
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +141 -345
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @neohm/
|
|
1
|
+
# @neohm/nestend
|
|
2
2
|
|
|
3
3
|
Reusable NestJS building blocks for SaaS backends: entities, migrations, JWT auth
|
|
4
4
|
(+ Google SSO), BullMQ queueing, Redis caching, encryption, system properties,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
QueueService,
|
|
12
12
|
AuthService,
|
|
13
13
|
DocumentService,
|
|
14
|
-
} from '@neohm/
|
|
14
|
+
} from '@neohm/nestend';
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
> Full, verbose reference (every service, method, env variable, and an end-to-end
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
## Installation
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
yarn add @neohm/
|
|
23
|
+
yarn add @neohm/nestend
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
Copy [`.env.example`](./.env.example) into your project and fill in real values —
|
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
DocumentModule,
|
|
44
44
|
TenantModule,
|
|
45
45
|
NotificationModule,
|
|
46
|
-
} from '@neohm/
|
|
46
|
+
} from '@neohm/nestend';
|
|
47
47
|
|
|
48
48
|
@Module({
|
|
49
49
|
imports: [
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
LoggingInterceptor,
|
|
71
71
|
MonitoringInterceptor,
|
|
72
72
|
MonitoringService,
|
|
73
|
-
} from '@neohm/
|
|
73
|
+
} from '@neohm/nestend';
|
|
74
74
|
|
|
75
75
|
const app = await NestFactory.create(AppModule);
|
|
76
76
|
app.useGlobalFilters(new GlobalExceptionFilter());
|
|
@@ -80,34 +80,50 @@ app.useGlobalInterceptors(
|
|
|
80
80
|
);
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
+
## Public API Surface
|
|
84
|
+
|
|
85
|
+
The barrel (`src/index.ts`) exports only what a consuming app builds against: every
|
|
86
|
+
module (plus its `*ModuleOptions`), every entity including the abstract bases, the
|
|
87
|
+
middlewares and request-context helpers (`Auth`, `AdminAuth`, `ApiKeyContext`), the
|
|
88
|
+
injectable services, guards, decorators, base classes, common DTOs, utilities,
|
|
89
|
+
identifier constants/maps, and the types those signatures name — plus everything in
|
|
90
|
+
the notification and document modules.
|
|
91
|
+
|
|
92
|
+
Internal by design: the controllers, DTOs and processors behind the built-in endpoints
|
|
93
|
+
(the whole `admin` module beyond `AdminModule` itself, `AuthController`,
|
|
94
|
+
`AdminAuthController`), the passport strategies, `JobConsumer` and the framework
|
|
95
|
+
jobs/subscribers/schedule resolvers, the `FILTER_OPERATORS` registry, the internal
|
|
96
|
+
`*Default` enums, and the migration classes. Import the module and call the endpoints —
|
|
97
|
+
these are free to change without a breaking release.
|
|
98
|
+
|
|
83
99
|
## Feature Map
|
|
84
100
|
|
|
85
|
-
| Area | Key exports
|
|
86
|
-
| ----------------- |
|
|
87
|
-
| Entities | `RootEntity`, `CommonEntity`, `CommonAdminEntity`, `UserEntity`, `AdminUserEntity`, `SystemRoleEntity`, `SystemAdminRoleEntity`, ...
|
|
88
|
-
| Migrations | `
|
|
89
|
-
| Queue | `QueueModule`, `QueueService`, `CommonJob
|
|
90
|
-
| Scheduled events | `SystemScheduledTaskEntity`, `ScheduledEventEntity`, `
|
|
91
|
-
| Auth | `AuthModule`, `AuthService.validateRole()`, `Auth`, `JwtMiddleware
|
|
92
|
-
| Admin auth | `AdminAuthService.validateRole()`, `AdminAuth`, `AdminJwtMiddleware
|
|
93
|
-
| API keys | `ApiKeyService`, `ApiKeyGuard` / `ApiKeyMiddleware`, `@ApiKeyScopes()`, `ScopeEntity`, `ApiScopeEntity`
|
|
94
|
-
| Multi-tenancy | `TenantModule`, `TenantEntity`, `
|
|
95
|
-
| Admin | `AdminModule
|
|
96
|
-
| Notifications | `NotificationModule`, `NotificationService`, `FcmPushNotificationService`
|
|
97
|
-
| Email (SES) | `EmailNotificationService`, `ProcessEmailNotification`, `EmailTemplateEntity`, `EmailNotificationLogEntity`
|
|
98
|
-
| Audit | `AuditService`
|
|
99
|
-
| Feature flags | `FeatureFlagService`
|
|
100
|
-
| Cache | `CacheService`
|
|
101
|
-
| Encryption | `EncryptionService`
|
|
102
|
-
| System properties | `SystemPropertyModule`, `SystemPropertyService`
|
|
103
|
-
| Documents | `DocumentModule`, `DocumentService`, `S3BucketDocumentService`, `MinioBucketDocumentService`
|
|
104
|
-
| HTTP | `CommonController`, `GlobalExceptionFilter`, common DTOs
|
|
105
|
-
| Raw SQL | `SqlService`, `SqlTarget`
|
|
106
|
-
| List endpoints | `CommonListProcessor`, `CommonListFilterDto`, `FilterDto`, `
|
|
107
|
-
| Outbound HTTP | `RemoteRequestService`, `ApiRequestTypeEnum`, `ApiContentTypeEnum`
|
|
108
|
-
| Observability | `LoggingInterceptor`, `MonitoringInterceptor`, `MonitoringService`
|
|
109
|
-
| Jobs/Events | `CommonJob`, `
|
|
110
|
-
| Constants & maps | `baseEntityConstants`, `baseJobConstants`, `baseEntityMaps`, `baseJobMaps`
|
|
101
|
+
| Area | Key exports | Notes |
|
|
102
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
103
|
+
| Entities | `RootEntity`, `CommonEntity`, `CommonAdminEntity`, `UserEntity`, `AdminUserEntity`, `SystemRoleEntity`, `SystemAdminRoleEntity`, ... | uuid PK, soft deletes, `created_by`, jsonb `attributes`; entity-level `findOneOrNew`, `softDelete`, `hardDelete`, `restore`, `paginate` statics |
|
|
104
|
+
| Migrations | `MigrationUtility`, `SeederUtility` (the 26 table migrations ship in `dist/migrations` — glob them, they are not barrel exports) | fluent `this.string()`, `this.numeric()`, `addRecord()` seeding |
|
|
105
|
+
| Queue | `QueueModule`, `QueueService`, `CommonJob` | BullMQ `@Processor`/`WorkerHost` consumer; auto-discovered jobs, duplicate prevention, recurring schedulers, 1-day TTL, retries, failures persisted to `sys_failed_jobs` |
|
|
106
|
+
| Scheduled events | `SystemScheduledTaskEntity`, `ScheduledEventEntity`, `ScheduleKind`, `ScheduleSpec`, `IsCronExpression` | schedule definitions in `sys_scheduled_tasks` → events in `sys_scheduled_events`; interval / cron / once specs with timezones, drift-free slots, horizon materialisation, catch-up + overlap policies, fire-once dispatch with backoff, cadence via `SCHEDULED_EVENT_MIN` |
|
|
107
|
+
| Auth | `AuthModule`, `AuthService.validateRole()`, `Auth`, `JwtMiddleware` | imperative auth (open by default); JwtMiddleware resolves the user into `Auth`'s AsyncLocalStorage context per request; access + rotating refresh tokens; session-based logout invalidation (`sys_auth_sessions`); Google SSO via ID token at `POST /auth/google` |
|
|
108
|
+
| Admin auth | `AdminAuthService.validateRole()`, `AdminAuth`, `AdminJwtMiddleware` (endpoints at `/admin/auth`) | fully separate stack for back-office admins — own users table (`sys_admin_users`), own roles (`sys_admin_roles`/`sys_auser_roles`), own sessions/refresh tokens (shared tables, `is_admin` flag) |
|
|
109
|
+
| API keys | `ApiKeyService`, `ApiKeyGuard` / `ApiKeyMiddleware`, `@ApiKeyScopes()`, `ScopeEntity`, `ApiScopeEntity` | hashed keys in `sys_api_keys` (admin-owned), scopes, expiry/revocation, `x-api-key` header; normalized scopes catalogue in `sys_scopes`/`sys_api_scopes` |
|
|
110
|
+
| Multi-tenancy | `TenantModule`, `TenantEntity`, `CommonTenantEntity`, `TenantContextService`, `TenantContextMiddleware` | AsyncLocalStorage tenant context; resolve by header, slug, or domain; tenants are onboarded by admins (`TenantEntity.creator` → `AdminUserEntity`) |
|
|
111
|
+
| Admin | `AdminModule` (its controllers, DTOs and processors are internal — import the module and hit the endpoints), `GlobalAdminRoles` | back-office APIs: tenant onboarding, client/admin user registration (single + bulk, no role granting), tenant + scheduled-task listing; 4-tier `GlobalAdminRoles` gate over `sys_admin_roles`; Swagger at `/docs` (hidden in production) |
|
|
112
|
+
| Notifications | `NotificationModule`, `NotificationService`, `FcmPushNotificationService` | in-app rows + FCM push (optional `firebase-admin`); device token registry |
|
|
113
|
+
| Email (SES) | `EmailNotificationService`, `ProcessEmailNotification`, `EmailTemplateEntity`, `EmailNotificationLogEntity` | templates in `sys_email_templates` rendered by a remote service, dispatched via SES per recipient (to/cc/bcc); logged to `sys_email_notification_logs` outside production; dispatch skipped when `AWS_SES_FROM_ADDRESS` unset |
|
|
114
|
+
| Audit | `AuditService` | `saveAuditLog(old, new)` with changed-value diffing into `sys_audit_logs` |
|
|
115
|
+
| Feature flags | `FeatureFlagService` | on/off, percentage rollouts, allow lists — stored as `feature.*` system properties |
|
|
116
|
+
| Cache | `CacheService` | Redis, TTL objects (`{days, hours, min}`), transparent encryption |
|
|
117
|
+
| Encryption | `EncryptionService` | AES-256-GCM, scrypt-derived keys |
|
|
118
|
+
| System properties | `SystemPropertyModule`, `SystemPropertyService` | cached + optionally encrypted key/value settings in `sys_properties` |
|
|
119
|
+
| Documents | `DocumentModule`, `DocumentService`, `S3BucketDocumentService`, `MinioBucketDocumentService` | `uploadDocument(multerFiles) → links[]`; driver chosen via `DOCUMENT_STORAGE_DRIVER` |
|
|
120
|
+
| HTTP | `CommonController`, `GlobalExceptionFilter`, common DTOs | health endpoint base controller, uniform error envelope |
|
|
121
|
+
| Raw SQL | `SqlService`, `SqlTarget` | named `:key` placeholders always bound as driver params, `:...key` array expansion; runs on the read replica (`DB_READ_*`) with transparent primary fallback; `fetchOne`/`fetchScalar`/`exists`/`count`/`paginate` helpers |
|
|
122
|
+
| List endpoints | `CommonListProcessor`, `CommonListFilterDto`, `FilterDto`, `CommonListFilterConfig` | allowlisted columns, parameterised operators (`eq`…`isNull`), typed value casting (`str`/`num`/`date`/`bool`/`null`), multi-sort + paginated on the read replica |
|
|
123
|
+
| Outbound HTTP | `RemoteRequestService`, `ApiRequestTypeEnum`, `ApiContentTypeEnum` | injectable `fetch` wrapper (global via `CommonModule`); `getApiResponse<T>()` parses JSON/text and throws `OperationException` on non-2xx, `getApiRawResponse()` returns the raw `Response`; JSON + form-urlencoded body serialisation |
|
|
124
|
+
| Observability | `LoggingInterceptor`, `MonitoringInterceptor`, `MonitoringService` | Sentry auto-registers when `@sentry/node` + `SENTRY_DSN` present; pluggable `MonitoringAdapter` |
|
|
125
|
+
| Jobs/Events | `CommonJob`, `CommonSubscriber`, `CommonDataProcessor` | dispatch/handle separation, discovery-based registration, worker-event lifecycle, column-change detection, field error collection |
|
|
126
|
+
| Constants & maps | `baseEntityConstants`, `baseJobConstants`, `baseEntityMaps`, `baseJobMaps` | centralised dotted identifiers (`as const`) plus identifier → class maps of every concrete entity and job (abstract bases excluded); map keys are computed from the constants, so renames propagate at compile time |
|
|
111
127
|
|
|
112
128
|
## Environment Variables
|
|
113
129
|
|
|
@@ -233,7 +249,7 @@ export class AppModule implements NestModule {
|
|
|
233
249
|
|
|
234
250
|
`AdminAuthController` (mounted at `/admin/auth`) exposes `POST login` (body:
|
|
235
251
|
`email_or_username`, `password`), `POST refresh`, `POST logout`, `GET me`.
|
|
236
|
-
`AdminAccessService` (
|
|
252
|
+
`AdminAccessService` (internal to the back-office admin APIs, see
|
|
237
253
|
[Admin Module](#admin-module)) is built on `AdminAuthService.validateRole()` and gates
|
|
238
254
|
against the `GlobalAdminRoles` hierarchy stored in
|
|
239
255
|
`sys_admin_roles.identifier`. Admins **cannot** grant `sys_roles` to tenant
|
|
@@ -329,10 +345,10 @@ therefore invisible to `retryJob(jobId)`. API instances leave
|
|
|
329
345
|
Recurring work is event-driven (off the BullMQ worker), not a reconciliation
|
|
330
346
|
loop. Two tables back it:
|
|
331
347
|
|
|
332
|
-
| Table | Entity | Role
|
|
333
|
-
| ---------------------- | --------------------------- |
|
|
348
|
+
| Table | Entity | Role |
|
|
349
|
+
| ---------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
334
350
|
| `sys_scheduled_tasks` | `SystemScheduledTaskEntity` | a schedule definition (`identifier`, `name`, `start_from`, `schedule`, `timezone`, `payload`, `catch_up_policy`, `max_catchup`, `overlap_policy`, `jitter_sec`, `enabled`, `next_upsert_at`) |
|
|
335
|
-
| `sys_scheduled_events` | `ScheduledEventEntity` | one row per fire time (`job_id` → task, `scheduled_at`, `status`, `next_attempt_at`, `started_at`, `failed_at`, `total_attempts`, `active`); one task → many events
|
|
351
|
+
| `sys_scheduled_events` | `ScheduledEventEntity` | one row per fire time (`job_id` → task, `scheduled_at`, `status`, `next_attempt_at`, `started_at`, `failed_at`, `total_attempts`, `active`); one task → many events |
|
|
336
352
|
|
|
337
353
|
`JobConsumer` enrols `SetScheduledEventJob` as a recurring scheduler once **both**
|
|
338
354
|
the worker's Redis connection is ready and the application has bootstrapped —
|
|
@@ -353,11 +369,11 @@ arm materialisation and dispatch — the value must be exactly `true`.
|
|
|
353
369
|
Each task's `schedule` column is a discriminated JSONB spec, so expressing a new
|
|
354
370
|
kind of "when" never changes the schema:
|
|
355
371
|
|
|
356
|
-
| `kind` | Shape
|
|
357
|
-
| ---------- |
|
|
358
|
-
| `interval` | `{ kind, day?, hour?, min?, sec? }`
|
|
359
|
-
| `cron` | `{ kind, expression }` (5- or 6-field)
|
|
360
|
-
| `once` | `{ kind }` — fires at `start_from`, then retires | `{ kind: 'once' }`
|
|
372
|
+
| `kind` | Shape | Example |
|
|
373
|
+
| ---------- | ------------------------------------------------ | --------------------------------------------- |
|
|
374
|
+
| `interval` | `{ kind, day?, hour?, min?, sec? }` | `{ kind: 'interval', hour: 6 }` |
|
|
375
|
+
| `cron` | `{ kind, expression }` (5- or 6-field) | `{ kind: 'cron', expression: '0 2 * * MON' }` |
|
|
376
|
+
| `once` | `{ kind }` — fires at `start_from`, then retires | `{ kind: 'once' }` |
|
|
361
377
|
|
|
362
378
|
`cron` is what expresses day-, weekday- and month-based schedules, evaluated in the
|
|
363
379
|
task's `timezone` (IANA name, default `UTC`) so a local wall time stays put across
|
|
@@ -389,11 +405,11 @@ a floor on schedule granularity**. A `{ sec: 30 }` task materialises every
|
|
|
389
405
|
What happens to fire times missed while the scheduler was down is a per-task
|
|
390
406
|
decision (`catch_up_policy`), not an accident:
|
|
391
407
|
|
|
392
|
-
| Policy
|
|
393
|
-
|
|
|
394
|
-
| `skip_missed`
|
|
395
|
-
| `fire_once`
|
|
396
|
-
| `fire_all`
|
|
408
|
+
| Policy | Behaviour |
|
|
409
|
+
| ------------- | ----------------------------------------------------------------------- |
|
|
410
|
+
| `skip_missed` | advance past them, materialise nothing |
|
|
411
|
+
| `fire_once` | **default** — materialise only the most recent elapsed slot |
|
|
412
|
+
| `fire_all` | materialise every elapsed slot, retaining the most recent `max_catchup` |
|
|
397
413
|
|
|
398
414
|
Discarded slots are counted and logged; a silent gap would read as "nothing was
|
|
399
415
|
scheduled". The elapsed-slot walk is bounded by `ScheduleDefault.MAX_SCAN`, and a
|
|
@@ -436,13 +452,13 @@ hand the catch-up policy a backlog it never asked for.
|
|
|
436
452
|
`status` carries where an occurrence is; `active` is orthogonal and carries
|
|
437
453
|
suppression by the parent task.
|
|
438
454
|
|
|
439
|
-
| Status | Meaning
|
|
440
|
-
| ----------- |
|
|
441
|
-
| `pending` | awaiting dispatch; `next_attempt_at` gates eligibility
|
|
442
|
-
| `claimed` | a pass owns it — a row stuck here means the process died between claim and enqueue
|
|
443
|
-
| `enqueued` | handed to the queue (terminal); BullMQ's own `attempts` governs it from there
|
|
444
|
-
| `failed` | last enqueue failed; retried once `next_attempt_at` passes
|
|
445
|
-
| `abandoned` | attempts exhausted — terminal and queryable, not merely absent from the due set
|
|
455
|
+
| Status | Meaning |
|
|
456
|
+
| ----------- | ---------------------------------------------------------------------------------- |
|
|
457
|
+
| `pending` | awaiting dispatch; `next_attempt_at` gates eligibility |
|
|
458
|
+
| `claimed` | a pass owns it — a row stuck here means the process died between claim and enqueue |
|
|
459
|
+
| `enqueued` | handed to the queue (terminal); BullMQ's own `attempts` governs it from there |
|
|
460
|
+
| `failed` | last enqueue failed; retried once `next_attempt_at` passes |
|
|
461
|
+
| `abandoned` | attempts exhausted — terminal and queryable, not merely absent from the due set |
|
|
446
462
|
|
|
447
463
|
Each occurrence fires **once**. A pass claims an event by moving it to `claimed`
|
|
448
464
|
under a still-dispatchable condition, incrementing `total_attempts` in the same
|
|
@@ -741,15 +757,15 @@ pass the actor to a processor.
|
|
|
741
757
|
|
|
742
758
|
### Endpoints
|
|
743
759
|
|
|
744
|
-
| Route | Min. role | Processor
|
|
745
|
-
| ---------------------------------- | --------------- |
|
|
746
|
-
| `POST /admin/tenants` | super admin | `TenantDataProcessor` (upsert — send `id` to update)
|
|
747
|
-
| `POST /admin/tenants/list` | admin | `TenantListProcessor`
|
|
748
|
-
| `POST /admin/users/clients` | super admin | `ClientUserDataProcessor`
|
|
749
|
-
| `POST /admin/users/clients/bulk` | super admin | `BulkUserDataProcessor`
|
|
750
|
-
| `POST /admin/users/admins` | admin | `AdminUserDataProcessor`
|
|
760
|
+
| Route | Min. role | Processor |
|
|
761
|
+
| ---------------------------------- | --------------- | ----------------------------------------------------------- |
|
|
762
|
+
| `POST /admin/tenants` | super admin | `TenantDataProcessor` (upsert — send `id` to update) |
|
|
763
|
+
| `POST /admin/tenants/list` | admin | `TenantListProcessor` |
|
|
764
|
+
| `POST /admin/users/clients` | super admin | `ClientUserDataProcessor` |
|
|
765
|
+
| `POST /admin/users/clients/bulk` | super admin | `BulkUserDataProcessor` |
|
|
766
|
+
| `POST /admin/users/admins` | admin | `AdminUserDataProcessor` |
|
|
751
767
|
| `POST /admin/scheduled-tasks` | content manager | `ScheduledTaskDataProcessor` (upsert — send `id` to update) |
|
|
752
|
-
| `POST /admin/scheduled-tasks/list` | content reader | `ScheduledTaskListProcessor`
|
|
768
|
+
| `POST /admin/scheduled-tasks/list` | content reader | `ScheduledTaskListProcessor` |
|
|
753
769
|
|
|
754
770
|
List endpoints are `POST .../list` with the filter payload in the body (a
|
|
755
771
|
`CommonListFilterDto`) — see [List Endpoints & Filtering](#list-endpoints--filtering).
|
|
@@ -787,7 +803,7 @@ The processor loads the row when an `id` is present, falls back to `Entity.creat
|
|
|
787
803
|
when it isn't, then assigns every field and saves — one path, no create/update
|
|
788
804
|
branching. Required fields stay **required in the DTO** (`@IsNotEmpty()`, `@IsString()`,
|
|
789
805
|
…), so the payload always describes the whole record and validation stays where the
|
|
790
|
-
decorators are. Omitting an
|
|
806
|
+
decorators are. Omitting an _optional_ field leaves it unchanged on an edit, since
|
|
791
807
|
TypeORM skips `undefined` properties on update.
|
|
792
808
|
|
|
793
809
|
Processors only validate what decorators cannot see: whether the `id` exists, and
|
|
@@ -795,12 +811,12 @@ uniqueness against other rows. Uniqueness checks (tenant `slug`, scheduled-task
|
|
|
795
811
|
`identifier`) exclude the row being edited — they run in code rather than as DB
|
|
796
812
|
constraints, so resaving a record must not collide with itself.
|
|
797
813
|
|
|
798
|
-
| Processor
|
|
799
|
-
|
|
|
800
|
-
| `TenantDataProcessor`
|
|
801
|
-
| `ScheduledTaskDataProcessor`
|
|
814
|
+
| Processor | Update | Notes |
|
|
815
|
+
| --------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
816
|
+
| `TenantDataProcessor` | yes | Never re-runs onboarding: `onboarded_at`, `created_by` and the welcome email belong to first registration |
|
|
817
|
+
| `ScheduledTaskDataProcessor` | yes | Changing `schedule`/`timezone`/`start_from` also re-seats the cursor and drops not-yet-due occurrences |
|
|
802
818
|
| `ClientUserDataProcessor`, `AdminUserDataProcessor` | not yet | Their DTOs carry `id`, but the processors are still create-only. Password and role changes are intended to get their own endpoints rather than riding on an upsert |
|
|
803
|
-
| `BulkUserDataProcessor`
|
|
819
|
+
| `BulkUserDataProcessor` | n/a | `AddBulkUsersDto` is a batch wrapper, not a record; each `BulkUserItemDto` carries an `id` |
|
|
804
820
|
|
|
805
821
|
Data processors extend `CommonDataProcessor` and are created per request
|
|
806
822
|
(`new XxxDataProcessor(...deps).process(dto)`); list processors return a
|
|
@@ -35,7 +35,7 @@ let AdminRoleController = class AdminRoleController {
|
|
|
35
35
|
};
|
|
36
36
|
exports.AdminRoleController = AdminRoleController;
|
|
37
37
|
__decorate([
|
|
38
|
-
(0, common_1.Post)('list'),
|
|
38
|
+
(0, common_1.Post)('tenant/list'),
|
|
39
39
|
(0, swagger_1.ApiOperation)({
|
|
40
40
|
summary: 'List the roles a tenant user can hold (sys_roles).',
|
|
41
41
|
description: 'Requires at least the global admin role.',
|
|
@@ -46,7 +46,7 @@ __decorate([
|
|
|
46
46
|
__metadata("design:returntype", Promise)
|
|
47
47
|
], AdminRoleController.prototype, "list", null);
|
|
48
48
|
__decorate([
|
|
49
|
-
(0, common_1.Post)('
|
|
49
|
+
(0, common_1.Post)('list'),
|
|
50
50
|
(0, swagger_1.ApiOperation)({
|
|
51
51
|
summary: 'List the roles an admin user can hold (sys_admin_roles).',
|
|
52
52
|
description: 'Feeds the role picker on admin-user creation, which requires at least one of these. Requires at least the global admin role.',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.role.controller.js","sourceRoot":"","sources":["../../../src/admin/controllers/admin.role.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAwD;AACxD,6CAAuE;AACvE,mEAA+D;AAC/D,2EAAsE;AACtE,0EAG0C;AAC1C,yDAAoD;AAU7C,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YACmB,kBAAsC,EACtC,UAAsB;QADtB,uBAAkB,GAAlB,kBAAkB,CAAoB;QACtC,eAAU,GAAV,UAAU,CAAY;IACtC,CAAC;IAOE,AAAN,KAAK,CAAC,IAAI,CAAS,GAAgB;QACjC,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,CAAC;QAC9C,OAAO,IAAI,uCAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7D,CAAC;IAQK,AAAN,KAAK,CAAC,cAAc,CAAS,GAAgB;QAC3C,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,CAAC;QAC9C,OAAO,IAAI,4CAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClE,CAAC;CACF,CAAA;AA1BY,kDAAmB;AAWxB;IALL,IAAA,aAAI,EAAC,
|
|
1
|
+
{"version":3,"file":"admin.role.controller.js","sourceRoot":"","sources":["../../../src/admin/controllers/admin.role.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAwD;AACxD,6CAAuE;AACvE,mEAA+D;AAC/D,2EAAsE;AACtE,0EAG0C;AAC1C,yDAAoD;AAU7C,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YACmB,kBAAsC,EACtC,UAAsB;QADtB,uBAAkB,GAAlB,kBAAkB,CAAoB;QACtC,eAAU,GAAV,UAAU,CAAY;IACtC,CAAC;IAOE,AAAN,KAAK,CAAC,IAAI,CAAS,GAAgB;QACjC,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,CAAC;QAC9C,OAAO,IAAI,uCAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7D,CAAC;IAQK,AAAN,KAAK,CAAC,cAAc,CAAS,GAAgB;QAC3C,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,CAAC;QAC9C,OAAO,IAAI,4CAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClE,CAAC;CACF,CAAA;AA1BY,kDAAmB;AAWxB;IALL,IAAA,aAAI,EAAC,aAAa,CAAC;IACnB,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,oDAAoD;QAC7D,WAAW,EAAE,0CAA0C;KACxD,CAAC;IACU,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,2BAAW;;+CAGlC;AAQK;IANL,IAAA,aAAI,EAAC,MAAM,CAAC;IACZ,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,0DAA0D;QACnE,WAAW,EACT,8HAA8H;KACjI,CAAC;IACoB,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,2BAAW;;yDAG5C;8BAzBU,mBAAmB;IAH/B,IAAA,iBAAO,EAAC,eAAe,CAAC;IACxB,IAAA,uBAAa,GAAE;IACf,IAAA,mBAAU,EAAC,iBAAiB,CAAC;qCAGW,yCAAkB;QAC1B,wBAAU;GAH9B,mBAAmB,CA0B/B"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { SqlService } from '../../common/services/sql.service';
|
|
2
2
|
import { AdminAccessService } from '../services/admin.access.service';
|
|
3
|
+
import { CommonParamsDto } from '../../common/dtos/common.params.dto';
|
|
3
4
|
import { AddScheduledTaskDto } from '../dtos/add.scheduled.task.dto';
|
|
4
5
|
import { ScheduledTaskListDto } from '../dtos/scheduled.task.list.dto';
|
|
6
|
+
import { SystemScheduledTaskEntity } from '../../common/entities/system.scheduled.task.entity';
|
|
5
7
|
export declare class AdminScheduledTaskController {
|
|
6
8
|
private readonly adminAccessService;
|
|
7
9
|
private readonly sqlService;
|
|
8
10
|
constructor(adminAccessService: AdminAccessService, sqlService: SqlService);
|
|
9
|
-
save(dto: AddScheduledTaskDto): Promise<
|
|
11
|
+
save(dto: AddScheduledTaskDto): Promise<SystemScheduledTaskEntity>;
|
|
10
12
|
list(dto: ScheduledTaskListDto): Promise<{
|
|
11
13
|
records: import("../..").SqlRow[];
|
|
12
14
|
total: number;
|
|
@@ -14,6 +16,7 @@ export declare class AdminScheduledTaskController {
|
|
|
14
16
|
limit: number;
|
|
15
17
|
total_pages: number;
|
|
16
18
|
}>;
|
|
17
|
-
|
|
19
|
+
detail({ id }: CommonParamsDto): Promise<SystemScheduledTaskEntity>;
|
|
20
|
+
remove({ id }: CommonParamsDto): Promise<import("../types/admin.types").DeleteResult>;
|
|
18
21
|
}
|
|
19
22
|
//# sourceMappingURL=admin.scheduled.task.controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.scheduled.task.controller.d.ts","sourceRoot":"","sources":["../../../src/admin/controllers/admin.scheduled.task.controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"admin.scheduled.task.controller.d.ts","sourceRoot":"","sources":["../../../src/admin/controllers/admin.scheduled.task.controller.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAItE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oDAAoD,CAAC;AAE/F,qBAGa,4BAA4B;IAErC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU;gBADV,kBAAkB,EAAE,kBAAkB,EACtC,UAAU,EAAE,UAAU;IASnC,IAAI,CAAS,GAAG,EAAE,mBAAmB;IAUrC,IAAI,CAAS,GAAG,EAAE,oBAAoB;;;;;;;IAWtC,MAAM,CAAU,EAAE,EAAE,EAAE,EAAE,eAAe;IAevC,MAAM,CAAU,EAAE,EAAE,EAAE,EAAE,eAAe;CAI9C"}
|
|
@@ -17,11 +17,13 @@ const common_1 = require("@nestjs/common");
|
|
|
17
17
|
const swagger_1 = require("@nestjs/swagger");
|
|
18
18
|
const sql_service_1 = require("../../common/services/sql.service");
|
|
19
19
|
const admin_access_service_1 = require("../services/admin.access.service");
|
|
20
|
+
const common_params_dto_1 = require("../../common/dtos/common.params.dto");
|
|
20
21
|
const scheduled_task_data_processor_1 = require("../libraries/scheduled.task.data.processor");
|
|
21
22
|
const scheduled_task_delete_processor_1 = require("../libraries/scheduled.task.delete.processor");
|
|
22
23
|
const scheduled_task_list_processor_1 = require("../libraries/scheduled.task.list.processor");
|
|
23
24
|
const add_scheduled_task_dto_1 = require("../dtos/add.scheduled.task.dto");
|
|
24
25
|
const scheduled_task_list_dto_1 = require("../dtos/scheduled.task.list.dto");
|
|
26
|
+
const system_scheduled_task_entity_1 = require("../../common/entities/system.scheduled.task.entity");
|
|
25
27
|
let AdminScheduledTaskController = class AdminScheduledTaskController {
|
|
26
28
|
constructor(adminAccessService, sqlService) {
|
|
27
29
|
this.adminAccessService = adminAccessService;
|
|
@@ -35,7 +37,14 @@ let AdminScheduledTaskController = class AdminScheduledTaskController {
|
|
|
35
37
|
await this.adminAccessService.validateContentReader();
|
|
36
38
|
return new scheduled_task_list_processor_1.ScheduledTaskListProcessor(this.sqlService).process(dto);
|
|
37
39
|
}
|
|
38
|
-
async
|
|
40
|
+
async detail({ id }) {
|
|
41
|
+
await this.adminAccessService.validateContentReader();
|
|
42
|
+
const task = await system_scheduled_task_entity_1.SystemScheduledTaskEntity.findOne({ where: { id } });
|
|
43
|
+
if (!task)
|
|
44
|
+
throw new common_1.NotFoundException('No scheduled task exists for this id');
|
|
45
|
+
return task;
|
|
46
|
+
}
|
|
47
|
+
async remove({ id }) {
|
|
39
48
|
const { user } = await this.adminAccessService.validateContentManager();
|
|
40
49
|
return new scheduled_task_delete_processor_1.ScheduledTaskDeleteProcessor(user).process(id);
|
|
41
50
|
}
|
|
@@ -63,15 +72,26 @@ __decorate([
|
|
|
63
72
|
__metadata("design:paramtypes", [scheduled_task_list_dto_1.ScheduledTaskListDto]),
|
|
64
73
|
__metadata("design:returntype", Promise)
|
|
65
74
|
], AdminScheduledTaskController.prototype, "list", null);
|
|
75
|
+
__decorate([
|
|
76
|
+
(0, common_1.Get)(':id'),
|
|
77
|
+
(0, swagger_1.ApiOperation)({
|
|
78
|
+
summary: 'One scheduled task, in full.',
|
|
79
|
+
description: 'Carries the schedule spec, payload and catch-up settings. Requires at least the global content reader role.',
|
|
80
|
+
}),
|
|
81
|
+
__param(0, (0, common_1.Param)()),
|
|
82
|
+
__metadata("design:type", Function),
|
|
83
|
+
__metadata("design:paramtypes", [common_params_dto_1.CommonParamsDto]),
|
|
84
|
+
__metadata("design:returntype", Promise)
|
|
85
|
+
], AdminScheduledTaskController.prototype, "detail", null);
|
|
66
86
|
__decorate([
|
|
67
87
|
(0, common_1.Post)(':id/delete'),
|
|
68
88
|
(0, swagger_1.ApiOperation)({
|
|
69
89
|
summary: 'Delete a scheduled task.',
|
|
70
90
|
description: 'Soft delete: the row keeps its data with `deleted_at` set and drops out of every listing. Occurrences that were materialised but have not been dispatched are dropped with it, so a deleted task stops firing immediately; ones already claimed, enqueued or terminal are left as history. Requires at least the global content manager role.',
|
|
71
91
|
}),
|
|
72
|
-
__param(0, (0, common_1.Param)(
|
|
92
|
+
__param(0, (0, common_1.Param)()),
|
|
73
93
|
__metadata("design:type", Function),
|
|
74
|
-
__metadata("design:paramtypes", [
|
|
94
|
+
__metadata("design:paramtypes", [common_params_dto_1.CommonParamsDto]),
|
|
75
95
|
__metadata("design:returntype", Promise)
|
|
76
96
|
], AdminScheduledTaskController.prototype, "remove", null);
|
|
77
97
|
exports.AdminScheduledTaskController = AdminScheduledTaskController = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.scheduled.task.controller.js","sourceRoot":"","sources":["../../../src/admin/controllers/admin.scheduled.task.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"admin.scheduled.task.controller.js","sourceRoot":"","sources":["../../../src/admin/controllers/admin.scheduled.task.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAOwB;AACxB,6CAAuE;AACvE,mEAA+D;AAC/D,2EAAsE;AACtE,2EAAsE;AACtE,8FAAwF;AACxF,kGAA4F;AAC5F,8FAAwF;AACxF,2EAAqE;AACrE,6EAAuE;AACvE,qGAA+F;AAKxF,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IACvC,YACmB,kBAAsC,EACtC,UAAsB;QADtB,uBAAkB,GAAlB,kBAAkB,CAAoB;QACtC,eAAU,GAAV,UAAU,CAAY;IACtC,CAAC;IAQE,AAAN,KAAK,CAAC,IAAI,CAAS,GAAwB;QACzC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,sBAAsB,EAAE,CAAC;QACxE,OAAO,IAAI,0DAA0B,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;IAOK,AAAN,KAAK,CAAC,IAAI,CAAS,GAAyB;QAC1C,MAAM,IAAI,CAAC,kBAAkB,CAAC,qBAAqB,EAAE,CAAC;QACtD,OAAO,IAAI,0DAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtE,CAAC;IAQK,AAAN,KAAK,CAAC,MAAM,CAAU,EAAE,EAAE,EAAmB;QAC3C,MAAM,IAAI,CAAC,kBAAkB,CAAC,qBAAqB,EAAE,CAAC;QAEtD,MAAM,IAAI,GAAG,MAAM,wDAAyB,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI;YACP,MAAM,IAAI,0BAAiB,CAAC,sCAAsC,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IAQK,AAAN,KAAK,CAAC,MAAM,CAAU,EAAE,EAAE,EAAmB;QAC3C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,sBAAsB,EAAE,CAAC;QACxE,OAAO,IAAI,8DAA4B,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC;CACF,CAAA;AApDY,oEAA4B;AAYjC;IANL,IAAA,aAAI,GAAE;IACN,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,iCAAiC;QAC1C,WAAW,EACT,+TAA+T;KAClU,CAAC;IACU,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,4CAAmB;;wDAG1C;AAOK;IALL,IAAA,aAAI,EAAC,MAAM,CAAC;IACZ,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,0CAA0C;QACnD,WAAW,EAAE,mDAAmD;KACjE,CAAC;IACU,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,8CAAoB;;wDAG3C;AAQK;IANL,IAAA,YAAG,EAAC,KAAK,CAAC;IACV,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,8BAA8B;QACvC,WAAW,EACT,6GAA6G;KAChH,CAAC;IACY,WAAA,IAAA,cAAK,GAAE,CAAA;;qCAAS,mCAAe;;0DAO5C;AAQK;IANL,IAAA,aAAI,EAAC,YAAY,CAAC;IAClB,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,0BAA0B;QACnC,WAAW,EACT,+UAA+U;KAClV,CAAC;IACY,WAAA,IAAA,cAAK,GAAE,CAAA;;qCAAS,mCAAe;;0DAG5C;uCAnDU,4BAA4B;IAHxC,IAAA,iBAAO,EAAC,yBAAyB,CAAC;IAClC,IAAA,uBAAa,GAAE;IACf,IAAA,mBAAU,EAAC,2BAA2B,CAAC;qCAGC,yCAAkB;QAC1B,wBAAU;GAH9B,4BAA4B,CAoDxC"}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { SqlService } from '../../common/services/sql.service';
|
|
2
2
|
import { AdminAccessService } from '../services/admin.access.service';
|
|
3
|
+
import { CommonParamsDto } from '../../common/dtos/common.params.dto';
|
|
3
4
|
import { AddTenantDto } from '../dtos/add.tenant.dto';
|
|
4
5
|
import { TenantListDto } from '../dtos/tenant.list.dto';
|
|
5
6
|
import { EmailNotificationService } from '../../notification/services/email.notification.service';
|
|
6
7
|
import { SystemPropertyService } from '../../common/services/system.property.service';
|
|
8
|
+
import { TenantEntity } from '../../tenant/entities/tenant.entity';
|
|
7
9
|
export declare class AdminTenantController {
|
|
8
10
|
private readonly adminAccessService;
|
|
9
11
|
private readonly sqlService;
|
|
10
12
|
private readonly emailNotificationService;
|
|
11
13
|
private readonly systemPropertyService;
|
|
12
14
|
constructor(adminAccessService: AdminAccessService, sqlService: SqlService, emailNotificationService: EmailNotificationService, systemPropertyService: SystemPropertyService);
|
|
13
|
-
onboard(dto: AddTenantDto): Promise<
|
|
15
|
+
onboard(dto: AddTenantDto): Promise<TenantEntity>;
|
|
14
16
|
list(dto: TenantListDto): Promise<{
|
|
15
17
|
records: import("../..").SqlRow[];
|
|
16
18
|
total: number;
|
|
@@ -18,6 +20,7 @@ export declare class AdminTenantController {
|
|
|
18
20
|
limit: number;
|
|
19
21
|
total_pages: number;
|
|
20
22
|
}>;
|
|
21
|
-
|
|
23
|
+
detail({ id }: CommonParamsDto): Promise<TenantEntity>;
|
|
24
|
+
remove({ id }: CommonParamsDto): Promise<import("../types/admin.types").DeleteResult>;
|
|
22
25
|
}
|
|
23
26
|
//# sourceMappingURL=admin.tenant.controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.tenant.controller.d.ts","sourceRoot":"","sources":["../../../src/admin/controllers/admin.tenant.controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"admin.tenant.controller.d.ts","sourceRoot":"","sources":["../../../src/admin/controllers/admin.tenant.controller.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAItE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,wDAAwD,CAAC;AAClG,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAEnE,qBAGa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,wBAAwB;IACzC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;gBAHrB,kBAAkB,EAAE,kBAAkB,EACtC,UAAU,EAAE,UAAU,EACtB,wBAAwB,EAAE,wBAAwB,EAClD,qBAAqB,EAAE,qBAAqB;IASzD,OAAO,CAAS,GAAG,EAAE,YAAY;IAejC,IAAI,CAAS,GAAG,EAAE,aAAa;;;;;;;IAW/B,MAAM,CAAU,EAAE,EAAE,EAAE,EAAE,eAAe;IAevC,MAAM,CAAU,EAAE,EAAE,EAAE,EAAE,eAAe;CAI9C"}
|
|
@@ -17,6 +17,7 @@ const common_1 = require("@nestjs/common");
|
|
|
17
17
|
const swagger_1 = require("@nestjs/swagger");
|
|
18
18
|
const sql_service_1 = require("../../common/services/sql.service");
|
|
19
19
|
const admin_access_service_1 = require("../services/admin.access.service");
|
|
20
|
+
const common_params_dto_1 = require("../../common/dtos/common.params.dto");
|
|
20
21
|
const tenant_data_processor_1 = require("../libraries/tenant.data.processor");
|
|
21
22
|
const tenant_delete_processor_1 = require("../libraries/tenant.delete.processor");
|
|
22
23
|
const tenant_list_processor_1 = require("../libraries/tenant.list.processor");
|
|
@@ -24,6 +25,7 @@ const add_tenant_dto_1 = require("../dtos/add.tenant.dto");
|
|
|
24
25
|
const tenant_list_dto_1 = require("../dtos/tenant.list.dto");
|
|
25
26
|
const email_notification_service_1 = require("../../notification/services/email.notification.service");
|
|
26
27
|
const system_property_service_1 = require("../../common/services/system.property.service");
|
|
28
|
+
const tenant_entity_1 = require("../../tenant/entities/tenant.entity");
|
|
27
29
|
let AdminTenantController = class AdminTenantController {
|
|
28
30
|
constructor(adminAccessService, sqlService, emailNotificationService, systemPropertyService) {
|
|
29
31
|
this.adminAccessService = adminAccessService;
|
|
@@ -36,10 +38,17 @@ let AdminTenantController = class AdminTenantController {
|
|
|
36
38
|
return new tenant_data_processor_1.TenantDataProcessor(user, this.emailNotificationService, this.systemPropertyService).process(dto);
|
|
37
39
|
}
|
|
38
40
|
async list(dto) {
|
|
39
|
-
await this.adminAccessService.
|
|
41
|
+
await this.adminAccessService.validateContentReader();
|
|
40
42
|
return new tenant_list_processor_1.TenantListProcessor(this.sqlService).process(dto);
|
|
41
43
|
}
|
|
42
|
-
async
|
|
44
|
+
async detail({ id }) {
|
|
45
|
+
await this.adminAccessService.validateContentReader();
|
|
46
|
+
const tenant = await tenant_entity_1.TenantEntity.findOne({ where: { id } });
|
|
47
|
+
if (!tenant)
|
|
48
|
+
throw new common_1.NotFoundException('No tenant exists for this id');
|
|
49
|
+
return tenant;
|
|
50
|
+
}
|
|
51
|
+
async remove({ id }) {
|
|
43
52
|
const { user } = await this.adminAccessService.validateSuperAdmin();
|
|
44
53
|
return new tenant_delete_processor_1.TenantDeleteProcessor(user).process(id);
|
|
45
54
|
}
|
|
@@ -60,22 +69,33 @@ __decorate([
|
|
|
60
69
|
(0, common_1.Post)('list'),
|
|
61
70
|
(0, swagger_1.ApiOperation)({
|
|
62
71
|
summary: 'List, search and filter tenants.',
|
|
63
|
-
description: 'Requires at least the global
|
|
72
|
+
description: 'Requires at least the global content reader role.',
|
|
64
73
|
}),
|
|
65
74
|
__param(0, (0, common_1.Body)()),
|
|
66
75
|
__metadata("design:type", Function),
|
|
67
76
|
__metadata("design:paramtypes", [tenant_list_dto_1.TenantListDto]),
|
|
68
77
|
__metadata("design:returntype", Promise)
|
|
69
78
|
], AdminTenantController.prototype, "list", null);
|
|
79
|
+
__decorate([
|
|
80
|
+
(0, common_1.Get)(':id'),
|
|
81
|
+
(0, swagger_1.ApiOperation)({
|
|
82
|
+
summary: 'One tenant, in full.',
|
|
83
|
+
description: 'Everything the listing leaves out — address, attributes and the onboarding trail. Requires at least the global reader role.',
|
|
84
|
+
}),
|
|
85
|
+
__param(0, (0, common_1.Param)()),
|
|
86
|
+
__metadata("design:type", Function),
|
|
87
|
+
__metadata("design:paramtypes", [common_params_dto_1.CommonParamsDto]),
|
|
88
|
+
__metadata("design:returntype", Promise)
|
|
89
|
+
], AdminTenantController.prototype, "detail", null);
|
|
70
90
|
__decorate([
|
|
71
91
|
(0, common_1.Post)(':id/delete'),
|
|
72
92
|
(0, swagger_1.ApiOperation)({
|
|
73
93
|
summary: 'Delete a tenant.',
|
|
74
94
|
description: "Soft delete: the row keeps its data with `deleted_at` set and drops out of every listing. The tenant's users are deleted with it and their sessions and refresh tokens revoked — tenant resolution matches on `is_active`, so leaving them behind would let them keep signing in. Requires the global super admin role.",
|
|
75
95
|
}),
|
|
76
|
-
__param(0, (0, common_1.Param)(
|
|
96
|
+
__param(0, (0, common_1.Param)()),
|
|
77
97
|
__metadata("design:type", Function),
|
|
78
|
-
__metadata("design:paramtypes", [
|
|
98
|
+
__metadata("design:paramtypes", [common_params_dto_1.CommonParamsDto]),
|
|
79
99
|
__metadata("design:returntype", Promise)
|
|
80
100
|
], AdminTenantController.prototype, "remove", null);
|
|
81
101
|
exports.AdminTenantController = AdminTenantController = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.tenant.controller.js","sourceRoot":"","sources":["../../../src/admin/controllers/admin.tenant.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"admin.tenant.controller.js","sourceRoot":"","sources":["../../../src/admin/controllers/admin.tenant.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { UserEntity } from '../../auth/entities/user.entity';
|
|
2
|
+
import { CommonParamsDto } from '../../common/dtos/common.params.dto';
|
|
3
|
+
import { AddBulkUsersDto } from '../dtos/add.bulk.users.dto';
|
|
4
|
+
import { AddClientUserDto } from '../dtos/add.client.user.dto';
|
|
5
|
+
import { ClientUserListDto } from '../dtos/client.user.list.dto';
|
|
6
|
+
import { AdminAccessService } from '../services/admin.access.service';
|
|
7
|
+
import { TenantService } from '../../tenant/services/tenant.service';
|
|
8
|
+
import { EmailNotificationService } from '../../notification/services/email.notification.service';
|
|
9
|
+
import { SystemPropertyService } from '../../common/services/system.property.service';
|
|
10
|
+
import { SqlService } from '../../common/services/sql.service';
|
|
11
|
+
export declare class AdminTenantUserController {
|
|
12
|
+
protected readonly adminAccessService: AdminAccessService;
|
|
13
|
+
protected readonly tenantService: TenantService;
|
|
14
|
+
protected readonly emailNotificationService: EmailNotificationService;
|
|
15
|
+
protected readonly systemPropertyService: SystemPropertyService;
|
|
16
|
+
protected readonly sqlService: SqlService;
|
|
17
|
+
constructor(adminAccessService: AdminAccessService, tenantService: TenantService, emailNotificationService: EmailNotificationService, systemPropertyService: SystemPropertyService, sqlService: SqlService);
|
|
18
|
+
clientUserDetail({ id }: CommonParamsDto): Promise<UserEntity>;
|
|
19
|
+
addClientUser(dto: AddClientUserDto): Promise<UserEntity>;
|
|
20
|
+
addClientUsersBulk(dto: AddBulkUsersDto): Promise<import("../types/admin.types").BulkUserResult>;
|
|
21
|
+
listClientUsers(dto: ClientUserListDto): Promise<{
|
|
22
|
+
records: import("../..").SqlRow[];
|
|
23
|
+
total: number;
|
|
24
|
+
page: number;
|
|
25
|
+
limit: number;
|
|
26
|
+
total_pages: number;
|
|
27
|
+
}>;
|
|
28
|
+
removeClientUser(id: string): Promise<import("../types/admin.types").DeleteResult>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=admin.tenant.user.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.tenant.user.controller.d.ts","sourceRoot":"","sources":["../../../src/admin/controllers/admin.tenant.user.controller.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAKjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wDAAwD,CAAC;AAClG,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAE/D,qBACa,yBAAyB;IAElC,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB;IACzD,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,aAAa;IAC/C,SAAS,CAAC,QAAQ,CAAC,wBAAwB,EAAE,wBAAwB;IACrE,SAAS,CAAC,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IAC/D,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,UAAU;gBAJtB,kBAAkB,EAAE,kBAAkB,EACtC,aAAa,EAAE,aAAa,EAC5B,wBAAwB,EAAE,wBAAwB,EAClD,qBAAqB,EAAE,qBAAqB,EAC5C,UAAU,EAAE,UAAU;IASrC,gBAAgB,CAAU,EAAE,EAAE,EAAE,EAAE,eAAe;IAiBjD,aAAa,CAAS,GAAG,EAAE,gBAAgB;IAc3C,kBAAkB,CAAS,GAAG,EAAE,eAAe;IAW/C,eAAe,CAAS,GAAG,EAAE,iBAAiB;;;;;;;IAW9C,gBAAgB,CAA6B,EAAE,EAAE,MAAM;CAI9D"}
|