← Files Microsoft DataverseARCHIVED FILE

skills/dv-admin/references/settings-overrides.md

3.12 KB · Oct 4, 2026 · 12:28 UTC

↓ Download file

# Settings-Definition Overrides (app/plan security roles)

A small number of allowlisted toggles don't live on the `organization` entity or in `orgdborgsettings`. They're modeled as a join between two entities:

- **`settingdefinition`** — defines the setting (uniquename, datatype, defaultvalue, description). Read-only; one row per known setting; identical across environments in the same build.
- **`organizationsettings`** — holds per-org overrides. If no row exists for a given `settingdefinitionid`, the `defaultvalue` from `settingdefinition` applies.

Allowlisted uniquenames (both `datatype=2` bool, stored as string `"true"`/`"false"`):
- `PowerAppsAppLevelSecurityRolesEnabled` — Enable app level security roles for canvas apps
- `PlanShareSecurityRolesEnabled` — Enable plan level security roles for plan designer

**Read current value:**

```python
import os, sys
sys.path.insert(0, os.path.join(os.getcwd(), "scripts"))
from auth import get_client

client = get_client("dv-admin")

UNIQUENAME = "PowerAppsAppLevelSecurityRolesEnabled"   # or PlanShareSecurityRolesEnabled

# settingdefinition + organizationsetting are ordinary entities — plain SDK record reads.
defs = list(client.records.list(
    "settingdefinition",
    select=["settingdefinitionid", "uniquename", "defaultvalue", "datatype"],
    filter=f"uniquename eq '{UNIQUENAME}'",
))
if not defs:
    raise SystemExit(f"Setting '{UNIQUENAME}' is not defined in this environment (ECS-gated -- not available here).")
defn = defs[0]
sd_id = defn["settingdefinitionid"]
default = defn["defaultvalue"]

overrides = list(client.records.list(
    "organizationsetting",
    select=["organizationsettingid", "value"],
    filter=f"_settingdefinitionid_value eq {sd_id}",
))

current = overrides[0]["value"] if overrides else default
print(f"{UNIQUENAME} = {current} (default = {default}, override present: {bool(overrides)})", flush=True)
```

**Write (idempotent CREATE-or-PATCH):**

```python
# Continues from Read script above — reuses UNIQUENAME, sd_id, overrides, client.
NEW_VALUE = "true"   # bool-as-string; "true"/"false" (lowercase)

if overrides:
    client.records.update("organizationsetting", overrides[0]["organizationsettingid"], {"value": NEW_VALUE})
else:
    # No override exists — CREATE a new one (@odata.bind uses the entity-set path).
    client.records.create("organizationsetting", {
        "settingdefinitionid@odata.bind": f"settingdefinitions({sd_id})",
        "value": NEW_VALUE,
    })
print(f"SUCCESS: {UNIQUENAME} = {NEW_VALUE}", flush=True)
```

**Notes:**
- `datatype=2` means bool; other values exist for string/int but only bool toggles are in our allowlist today.
- `value` is always a **string**, even for bool and int definitions — `"true"` not `True`.
- The two allowlisted uniquenames are gated by ECS feature flags (`enablePowerAppsAppLevelSecurityRolesToggle`, `enablePlanShareSecurityRolesToggle`) in the PPAC UI, but the entities exist regardless — if the flag is off in an env, setting the override still takes effect.
- `DELETE` on the override row reverts to the `settingdefinition.defaultvalue`.

SHA-256: 2f6bc0dfbdd5eeba77fd9b35a6807882130d68b9140077925118a3acde1444e1