How to set permissions
xly's permission model has two complementary tables. Understanding the difference matters: they answer different questions and are loaded at different times.
The two tables
| Table | Granularity | Loaded when |
|---|---|---|
gdsjurisdiction |
per module + per role + per button/data type | every getModelBysId call (skipped for ADMIN — see Slice 1) |
sysjurisdiction |
per user + per individual permission grant | session/auth time |
What gdsjurisdiction controls
Per-module rules that decide:
- Which buttons a role can see and click on the form (新增 / 修改 / 保存 / 删除 / 导出 / 打印 / …).
-
Which data a role can see — typically by limiting visible columns
or by adding extra
WHEREpredicates to the form'ssSqlStr.
Indexed by:
- The module the rule applies to.
- The button or data-type identifier (lookup IDs in
plat_base_authority_button_typeandplat_base_authority_data_type). - The role / user-type the rule applies to.
In dev there are 4,130 gdsjurisdiction rows — substantial. In
production, expect hundreds per module.
What sysjurisdiction controls
Per-user permission grants. 26,926 rows in dev — 6× larger than
gdsjurisdiction. Likely the table that records the actual granted
permissions per user, where gdsjurisdiction is the defined rules
the framework applies.
How permissions are loaded
When the SPA calls /business/getModelBysId/{moduleId}, the
service-layer pseudocode is:
if (!UserType.ADMIN.equals(userType)) {
jList = businessGdsconfigformsService.getJurisdictionData(qMap);
}
returnMap.put("gdsjurisdiction", jList);
— from BusinessBaseServiceImpl.java:196-198. ADMIN bypasses
permissions entirely and gets an empty jurisdiction list (which the
SPA interprets as "show everything"). Non-admin users get the rules
that apply to their role + module.
The frontend then enables/disables buttons and shows/hides columns based on those rules.
How to set a permission
For a new module, the typical path is:
- Define the module + form (recipe).
- For each role that should NOT have full access, insert
gdsjurisdictionrows describing what they cannot do. - (Or insert per-user grants in
sysjurisdictionif more granularity is needed.) - Save through BACK so cache invalidation propagates.
The exact column conventions for the rule rows (which combinations of fields express "can save but not delete", "can see but not edit", etc.) deserve their own walkthrough that the wiki should add as a follow-up.
ADMIN as a special case
The hardcoded ADMIN bypass (line 196-198 above) is a real escape hatch. Every deployment has at least one ADMIN account by convention. From a security audit perspective, ADMIN access should be tightly controlled and audited externally — the framework offers no within-app constraint.
Cross-tenant boundary is not permissions
Worth saying explicitly: gdsjurisdiction enforces within-tenant
permissions. The cross-tenant boundary (one company can't read another
company's rows) is enforced by the
multi-tenant scoping — automatic
sBrandsId/sSubsidiaryId injection, not jurisdiction rules.