MemberJunction / MemberJunction/MJ

Field-Level Security: no UI can enable it — `EnableFieldLevelSecurity` is not exposed on the Entity form

Open
#4,297 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
TSQL
Stars
29
Forks
6
Avg merge
2d 1h
Merged PRs (30d)
323

Description

## Summary

Field-level security is gated entirely on `Entity.EnableFieldLevelSecurity`. Every enforcement point in the feature tests that boolean first and short-circuits when it is off, and reconciliation/snapshot initialization is triggered by the flag going from off to on. **There is no way to set it in the product.**

## Detail

The *generated* Entity form does render the field:

`packages/Angular/Explorer/core-entity-forms/src/lib/generated/Entities/MJEntity/mjentity.form.component.html`

...but `MJ: Entities` has a **custom** form registered, which wins by ClassFactory priority and does not expose it:

`packages/Angular/Explorer/core-entity-forms/src/lib/custom/Entities/entity-form.component.{ts,html}`

That form surfaces `TrackRecordChanges`, `AllowCaching` and the other entity-level configuration, but has no control for `EnableFieldLevelSecurity`.

Consequence: an administrator following the Field-Level Security guide reaches "turn the flag on" with nothing to click. Every manual verification pass during development had to flip it through the entity layer from the browser console.

## Why direct SQL is not an acceptable workaround

Enabling the flag is not a plain column write. `MJEntityEntityServer.Save()` wraps two things in one entity transaction — persisting the flag, then running `ReconcileFieldPermissions` to snapshot the entity's existing entity-level permissions into per-field rows. On an FLS-enabled entity **a field with no permission rows is denied**, so committing the flag without the snapshot locks every user out of every field on that entity until something else reconciles.

So the fix has to go through the entity layer, not the table.

## Proposed fix

Add the flag to the custom Entity form's configuration section, alongside `TrackRecordChanges` / `AllowCaching`. Worth considering as part of the same change:

- a confirmation step explaining that enabling writes snapshot rows and disabling retains them;
- surfacing the resulting `MJ: Entity Field Permissions` rows for the entity, since there is currently no administrative surface for those either.

## References

- Guide: `guides/FIELD_LEVEL_SECURITY_GUIDE.md` §1.1 (configuration model) and §5 (operational notes)
- Flag semantics: `packages/MJCore/src/generic/entityInfo.ts` (`EntityInfo.EnableFieldLevelSecurity`)
- Snapshot-on-enable: `packages/MJCoreEntitiesServer/src/custom/MJEntityEntityServer.server.ts`

Contributor guide

Open the contributing guide

Research direction

Start with packages/Angular/Explorer/core-entity-forms/src/lib/custom/Entities/entity-form.component.ts and entity-form.component.html, comparing the custom form with the generated form. Read packages/MJCoreEntitiesServer/src/custom/MJEntityEntityServer.server.ts and the Field-Level Security guide to understand the enable-time snapshot behavior. Done means administrators can enable the flag through the custom Entity form without bypassing the entity layer.

Written by the indexing model from the issue text.

Assessment

Tech stack
angular, typescript
Domain
frontend, security
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.