Skip to content

wisefoxme/plugin-migrate-permset-perms

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

plugin-migrate-permset-perms

NPM Downloads/week License

Commands

sf migrate layout edit

Add, move, or remove fields on page layouts using a YAML file or single-operation flags.

USAGE
  $ sf migrate layout edit -t <value> [--json] [--flags-dir <value>] [-f <value>] [--field <value>] [--remove]
    [--at-top-of <value>] [--at-bottom-of <value>] [--layouts <value>...] [--read-only] [--required] [--api-version
    <value>]

FLAGS
  -f, --file=<value>          Path to a YAML layout edit specification (`upsert` / `remove`).
  -t, --target-org=<value>    (required) Username or alias of the org to retrieve from and deploy to.
      --api-version=<value>   Override the api version used for api requests made by this command
      --at-bottom-of=<value>  Place the field immediately below this existing `Object.Field` (single-operation mode).
      --at-top-of=<value>     Place the field immediately above this existing `Object.Field` (single-operation mode).
      --field=<value>         Field API name as `Object.Field` (single-operation mode; not used with `--file`).
      --layouts=<value>...    Limit to these layout FullName values (repeat flag or use multiple times). Default: all
                              layouts for the object.
      --[no-]read-only        Set layout item behavior to Readonly (upsert / single-operation upsert only).
      --remove                Remove this field from the selected layouts (single-operation mode). Cannot be combined
                              with `--at-top-of` / `--at-bottom-of`.
      --[no-]required         Set layout item behavior to Required (upsert / single-operation upsert only).

GLOBAL FLAGS
  --flags-dir=<value>  Import flag values from a directory.
  --json               Format output as json.

DESCRIPTION
  Add, move, or remove fields on page layouts using a YAML file or single-operation flags.

  Lists layouts **only** via the **Tooling API** (no Metadata `listMetadata` fallback). First resolve
  **`Layout.TableEnumOrId`** with `SELECT DurableId FROM EntityDefinition WHERE QualifiedApiName = '<ObjectApiName>'` —
  for **standard** objects `DurableId` is the same as the API name (e.g. `Account`); for **custom** objects it is the
  entity id (e.g. `01I…`). Then `SELECT Id, Name FROM Layout WHERE TableEnumOrId = '<DurableId>'`. Layout metadata
  **FullName** values are built as `<ObjectApiName>-<Name>` (Tooling cannot return `FullName` when multiple layout rows
  match in one query). Failures: unknown object (`UnknownObjectApiName`), Tooling errors (`LayoutListError`), or no
  layouts (`NoLayoutsForObject`). Retrieves **Layout** metadata with `@salesforce/source-deploy-retrieve` into a
  temporary directory, edits `layoutSections` XML, then deploys when something changed.

  If a **reference field** for placement is not on a layout, that layout is skipped with a **warning** (no deploy for
  that file).

  Detail **layoutSections** only; related lists and other regions are not searched for the reference.

EXAMPLES
  YAML specification:

    $ sf migrate layout edit -f layouts.yaml -t myorg

  Place `Contact.Custom__c` immediately below `Contact.Email` on all Contact layouts:

    $ sf migrate layout edit -t myorg --field Contact.Custom__c --at-bottom-of Contact.Email

  Remove a field from named layouts only:

    $ sf migrate layout edit -t myorg --field Contact.Custom__c --remove --layouts "Contact-Contact Layout"

See code: src/commands/migrate/layout/edit.ts

sf migrate permset assign

Create, update, or remove FieldPermissions (FLS read/edit) on one or more target orgs from a YAML specification.

USAGE
  $ sf migrate permset assign -f <value> -t <value>... [--json] [--flags-dir <value>] [--include-profile-owned] [--strict]
    [--api-version <value>]

FLAGS
  -f, --file=<value>           (required) Path to the YAML assign specification file.
  -t, --target-org=<value>...  (required) Username or alias of an org to update (repeat for multiple targets).
      --api-version=<value>    Override the api version used for api requests made by this command
      --include-profile-owned  Include permission sets owned by profiles (IsOwnedByProfile = true).
      --strict                 Fail if any object or field from the YAML is missing on the target org. When omitted,
                               missing target fields/objects are skipped with warnings.

GLOBAL FLAGS
  --flags-dir=<value>  Import flag values from a directory.
  --json               Format output as json.

DESCRIPTION
  Create, update, or remove FieldPermissions (FLS read/edit) on one or more target orgs from a YAML specification.

  Reads a YAML file that defines **PermsetGroups** (named groups of permission set API names), an **Upsert** section
  (grant read/edit via group references), and a **Remove** section (revoke read/edit). Each of Upsert and Remove is a
  list of entries; each entry is either **Objects** (nested object and field names) or **Fields** (full `Object.Field`
  API names).

  Preflight validation uses the Tooling API (`EntityDefinition`, `FieldDefinition`) on each target org. By default,
  objects or fields missing on a target are skipped with warnings. Use **--strict** to fail instead.

  **Upsert** merges grants onto the current org state (OR for read/edit). Granting edit forces read on for that row.
  **Remove** is applied after Upsert on the merged state: revoking read also clears edit. If both read and edit end up
  false, the FieldPermissions row is deleted.

  By default, only permission sets with `IsOwnedByProfile = false` are considered. Use **--include-profile-owned** to
  include profile-owned (shadow) permission sets.

