permissions.md 3.33 KB

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 WHERE predicates to the form's sSqlStr.

Indexed by:

  • The module the rule applies to.
  • The button or data-type identifier (lookup IDs in plat_base_authority_button_type and plat_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:

  1. Define the module + form (recipe).
  2. For each role that should NOT have full access, insert gdsjurisdiction rows describing what they cannot do.
  3. (Or insert per-user grants in sysjurisdiction if more granularity is needed.)
  4. 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.