# Site Permissions

Site permissions extend the existing permission management framework, so that access rights can be defined and enforced per site (or store) not just globally. This lets businesses restrict employee visibility to the specific sites or business units relevant to their roles, while still reusing the central permission management concepts such as roles, scopes, and permission policies.

Site permissions separate responsibilities across multiple sites, markets, or brands and reduce the risk of unauthorized changes. Employees, as business users, benefit from an improved and simpler experience because they only interact with the sites that are relevant to them.

## Example use cases

The functionality is particularly relevant for B2B scenarios, when multiple tenants, customers, or business units are hosted on one platform. However, it can also be valuable in B2C setups with multiple brands, countries, or storefronts where responsibilities need to be clearly separated.

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th align="center"></th><th align="center"></th><th></th><th align="center"></th><th></th></tr></thead><tbody><tr><td align="center"><i class="fa-book-atlas">:book-atlas:</i></td><td align="center"><strong>Regional separation</strong></td><td align="center">A company operates multiple regional sites (for example, DE, FR, US), therefore needs separate access control for different regional sites. Local teams need to manage only their own region. With site-aware permissions, roles can be configured so that the German team only has access to the DE site, the French team only to FR, and the like, while global admins can still see and manage all sites.</td><td></td><td align="center"></td><td></td></tr><tr><td align="center"><i class="fa-building-memo">:building-memo:</i></td><td align="center"><strong>Delegated administration</strong></td><td align="center">A large manufacturer company shares the commerce platform with multiple distributors. They need a single shared infrastructure and centralized product data, but each distributor needs to manage their own orders and customers.</td><td></td><td align="center"></td><td></td></tr></tbody></table>

## Technical overview

Site-aware permissions build on the existing Identity and Access Management framework that enables granting users specific roles, scopes, and policies - and extend it with a site dimension. When an employee logs in or performs actions, their effective permissions are evaluated based on both their role and the current site context. Site-aware entities query these permissions with a specific site identifier to determine which data and actions are available for that employee on that site.

Technically, this is achieved through the `restriction` property added to entities that are restriction-aware, which can either automatically synchronize with site codes (default setup) or be configured independently for advanced requirements. The implementation involves updated API scopes and a revamped management interface that ensures security and operational focus by preventing unauthorised cross-site data access.

### Concepts

Here are some concepts that are crucial for site or restriction-based permissions management.

#### Restriction

The `restriction` property serves as the foundation for access control. By default, restriction serves to limit access to entities that are site-aware, by reading the associated `siteCode`. However, the restrictions can be extended by defining the custom restriction values. This provides the flexibility to handle advanced access scenarios beyond site separation. The restriction-aware entities are companies (legal entities), customers, carts, orders, and quotes.

#### Scope format

When the site permissions or custom restrictions are enabled, the system generates scopes by appending a restriction suffix to the standard permission in the format `{entity}.{action}--{restriction}`.

Examples:

* `order.order_read--DE` - for a single restriction
* `order.order_manage--DE#FR#PL` - for multiple restrictions combined

#### Access control

By defining relevant scopes, you benefit from two distinct tiers of access control, allowing you to balance central governance with granular, site-specific security.

* Global scopes (for example, `order.order_read`) - Represent the traditional, unrestricted access model, regardless of any site or restriction settings. They are designed for high-level administrators who require full visibility across the entire organisation. If a user holds a global scope, the backend service bypasses restriction filtering entirely. This is essential for "global admins" who need to manage all sites without being limited to a specific region.
* Restriction-limited scopes (for example, `order.order_read--DE`) - Introduce the permission model designed to limit a user's access to specific data subsets, such as a single country or brand. They strictly limit access to entities that match the specified restriction values:
  * For `GET` operations - The backend automatically filters data, returning only entities that match the restriction.
  * For `CREATE/UPDATE` operations: The system validates that the target entity belongs to the user's allowed restriction before permitting the change.

