Skip to main content

Users, Roles & Permissions

Overview

This feature has two halves that work together:

  • User administration at /user-management — creating, editing, viewing and deleting users, assigning roles, toggling status, deciding which LINE OAs each user can reach, and triggering password resets on their behalf.
  • The permission system — the machinery that turns the permissions the server returns into the rules the frontend uses to gate pages, menus and a handful of buttons.

Users are organization-level records, not tied to any single channel, so this page is treated as account-level in the same way as LINE OA Management and renders without the sidebar.

Worth knowing: this page does not appear in the sidebar. There are only two ways in — a button in the LINE OA Management header and the quick-access menu — and both are filtered by the user-view permission. The page itself is additionally protected by a route-level permission check, on both the list and the form.

Business Flow

1. User list

  1. On open, the app checks user-view permission, then sets the breadcrumb and active menu entry.
  2. The most recent filter is restored from sessionStorage and the list is fetched from GET /user.
  3. The toolbar holds a search box, a status filter, and a total-user counter.
  4. The table has five columns: row number, user details (initials avatar, full name that links to the detail view, and email), role, status, and actions.
  5. Role tags are coloured automatically from the role name — administrator-type roles in red, managers in orange, editors in blue.
  6. The actions column offers four buttons: edit, OA access, password reset and delete.
  7. Every change to the page, page size or filter is written back to sessionStorage.
  8. The "Create user" button sits in the page header.

2. Creating, editing and viewing a user

  1. The form page supports three modes — create, edit and read-only — distinguished by the URL parameters.
  2. It loads the role list for the dropdown, and the user record when an id is present.
  3. The form has five fields: first name, last name, email, role and status (active / inactive).
  4. In edit mode, email and role are locked and cannot be changed. Read-only mode disables every field and offers only a back button.
  5. Saving posts to POST /user for a new user or PUT /user/{id} for an existing one.
  6. On success a confirmation appears and the user returns to the list. If the server identifies invalid fields, errors are shown per field; otherwise an error modal is displayed.

3. Deleting a user

The delete button in the table opens an inline confirmation. Once confirmed, the app calls DELETE /user/{id} and reloads the table.

4. Resetting a user's password

The key icon opens a confirmation prompt. On confirmation the app calls POST /user/{id}/admin-reset-password, and the server emails that user a link to set a new password. The rest of that flow is covered under Password Management.

5. Assigning LINE OA access to a user

  1. The access button in the table opens a modal populated from GET /user/{id}/oa-access.
  2. The mode is inferred automatically: users who already have specific OAs assigned start in "specific OAs" mode, everyone else in "all OAs" mode.
  3. In specific mode the modal lists every channel with checkboxes.
  4. Choosing specific mode without selecting anything produces a warning and nothing is saved.
  5. Saving sends the selection to PUT /user/{id}/oa-access, where an empty list means access to every channel.
  6. The mirror image of this setting is the channel access modal in LINE OA Management, which views the same relationship from the channel's side.

6. Translating server permissions into frontend rules

  1. The server returns permissions as a list of modules, each with the actions the user is allowed — read, create, update, delete, export and so on.
  2. The frontend converts this in three steps:
    • Look up which frontend pages correspond to each server module name. Modules with no matching page are skipped.
    • Convert the actions: read-type actions become a "view" permission, and export becomes an "export" permission. Create, update and delete are not translated into the frontend permission system at all.
    • Fan out — a single server module may unlock several frontend pages at once.
  3. The resulting rules form a pure allow-list: there are no explicit denials and no record-level conditions.
  4. The rule set lives in global state but is not persisted, so it is rebuilt on every page load. It is compiled in exactly two places: when the application boots, and when the user selects a channel to work in.

The mapping from server modules to frontend pages:

Server modulePages unlocked
dashboardDashboard
line-oaLINE OA Management, Menu Builder and the whole content management group
userUser Management and the settings page
rich-menuAll three rich menu types (default, custom, switch)
rich-messageRich Message Management
template-messageTemplate Message Management
campaignCampaign Management and the Campaign Planner
auto-responseAuto Response and Quick Reply
report-all-friendsAll-friends report
audiencesEvery audience management variant
form-builderForm Builder and OTP configuration
customer-databaseMember database
import-mappingImport mapping
attribute-masterAttribute setup
trigger-ruleTrigger rules
workflowWorkflows
friend-trackFriend tracking
api-keyAPI key management
system-attributeSettings page
system_moduleKnowledge base and BigQuery sync

7. How permissions filter the interface

  • Page level — the page wrapper (PermissionGuard) renders nothing while permissions are still loading, shows a "no permission" screen when the check fails, and renders the real content when it passes.
  • Sidebar — each menu entry is added only if the user can view that page. The rich menu group checks the combined permission of all three types first, then filters each child. The Apps and Settings groups are shown without a permission check, except for the OTP configuration child.
  • Quick access — entries with no page reference always appear; entries that name one are filtered exactly as the sidebar is.
  • Button level — only a handful of buttons are filtered, such as the User Management button in the LINE OA Management header.
  • A limitation worth knowing — because create, update and delete actions are never translated into the frontend permission system, those buttons appear for everyone who can reach the page. The real enforcement happens server-side.
  • Super administrator — per-user channel access in LINE OA Management is gated by checking the role id directly rather than going through the central permission system.