EXAMPLES
  Apply `spec.yaml` to two orgs:

    $ sf migrate permset assign --file spec.yaml -t sandbox -t prod

  Strict validation and include profile-owned permission sets:

    $ sf migrate permset assign -f ./perms/spec.yaml -t myorg --strict --include-profile-owned

See code: src/commands/migrate/permset/assign.ts

sf migrate permset copy

Copy FieldPermissions and/or ObjectPermissions from a source org to a target org for matching permission sets.

USAGE
  $ sf migrate permset copy -s <value> -t <value> -p <value> [--json] [--flags-dir <value>] [--include-profile-owned]
    [--strict] [--api-version <value>]

FLAGS
  -p, --perms=<value>          (required) Comma-separated list: object API name for object-level permissions only;
                               Object.Field or Object:Field for one field; Object._ or Object:_ for all FLS-enabled
                               fields on that object (expanded using Tooling FieldDefinition on the source org).
  -s, --source-org=<value>     (required) Username or alias of the org to read permissions from.
  -t, --target-org=<value>     (required) Username or alias of the org to update.
      --api-version=<value>    Override the api version used for api requests made by this command
      --include-profile-owned  Include permission sets owned by profiles (IsOwnedByProfile = true).
      --strict                 Fail if any object or field from --perms is missing on the target org. When omitted,
                               missing target fields/objects are skipped with warnings.

GLOBAL FLAGS
  --flags-dir=<value>  Import flag values from a directory.
  --json               Format output as json.

DESCRIPTION
  Copy FieldPermissions and/or ObjectPermissions from a source org to a target org for matching permission sets.

  Provide one or more permission targets with `--perms`:

  - **Object only** (e.g. `Account`) — syncs **ObjectPermissions** for that object (create/read/edit/delete, etc.). Does
  not read FieldPermissions for that token.
  - **Field** (`Object.Field` or `Object:Field`, e.g. `Account.Name`) — syncs **FieldPermissions** for that field.
  Object-level permissions for that object are also synced for permission sets that have source field rows (narrow
  scope).
  - **All fields on an object** (`Object.*` or `Object:*`) — expands to every field on that object that is
  **FLS-enabled** in metadata (Tooling **FieldDefinition** / `IsFlsEnabled` on the **source** org), then syncs
  FieldPermissions like individual field tokens. Wildcard expansion uses the Tooling API so the list does not depend on
  the user’s field visibility.

  You may mix tokens in one command (e.g. `Account,Contact.Email` or `Contact.*`).

  Queries FieldPermissions and ObjectPermissions on the source and target orgs as needed, matches permission sets by API
  name (PermissionSet.Name) and NamespacePrefix, computes the diff (source is the source of truth), then applies
  inserts, updates, and deletes on the target.

  Wildcard expansion and preflight validation use the **Tooling API** (`FieldDefinition`, `EntityDefinition`) so object
  and field names come from org metadata; the running user must have Tooling access (e.g. View Setup and Configuration),
  not only FLS on the migrated fields.

  By default, only permission sets with IsOwnedByProfile = false are considered. Use --include-profile-owned to include
  profile-owned (shadow) permission sets.

  By default, fields (and objects) that are not present on the **target** org are **skipped** with a warning so the rest
  of the migration still runs. Use **--strict** to fail the command instead when anything in `--perms` is missing on the
  target.

EXAMPLES
  Copy FLS for two fields between aliases `org1` and `org2`:

    $ sf migrate permset copy --source-org org1 --target-org org2 --perms \
      "Account.My_Field**c,Custom_Object**c.Other\_\_c"

  Object-level permissions for Account only, plus one field on Contact:

    $ sf migrate permset copy -s org1 -t org2 --perms "Account,Contact:Email\_\_c"

  Use colon separators and include profile-owned permission sets:

    $ sf migrate permset copy -s org1 -t org2 --perms "Object**c:Field**c" --include-profile-owned

  Sync all permissionable Contact fields (wildcard):

    $ sf migrate permset copy -s org1 -t org2 --perms "Contact.\*"

See code: src/commands/migrate/permset/copy.ts

