Organization Module Settings (Super Admin)
Overview
This page is an internal super-administrator tool with two jobs:
- Enabling or disabling CMS modules per organization — deciding which features each organization can use. The outcome is what end users see in their sidebar.
- Setting plan limits — the maximum number of channels, audiences, workflows, templates and custom attributes an organization may create, shown alongside current usage.
It lives at /xsd2safsadf/module-setting, whose deliberately random first path segment is not linked from anywhere in the application. The URL has to be typed directly.
A note on security — hiding the URL is a convenience layer, not a protection mechanism. Real enforcement lives on the server, where every endpoint is guarded at the super-administrator level. A user without that role can open the page but will only see a "forbidden" notice, because every request is rejected with a 403.
The page has no frontend route guard and is written differently from the rest of the system: it does not use the shared request handler, and it sets neither a breadcrumb nor an active sidebar entry.
Business Flow
1. Opening the page and loading organizations
- On open, the token is checked and permissions are loaded as usual, then the organization list is fetched from
GET /org-module-setting/organizations. - If the server responds with a 403, the page renders only an alert saying a super-administrator account is required and stops there.
- Any other error — a server fault, a network failure — is swallowed silently. The user simply sees an empty organization picker.
- On success, the picker lists every organization with its id and name. Organizations with their own module configuration are suffixed with "custom", and the list is searchable.
2. Selecting an organization
- Choosing an organization triggers two fetches: the module list from
GET /org-module-setting/{orgId}and the plan limits fromGET /org-module-setting/{orgId}/limits. - Modules that are currently enabled arrive pre-checked in the table.
- A tag beside the picker reports the configuration state — blue when the organization has its own module set, grey when it uses the defaults.
- If the limits request fails — for instance because limits were never provisioned for this organization — the limits panel simply does not appear, with no explanation.
3. Toggling modules and saving
- The module table has three columns: an enable checkbox, the module name, and the list of actions that module supports.
- Checking and unchecking only changes local state; nothing is sent to the server yet.
- Save as override persists the checked set as this organization's own configuration via
PUT /org-module-setting/{orgId}. - Reset to default removes the custom configuration so the organization falls back to the standard module set.
- The server reports back whether the result is the baseline or an override, along with how many modules are enabled, and the page shows the matching confirmation message.
- After a successful save, the modules and limits are reloaded, and the organization list is refetched so the "custom" suffix stays accurate.
- If the save fails, a generic error message appears — the server's own message is not read.
4. Plan limits and usage
The limits panel appears once an organization is selected and its data loads successfully. It contains five rows:
| Row | What it caps |
|---|---|
| LINE OA channels | Maximum channels the organization can create |
| Audiences | Maximum audience segments |
| Active workflows | Maximum workflows running at once |
| Templates | Maximum message templates |
| Custom attributes | Maximum custom attributes |
Each row shows the label, usage against the limit, a progress bar, a number input, and an "unlimited" checkbox.
Display rules worth knowing:
- Rows set to unlimited show a full grey bar, and the number input is disabled.
- Rows that have reached or exceeded their limit are highlighted in red across the whole row so they stand out immediately.
- Unchecking "unlimited" sets the limit to the current usage rather than to zero, so the cap never lands below data that already exists.
The final row is a switch for automatic audience refresh, tagged "Premium". That tag is descriptive only — the switch is not actually gated by the plan.
Saving sends the whole limits object to PUT /org-module-setting/{orgId}/limits and then reloads the data.
5. Baseline versus override
Module entitlement has two levels:
| Level | Meaning | On-screen signal |
|---|---|---|
| Baseline | The default module set every organization receives | Grey tag; no suffix in the picker |
| Override | A custom module set defined for this organization by a super administrator | Blue tag; "custom" suffix in the picker |
Saving as an override creates or updates the custom set to match the checkboxes. Resetting deletes it so the organization returns to the baseline.
6. How this reaches end users
- A super administrator adjusts modules on this page.
- A user in that organization signs in, and the server returns only the permissions for modules the organization has enabled and the user's role allows.
- The frontend converts those permissions into its access rule set.
- The sidebar, quick-access menu and page-level guards all read that rule set to decide what the user can see and open.
Limitations to be aware of
- There is no unsaved-change tracking. Toggling modules or editing numbers and then switching organizations or closing the tab discards the edits silently.
- The save buttons are never disabled, so they can be pressed repeatedly with no changes.
- Non-403 errors while loading the organization list are swallowed entirely — no message, no retry.
- The limits panel disappears silently when its request fails, making "never provisioned" indistinguishable from any other problem.
- Limit and usage figures are a snapshot from load time; nothing refreshes automatically.
- There is no confirmation before disabling a module, even though doing so removes menu entries for every user in that organization the next time they reload.
Key Screens & Components
Page structure
The entire page lives in a single file (src/app/xsd2safsadf/module-setting/page.tsx), with no container/presenter split as elsewhere in the system. It holds the organization picker, the configuration-state tag, the module table, the two save buttons, and the plan limits panel.
Service layer
The service this page uses (src/services/org-module-setting.service.ts) bundles five functions: list organizations, read an organization's modules, save modules, read limits, and save limits.
API endpoints
| Operation | Endpoint |
|---|---|
| List organizations | GET /org-module-setting/organizations |
| Read an organization's modules | GET /org-module-setting/{orgId} |
| Save modules | PUT /org-module-setting/{orgId} |
| Read limits and usage | GET /org-module-setting/{orgId}/limits |
| Save limits | PUT /org-module-setting/{orgId}/limits |
Controlled elsewhere
Enabling and disabling mini-apps in the Apps group is not handled here. Those are set from the platform administrator's own console, and the CMS only reads the result — deliberately, so an organization cannot re-enable an app the platform administrator has switched off.
Dependencies
- Server-side authorization — the super-administrator guard protecting these endpoints is the real access control. The frontend merely catches the 403 and renders a notice.
- Permissions and navigation — the modules enabled here determine what permissions users in that organization receive, which in turn drives the sidebar, quick access, and page access throughout the CMS.
- Limit enforcement — limits are enforced server-side; creating data beyond quota is rejected there. This page only edits the numbers and performs almost no client-side validation.
- Sign-up — newly registered organizations need their modules enabled and quotas set here before they can be used fully.
Backend Details (CMS API)
This page is the platform administrator's console. What is configured here takes effect at the API level, not merely in the UI.
The authorization that is actually enforced
Every endpoint in this module is wrapped in the super-admin guard, which checks that the caller's role id equals 1 and returns 403 otherwise. That is what makes the randomized URL on the frontend a supplementary layer rather than the real defence, and it is the source of the "super administrator account required" notice the frontend renders when it catches a 403.
Enabling or disabling a module has two effects
Saving a module set through PUT /api/org-module-setting/:orgId writes the organization-level module settings table, and the result surfaces in two places at once:
- At the menu level —
GET /api/user/:id/permissionfor users in that organization now returns the override instead of the role baseline, so the cms-web menus change accordingly. - At the API level — ModuleGate on the disabled module's routes returns 403 immediately, even if the user calls the API directly, bypassing the frontend. Governance is therefore real, not just hidden buttons.
Crucially, both paths call the same resolver in the backend code, which guarantees that what the menus show and what the API permits can never disagree.
What baseline and override mean in data terms
- Baseline comes from the permissions attached to roles at the system level; every organization gets the same set.
- Override is a row specific to that organization. Saving a custom set replaces the whole set rather than adding items individually.
- The reset button tells the backend to delete all overrides for that organization, returning it to the role baseline.
- Platform-operator users always use the baseline and are never overridden — disabling a module for an organization still leaves internal staff with normal access.
How plan limits work on the backend
Plan limits are not a module with its own endpoints; they are an internal provider that other modules call whenever they are about to create something new. The sequence is: read the organization's configured value first, fall back to the platform default if that key is absent, then count the existing records and compare. If the count exceeds the limit, the request is rejected with a "package limit reached" message.
Platform defaults, used until an organization is configured:
| Item | Default |
|---|---|
| Maximum audiences | 5 |
| Concurrently active workflows | 3 |
| Message templates | 20 |
| Custom attributes | 30 |
| Audience auto-refresh | Off |
Additional points:
- A value of
-1means unlimited, matching the "unlimited" checkbox on screen. - The channel count is a special case — it is not stored alongside the other quotas but always read from the organization's legacy column, so it has no entry in the default set.
- The modules that actually enforce quotas are LINE OA management, audiences and audience filters, workflows, message templates, and attribute setup.
- The auto-refresh toggle is one of the real quota values the backend stores, even though the Premium badge on screen is purely descriptive.
The system module registry
The module list shown in this page's table comes from the system-wide module registry, which has its own management module — also super-admin guarded on every route — supporting create, update and soft delete.
One thing to watch when adding a new module: its name must match exactly the name ModuleGate checks in the code. If it does not, the gate cannot find it, so the module appears in the table and can be ticked, but enabling or disabling it has no effect at the API level at all.