Key Screens & Components

User list screen

All list logic lives in a single container (src/components/user-management/list/user-management.container.tsx), which builds the table, toolbar and columns inline and also handles deletion, password resets and searching.

OA access modal

The modal pairs a two-option mode selector with a checkbox list, letting administrators choose between granting access to every channel and naming specific ones.

User form screen

The form splits into a container that loads role options, assembles the payload and performs the save, and a presentational form that renders the fields and enables or disables them according to the current mode.

Permission layer

The permission layer lives under src/components/ability/ in two main files: one holding the module mapping table and the conversion function, and one that compiles the rules into a usable ability set.

Main API endpoints

OperationEndpoint
List usersGET /user
Read one userGET /user/{id}
Create a userPOST /user
Update a userPUT /user/{id}
Delete a userDELETE /user/{id}
A user's OA accessGET and PUT /user/{id}/oa-access
Administrator password resetPOST /user/{id}/admin-reset-password
Load permissions to build the rule setGET /user/{id}/permission
Role options for the dropdownGET /system-role/find-all-object

Dependencies

  • Login — the rule set is compiled when the application boots and again when a channel is selected, including the always-granted access to the OA selection page.
  • LINE OA Management — the main way into this page, and home to the channel access modal that mirrors the OA access setting here.
  • Password Management — the reset button in the table starts the flow that emails a user their password-reset link.
  • Role definitions — this CMS has no screen for managing roles and permissions; which modules a role can reach is configured on the server.
  • Every page in the system — the permission machinery described here determines which menus each user sees and which pages they can open.

Backend Details (CMS API)

This section matters more than most, because the backend permission system does not work the way its name suggests — and misreading it leads directly to an inaccurate security assessment.

Four permission layers, only three actually enforced

LayerEnforced?What it does
CASL policy (action/module level)Not enforcedMetadata exists on every route, but the checker lets every request through
SuperAdminGuardEnforcedRequires role id 1
ModuleGateEnforcedIf a platform administrator disables a module for an organization, its customers get 403 even when calling the API directly
AppEnabledGuardEnforcedAn app (appointment / loyalty / bulletin) must be enabled for that organization first

The key takeaway: the permissions stored against roles and modules exist only to show or hide menus in cms-web — they do not block API calls. This behaviour was carried over deliberately from the previous system, whose policy guard also always returned "allowed". So when this page notes that "real control lives on the server", that means ModuleGate and SuperAdminGuard, not per-action permissions.

What GET /api/user/:id/permission actually does

  1. Restricts reads to yourself — the user id in the path must match the token's user, otherwise the request is rejected with a "cannot access another user id" error. The frontend simply cannot read anyone else's permissions.
  2. Loads the user's baseline from the permissions attached to their role, and pulls the full list of system modules.
  3. Branches on the user's type — for customer-type users whose organization has module settings configured, the platform administrator's settings replace the role baseline. For platform-operator users (including role id 1), the role baseline always applies and is never overridden.
  4. Returns a list pairing module names with their allowed actions, which the frontend compiles into its rule set.

A consequence: two users with the same role in different organizations may see different menus if their organizations have different module settings.

ModuleGate — the layer that really blocks API calls

The gate runs in order: read the caller's type from the request context, let platform operators (or callers it cannot identify) through immediately, and for customers check whether the module is enabled for their organization using the same baseline-versus-override logic described above.

Error-handling behaviour worth knowing:

  • ModuleGate fails open. If the check itself errors — a stumbling query, for instance — the request is allowed through and the failure is logged, rather than denied, so a transient problem cannot lock an entire organization out.
  • The platform-only route fails closed, in contrast. The route that enables or disables apps for an organization denies by default when the check cannot be completed, because the risk there is privilege escalation.

Modules wrapped by ModuleGate: api-key, attribute-master, audiences, auto-response, campaign, customer-database, form-builder, friend-track, import-mapping, report-all-friends, rich-menu, rich-message, template-message, trigger-rule and workflow.

Inside the user module

  • Every route uses the guard that accepts tokens without an OA id, not the ordinary one, because user management is an account-level page that must be reachable before a channel is selected.
  • The user list is always scoped to the caller's organization, so an administrator in one organization never sees another's users even though the policy layer is not enforced.
  • User creation accepts multipart data to support avatar uploads, and hashes the password and records it in password history within the same request.
  • Deletion is a soft delete that stamps a deleted timestamp. A separate hard-delete route exists, requiring super admin plus an explicit confirmation parameter — the frontend exposes no button for it.
  • Per-user OA access writes the same table as the modal in LINE OA Management, so the two screens genuinely show one data set from opposite directions. This feature is new and did not exist in the previous system.
  • GET /api/user/find-all-object, used to populate dropdowns, carries no permission metadata at all, matching a comment left in the original system.

Inside system roles

  • The backend role module exposes a single endpoint, GET /api/system-role/find-all-object, purely to populate dropdowns.
  • There is no API for editing roles or their permissions. That data is master data set directly in the database and then adjusted per organization through organization module settings. This is the technical explanation for the observation that the CMS has no role management screen.
  • Role id 1 is the super admin, the value the super-admin guard checks directly — consistent with the frontend checking the role id itself rather than going through the central permission system.