Limitations

  • Permission sets are matched across orgs by API name (PermissionSet.Name) and NamespacePrefix. If the same API name exists in different namespaces, resolve collisions by ensuring metadata is unambiguous on both sides.
  • Only permission sets that already exist on the target are updated. Source-only permission sets are reported in JSON output under skippedPermissionSets and are not created on the target.
  • Object-only tokens (e.g. Account) sync ObjectPermissions for that object for every matched permission set on both orgs. Field tokens sync FieldPermissions only for that field; if you do not pass any object-only token, object-level rows for that object are synced only for permission sets that have source field rows. If you pass both (e.g. Account,Account.Name), object-level sync covers all matched sets for the objects in your --perms list, and the source query includes ObjectPermissions for every matched permission set so rows are not missed when discovery omitted a parent.
  • DML order on the target is: insert ObjectPermissions then FieldPermissions, then updates in the same order, then delete FieldPermissions then ObjectPermissions, so object rows exist before field rows and revokes remove field rows before object rows. Field/Object permission deletes use one REST DELETE per record Id (not the composite ?ids= batch) for compatibility with Salesforce responses. Query rows normalize Id / id from the API.
    • Object.* (or Object:*) expands to fields on that object where Tooling FieldDefinition reports IsFlsEnabled (same idea as “permissionable” in describe). The field list is resolved on the source org via the Tooling API (metadata, not the user’s FLS visibility). By default, fields (or whole objects) that are missing on the target are skipped with a warning; use --strict to fail instead if anything in --perms is absent on the target.
  • Schema checks use the Tooling API (FieldDefinition, EntityDefinition). The integration user needs access to Tooling (e.g. View Setup and Configuration or equivalent), not only FLS on the fields being migrated. FieldDefinition SOQL filters use the EntityDefinition relationship in the WHERE clause (not only FROM FieldDefinition).
  • Field sync only considers FieldPermissions rows whose SobjectType matches an object from --perms (e.g. Contact.* ignores unrelated rows such as other entities that can appear in broad queries). That avoids diffing or deleting FLS for objects you did not request.
  • sf migrate layout edit retrieves and deploys Layout metadata via @salesforce/source-deploy-retrieve into a temp directory (no local DX project required). Layout listing is Tooling-only (no Metadata listMetadata fallback). It resolves Layout.TableEnumOrId via SELECT DurableId FROM EntityDefinition WHERE QualifiedApiName = '<apiName>' — for standard objects DurableId matches the API name; for custom objects it is the entity id (e.g. 01I…). Then SELECT Id, Name FROM Layout WHERE TableEnumOrId = '<DurableId>'; metadata FullName values are <apiName>-<Name> (Tooling returns MALFORMED_QUERY if FullName is selected when more than one layout row is returned). After deploy, you can confirm field order with node scripts/verify-layout-field-position.mjs (after yarn compile) on a retrieved .layout-meta.xml. Placement looks for the reference field only under detail layoutSectionslayoutColumnslayoutItems. If the reference is missing, that layout is skipped with a warning and is not deployed. The plugin build enables skipLibCheck so third-party packages (including SDR) type-check without pulling their JSON typings into the project compile.
  • Layout deploy errors (LayoutDeployError) include component-level messages from the Metadata API when present (many orgs return status: Failed with a blank errorMessage, while the real text is under details.componentFailures). The message includes the Deploy Id so you can match it in Setup → Deployment Status. If you move a standard Name field and set --read-only, the deploy may be rejected—retry without --read-only if the failure mentions name or editability.

YAML schema example

# define the groups of permission sets that we will grant permissions to
PermsetGroups:
  - name: 'Group 1'
    permsets: [set1, set2, setN]
  - name: 'Group 2'
    permsets: [set1, set2, setN]

# "Upsert" contains the permissions the command will create or update
Upsert:
  # objects that we will grant permissions to
  - Objects:
      - name: 'Object'
        perms:
          - type: read
            permsets: ['Group 1', 'Group 2']
          - type: edit
            permsets: ['Group 1']

  # fields that we will grant permissions to
  - Fields:
      - name: 'Object.Field'
        perms:
          - type: read
            permsets: ['Group 1', 'Group 2']
          - type: edit
            permsets: ['Group 1']

  # The above literally means:
  # For these objects, grant read permission to Group 1 and Group 2, where
  # "read" is granted to permission sets in group "Group 1" and "Group 2"
  # and "edit" is granted to permission sets in group "Group 1"
  # For the field "Field" on the object "Object", grant read permission to
  # groups "Group 1" and "Group 2", where "read" is granted to permission sets
  # in group "Group 1" and "edit" is granted to permission sets in group "Group
  # 1"

# "Remove" contains the permissions the command will remove
Remove:
  - Objects:
      - name: 'Object'
        perms:
          - type: read
            permsets: ['Group 1', 'Group 2']
          - type: edit
            permsets: ['Group 1']

  - Fields:
      - name: 'Object.Field'
        perms:
          - type: read
            permsets: ['Group 1', 'Group 2']
          - type: edit
            permsets: ['Group 1']

  # The above literally means:
  # For these objects, revoke read permission from Group 1 and Group 2, where
  # "read" is revoked from permission sets in group "Group 1" and "Group 2"
  # and "edit" is revoked from permission sets in group "Group 1"
  # For the field "Field" on the object "Object", revoke read permission from
  # groups "Group 1" and "Group 2", where "read" is revoked from permission sets
  # in group "Group 1" and "edit" is revoked from permission sets in group "Group
  # 1"

Salesforce API references

About

Migrate permission set settings for object and field-level settings between orgs

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors