# @servicelabsco/slabs-access-manager

NestJS access-domain library for Finnoto services. Install it into your app to get business users/roles/groups, menus, dashboards, reports, notifications (email / FCM / Slack / GChat / WhatsApp), bulk upload, file upload, PDF generation, UI policy, and approval workflows — as Nest modules, TypeORM entities, services, jobs, and migrations.

This repo is also a runnable HTTP server, but **most teams consume it as an npm package**.

**Current major:** `2.x` · **Requires** Node `>=24.11.0` and `@servicelabsco/nestjs-utility-services` `^3.0.5`.

## Install

```bash
npm install @servicelabsco/slabs-access-manager@^2
```

Align your host app with the same Nest 11 / TypeORM / BullMQ stack that NU 3.x expects. Keep `nestjs-utility-services` on `^3.0.5` or newer within 3.x.

## Quick start

Import the modules you need next to your own `TypeOrmModule`, BullMQ, and NU modules (`AuthModule`, `PlatformUtilityModule`, `SystemModule`, etc.):

```ts
import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import {
  AccessModule,
  AccessUtilityModule,
  AccessWorkflowModule, // optional — approval / delegation
  BusinessMiddleware,
} from '@servicelabsco/slabs-access-manager';
import {
  AuthModule,
  BasicAuthMiddleware,
  JwtMiddleware,
  PlatformUtilityModule,
  RestrictedMiddleware,
  SystemModule,
} from '@servicelabsco/nestjs-utility-services';

@Module({
  imports: [
    // your TypeOrmModule.forRoot(...), BullModule.forRoot(...), ConfigModule, …
    AuthModule,
    SystemModule,
    PlatformUtilityModule,
    AccessModule,
    AccessUtilityModule,
    AccessWorkflowModule,
  ],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(JwtMiddleware, BasicAuthMiddleware).forRoutes({ path: '*', method: RequestMethod.ALL });
    consumer.apply(RestrictedMiddleware).forRoutes({ path: 'api/*', method: RequestMethod.ALL });
    consumer.apply(BusinessMiddleware).forRoutes({ path: 'api/b/*', method: RequestMethod.ALL });
  }
}
```

Adjust path prefixes to match your API. `BusinessMiddleware` loads business roles into `Auth.user()` for business-scoped routes.

## Using the package

Import from the package root (barrel generated on publish):

```ts
import {
  AccessModule,
  AccessUtilityModule,
  BusinessUserEntity,
  BusinessUserRoleService,
  ListingService,
  NotificationService,
  FileUploadService,
  BusinessParamDto,
} from '@servicelabsco/slabs-access-manager';
```

Typical export categories:

| Category | Examples |
| --- | --- |
| Modules | `AccessModule`, `AccessUtilityModule`, `AccessWorkflowModule` |
| Entities | `BusinessUserEntity`, `ApiAccountEntity`, `BulkUploadItemEntity`, … |
| Services | `ListingService`, `NotificationService`, `FileUploadService`, `ApiAccountService`, … |
| Libraries / use cases | `ProcessDbFind`, `SendEmailService`, `ProcessBusinessUserRoleUpdate`, … |
| DTOs | `BusinessParamDto`, `CommonListFilterDto`, `DbFindOptionsDto`, … |
| Middleware | `BusinessMiddleware` |

Prefer the public root exports. Deep `dist/...` paths are not a supported contract.

Inside handlers, use NU’s `Auth.user()` / `Auth.check()` — not `req.user`. Business context is usually at `Auth.user().auth_attributes.business_id`.

## Domain modules

### `AccessModule`

Core access domain: business users, roles, groups, menus, features, dashboards, reports, scripts, webhooks, choice lists, custom fields, listings, currencies, app integrations, and notification channels.

Depends on NU (`AuthModule`, `PlatformUtilityModule`, `SystemModule`) and pulls in `AccessUtilityModule`.

### `AccessUtilityModule`

Shared utilities used by Access and by host apps: bulk upload, S3/Lambda file upload, PDF documents, UI policy, data-access helpers.

Uses `forwardRef(() => AccessModule)` to break the Nest cycle with Access.

### `AccessWorkflowModule`

Approval workflow steps, stage activity, authority delegation, and related limit/config surfaces. Import only if your product uses workflows. Depends on both Access modules.

## Database and migrations

Entities and migrations ship inside this package under `dist/`.

Your TypeORM config should load sibling `@servicelabsco/*` entities and migrations the same way this app does, for example:

```ts
entities: [
  join(__dirname, '/../**/**/*.entity.{ts,js}'),
  join(__dirname, '..', '..', 'node_modules/@servicelabsco/**/*.entity.{ts,js}'),
],
migrations: [
  join(__dirname, '/../migrations/**/*.{ts,js}'),
  join(__dirname, '..', '..', 'node_modules/@servicelabsco/**/migrations/**/*.{ts,js}'),
],
migrationsTableName: 'sys_migrations',
synchronize: false,
```

Run migrations from the **host** app (or this package when you run it as a server). Do not enable `synchronize` against these tables.

Naming uses TypeORM `SnakeNamingStrategy` (`businessId` → `business_id`).

## Jobs and entity events (NU 3.0.5)

From NU `3.0.5`, entity-bound queue work and TypeORM subscribers can coexist:

- **Post-persist / async side effects** live on jobs decorated with `@SubscribeFor(SomeEntity)` (they receive `DatabaseEventDto` via the dispatcher after commit).
- **Synchronous `beforeInsert` / `beforeUpdate` / …** stay on TypeORM subscribers that extend `CommonSubscriber`.

Empty no-op jobs and subscribers were removed in 2.0. Do not reintroduce “subscriber only to `delayedDispatch` + job handling the same event” — that double-fires under the new model.

If you extend this package with your own entity reactions, follow the same split: mutate rows in `before*`, enqueue or react after persist with `@SubscribeFor`.

## Auth and HTTP surface

When you mount these modules, their controllers register under your Nest app. Protect them with the same middleware chain your product already uses for NU:

| Prefix (typical) | Middleware | Principal |
| --- | --- | --- |
| `*` | `JwtMiddleware`, `BasicAuthMiddleware` | Parse credentials if present |
| `api/*` | + `RestrictedMiddleware` | Authenticated JWT user |
| `api/b/*` | + `BusinessMiddleware` | Business roles on `Auth.user()` |
| `v1/*` / `internal/*` | Host-defined | API-key or server-to-server |

Exact routes depend on which modules you import. Treat published controllers, DTOs, and entities as a **versioned contract** — bumping this package can change them for every consumer.

## Runtime expectations

Consumers usually already provide:

- Postgres (primary; optional read replica connection named `'read'`)
- Redis + BullMQ (`BULL_QUEUE_NAME` / queue config compatible with NU)
- JWT / app secrets as required by `nestjs-utility-services`

This package does not replace your `AppModule` bootstrap; it plugs into it.

## Versioning

- **npm:** `@servicelabsco/slabs-access-manager`
- **2.x** — current major (NU `^3.0.5`, Node `>=24.11`, `@SubscribeFor` job model)
- Follow semver: breaking public surface → new major

Check [npm](https://www.npmjs.com/package/@servicelabsco/slabs-access-manager) for the latest published version.

## License

MIT