Restriction‑scoped permissions also control who can edit existing restrictions. To change a restriction on a restriction-aware entity, an employee must have the relevant manage scope. If the employee’s group includes restriction‑scoped permissions (for example, `quote.quote_manage--DE#FR`), they can create or update restrictions only to the values in their scopes (for example, `DE` or `FR`). They cannot create an entity without a restriction.

### Restrictions handling

To ensure flexibility of how you can handle and enforce relevant permissions, the functionality relies on the following implementation:

* Generic `restriction` property - The property can be added to various entities, such as companies (legal entities), customers, carts, orders, and quotes. It acts as a tag that defines which subset of data an entity belongs to. It typically aligns with a site (for example, a specific storefront site), but it is designed as a generic solution, allowing for broader use cases like regional groupings (for example, `westEU`). By default, it's empty `[]`.
* Configuration modes - Admins can handle restrictions in two distinct modes depending on their business needs with the `enableSyncBetweenRestrictionsAndSiteCodes` setting.

|                                                       **Sync `true`**                                                      |                                                                    **Sync `false`**                                                                    |
| :------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------: |
| The default setup. In this mode, the restriction property automatically synchronizes with the entity's current `siteCode`. | This mode disconnects the restriction from the site code, allowing for custom definitions added in the system preferences (for example, westEU, Asia). |

## Restriction resolution when creating site-aware entities

The `restrictions` and `enableSyncBetweenRestrictionsAndSiteCodes` properties are correlated. When a restriction-aware entity is created, the system determines the entity's `restriction` value using a fixed order of precedence. The following three cases describe how the restriction is resolved.

### Case 1: No restriction in the payload, no customer restriction, sync enabled

**When it applies:** The `enableSyncBetweenRestrictionsAndSiteCodes` is set to `true`, and the request does not include a restriction value. The customer or context creation has no customer-level restriction.

**Behaviour:** The entity's `siteCode` is used as the restriction. The system automatically sets `restriction` to the same value as `siteCode`.

**Example — customer creation**

Request payload:

```json
{
  "firstName": "John",
  "lastName": "Doe",
  "siteCode": "main",
  "restriction": null
}
```

Resulting customer:

```json
{
  "firstName": "John",
  "lastName": "Doe",
  "siteCode": "main",
  "restriction": "main"
}
```

**Workflow**

{% @mermaid/diagram content="---
config:
layout: fixed
theme: base
themeVariables:
primaryColor: '#DDE6EE'
primaryBorderColor: '#4C5359'
actorBkg: '#DDE6EE'
actorBorder: '#4C5359'
actorLineColor: '#4C5359'
signalColor: '#E86C07'
signalTextColor: '#7B8B99'
background: transparent
-----------------------

sequenceDiagram
participant Client
participant API
participant Config as Configuration Service
participant DB

```
Client->>API: Create entity (restriction = null, siteCode = "main")
API->>Config: getEnableSyncBetweenRestrictionsAndSiteCodes()
Config-->>API: true
API->>API: restriction = siteCode ("main")
API->>DB: Save entity (restriction = "main")
DB-->>API: Entity saved" %}
```

### Case 2: Customer restriction present, no restriction in the payload

**When it applies:** The request does not include a restriction value, but the customer already has a restriction assigned (in the Management Dashboard, the customer restriction is visible in the **Preferred Site** or **Restriction** properties). This works independently from the sites and restrictions synchronization setting.

**Behaviour:** The new entity inherits the customer's restriction. For example, if the customer has a `restriction = DE`, a newly created cart or quote also gets the `restriction = DE`.

**Example:** A customer with the `restriction = DE` creates a cart without sending the `restriction` in the payload. The saved cart has the `restriction = DE`.

For custom restrictions setup example, a customer is assigned to a specific regional grouping restriction (for example, `restriction = westEU`) by the API or backend process. When such a customer creates carts or orders, these entities inherit the `restriction = westEU` regardless of which specific storefront (`siteCode`) the customer is browsing.

**Workflow**

{% @mermaid/diagram content="---
config:
layout: fixed
theme: base
themeVariables:
primaryColor: '#DDE6EE'
primaryBorderColor: '#4C5359'
actorBkg: '#DDE6EE'
actorBorder: '#4C5359'
actorLineColor: '#4C5359'
signalColor: '#E86C07'
signalTextColor: '#7B8B99'
background: transparent
-----------------------

sequenceDiagram
participant Client
participant API
participant DB

```
Client->>API: Create cart/quote (restriction = null)
API->>DB: Load customer
DB-->>API: Customer (restriction = "DE")
API->>API: restriction inherited from customer ("DE")
API->>DB: Save entity (restriction = "DE")
DB-->>API: Entity saved" %}
```

### Case 3: Restriction explicitly provided in the payload

**When it applies:** The request payload includes an explicit `restriction` value when creating a restriction-aware entity (such as legal entity, customer, cart, order, or quote).

**Behaviour:** The restriction from the payload takes precedence over other restrictions. It overrides both the customer's restriction and the entity's `siteCode` restrictions. As a prerequisite, the provided value must exist in the restrictions configuration; otherwise the request is rejected.

**Workflow**

{% @mermaid/diagram content="---
config:
layout: fixed
theme: base
themeVariables:
primaryColor: '#DDE6EE'
primaryBorderColor: '#4C5359'
actorBkg: '#DDE6EE'
actorBorder: '#4C5359'
actorLineColor: '#4C5359'
signalColor: '#E86C07'
signalTextColor: '#7B8B99'
background: transparent
-----------------------

sequenceDiagram
participant Client
participant API
participant Config as Configuration Service
participant DB

```
Client->>API: Create entity (restriction = "PL")
API->>Config: Get allowed restrictions
Config-->>API: ["PL", "DE", "FR"]
API->>API: Payload restriction has highest priority
API->>DB: Save entity (restriction = "PL")
DB-->>API: Entity saved" %}
```

## Employee access control

Restrictions applied to entities influence access control for employees. The permissions granted to employees become more granular and context-specific. This process is managed through the Identity and Access Management (IAM) Service and group permissions. Groups include the `restrictions` property that carries the entities visibility for group members. Employees assigned to groups with specific restrictions applied receive restricted scopes to particular entities. For example, an employee belonging to a group with access restriction for DE site and `manage` rights for order entity gets the `order.order_manage--DE` scope, while an employee belonging to a group with defined restrictions for DE and FR sites and `read` permission for order entity gets the `order.order_read--DE#FR` scope.

The scopes defined through restrictions and through specific entity rights on a group level affect what an employee can see and/or manage in the Management Dashboard.

Groups without assigned restrictions maintain full entity visibility.

{% hint style="info" %}
For more information on the employee groups and permissions management, see the [Users and Groups](https://developer.emporix.io/ce/management-dashboard/administration/usersandgroups).
{% endhint %}

### Deployment and migration

{% hint style="warning" %}
If you DO NOT need permissions separation by sites or by another factor, no action is required. The synchronization between sites and restriction is enabled by default, but it doesn't affect employees access unless you explicitly define restrictions on groups.
{% endhint %}

{% hint style="danger" %}
**Data Migration**

The feature does not affect existing data automatically. Migration of the existing data is required. Our [Support Team](mailto:support@emporix.com) can perform migration upon your request.
{% endhint %}

### Enabling site-related restrictions/permissions

To use the **site-based** restrictions to manage access control for your employees, ensure the following:

{% stepper %}
{% step %}

#### Enable sites and restrictions sync

In the Management Dashboard, go to the **Settings** -> **System Preferences** and ensure the `enableSyncBetweenRestrictionsAndSiteCodes` is set to true (the default value). The setting for the list of restrictions populates automatically with the site codes available in your tenant.

<figure><img src="https://3057647601-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbTY7EwZtYYQYC6GOcdTj%2Fuploads%2Fgit-blob-0f0446d23e254a88b9b3efba2a156363dd5f1037%2FenableSiteSync_setting.png?alt=media" alt="Sites and restrictions sync on setting"><figcaption><p>Enable sites and restrictions sync setting</p></figcaption></figure>

<figure><img src="https://3057647601-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbTY7EwZtYYQYC6GOcdTj%2Fuploads%2Fgit-blob-c37801e7a599ca0e55ac402d83e2e48565252904%2Flist_restrictions.png?alt=media" alt="List of site restrictions setting"><figcaption><p>List of restrictions setting</p></figcaption></figure>
{% endstep %}

{% step %}

#### Create dedicated employee groups

Go to the **Administration** -> **Users and Groups** and create appropriate groups with site-specific access to limit access only to site-aware entities with specific site restrictions. Specify the access rights to the relevant site-aware entities (read or manage) and assign employees to the corresponding groups.
{% endstep %}

{% step %}

#### Run data migration

Contact the [Support Team](mailto:support@emporix.com) to run a migration script for the existing data.
{% endstep %}
{% endstepper %}

### Enabling independent custom restrictions

For the cases when you want to apply access control restrictions that do not map one-to-one with technical storefront sites, enable and define custom restrictions. For instance, you want to group multiple countries into a single administrative region (for example, "Western Europe") or to manage permissions based on business divisions rather than storefronts. The process to allow custom permissions is as follows:

{% stepper %}
{% step %}

#### Disable site code synchronization

In the Management Dashboard **System Preferences**, disable the `enableSyncBetweenRestrictionsAndSiteCodes` setting to be able to define custom configuration.

<figure><img src="https://3057647601-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbTY7EwZtYYQYC6GOcdTj%2Fuploads%2Fgit-blob-12690bc6ba14dd7f014da217e86c51bdfd12c7d4%2FsiteSyncOff_setting.png?alt=media" alt="Sites and restrictions sync off setting"><figcaption><p>Sites and restrictions sync off setting</p></figcaption></figure>
{% endstep %}

{% step %}

#### Configure restrictions

Define custom restrictions in the `restrictions` setting in the **System Preferences** (for example, westEU, eastEU, Asia).

<figure><img src="https://3057647601-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbTY7EwZtYYQYC6GOcdTj%2Fuploads%2Fgit-blob-79500b7edec6e3771007baa615703968d5ba6e4c%2Fsetting_restrictionslist.png?alt=media" alt="List of custom restrictions list setting"><figcaption><p>List of custom restrictions list setting</p></figcaption></figure>
{% endstep %}

{% step %}

#### Create employee groups and assign employees

In the **Administration** -> **Users and Groups**, create relevant groups and select the relevant custom restrictions to limit access to the entities that bear the same restriction(s). Assign specific access rights to the selected entities and add relevant employees to these groups.
{% endstep %}

{% step %}

#### Adjust Backend for Frontend (BFF)

It is essential to adjust the API requests in your BFF so that the payloads carry the relevant `restrictions` properties and populate these values to the entities. For example, assign customers to custom restrictions during registration, fetch restrictions during order creation, and more.
{% endstep %}

{% step %}

#### Run data migration

Contact the [Support Team](mailto:support@emporix.com) to run a migration script for existing data.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
For more information on how to handle restrictions on the user groups level, see the [Users and Groups](https://developer.emporix.io/ce/management-dashboard/administration/usersandgroups#create-a-user-group) guide.
{% endhint %}

{% hint style="info" %}
If you're looking for instructions how to handle multiple sites in your tenant, refer to the [Multi-site Architecture](https://app.gitbook.com/s/d4POTWomuSS7d3dnh4Dg/quickstart/multisites).
{% endhint %}
