Try in your browser
The IsolatedSites module is a comprehensive security and access control solution for Omeka S that enforces content isolation based on site permissions. It ensures users can only view and interact with resources (items, item sets, media, assets, and sites) belonging to sites they are explicitly granted access to, significantly enhancing security and usability in multi-site, multi-user environments.
The module achieves this through role-based access control with specialized site-scoped roles (site_researcher, site_editor, site_manager), user-configurable scope limitation settings, and full API integration for programmatic access management. This allows organizations to maintain strict data boundaries between different sites and users while preserving a streamlined administrative experience for site editors and content managers.
-
User Setting Options βοΈ:
- Two flags are added per user:
limit_to_granted_siteslimit_to_own_assets
- These options are available in each user's settings (
Profiles β User Settings):- π Limit to granted sites:
- Items and Item Sets assigned to sites where the logged-in user has no role are filtered out from the admin browse pages.
- In the Admin Dashboard and under the "Sites" navigation menu, only the sites where the user has assigned roles are shown.
- π Limit assets list to my own assets:
- Assets not owned by the logged-in user are hidden from the admin browse page.
- π Limit to granted sites:
- Two flags are added per user:
-
Site-scoped Roles π:
- Three specialized roles for site-scoped work, all isolated to the sites a user is granted on:
site_researcher(inheritsresearcher): read-only access within granted sites.site_editor(inheritseditor): manages content (items, item sets, media) of granted sites, but not the site itself.site_manager(inheritseditor): manages content and the site β pages, title, navigation and theme β of granted sites.
- Because core only exposes item-set site assignment on Sites β Resources (which
site_editorcannot reach), the module adds a Sites tab to the item-set add/edit form so site-scoped roles can still assign their item sets. - Ideal for organizations with multiple sites requiring strict content isolation between teams.
- See the Site-scoped Roles section below for the full permission breakdown.
- Three specialized roles for site-scoped work, all isolated to the sites a user is granted on:
-
Full API Integration π:
- Custom user settings (
limit_to_granted_sites,limit_to_own_assets) are fully accessible via REST and PHP APIs. - Programmatic management of user permissions and scope settings.
- Seamless integration with existing Omeka S API workflows.
- See the API Integration section below for detailed usage examples.
- Custom user settings (
-
Automatic Filtering:
- When enabled, content filtering is automatic without requiring any manual user action.
- Resource queries are filtered at the API level for consistent behavior.
-
Admin Exemption:
- Global administrators retain unrestricted access to all content, regardless of the settings.
- Ensures system administrators can always perform maintenance and troubleshooting.
-
Docker Compose for Easy Testing π³:
- A simple Docker environment is included for fast testing and development.
- Download the latest release from GitHub.
- Extract the ZIP file into your Omeka S
modulesdirectory. - In the Omeka S Admin Panel, navigate to Modules, find IsolatedSites, and click Install.
A docker-compose.yml file is provided:
# Make sure you have Docker and Docker Compose installed
git clone https://github.com/ateeducacion/omeka-s-IsolatedSites.git
cd omeka-s-IsolatedSites
make up-
Wait for the containers to start (this may take a minute).
-
Access Omeka S at http://localhost:8080.
-
Log in as admin (
admin@example.com/PLEASE_CHANGEME).
On first boot the Docker environment provisions a ready-made multi-site scenario
(see data/provision-demo.php) so the isolation can be checked end to end:
| User | Password | Role | Scope | |
|---|---|---|---|---|
| Editor (control) | editor@example.com |
1234 |
editor |
No isolation β sees everything |
| Site Researcher A | siteresearcher.a@example.com |
1234 |
site_researcher |
site-a, read-only |
| Site Editor A | siteeditor.a@example.com |
1234 |
site_editor |
site-a, manages content (not the site) |
| Site Manager A | sitemanager.a@example.com |
1234 |
site_manager |
site-a, content and site/pages |
| Site Editor B | siteeditor.b@example.com |
1234 |
site_editor |
site-b, manages content |
Each site has two items and an item set. The
Impersonate module is also
installed so you can switch into any of these users from the admin user list
(or with ?login_as=<userId>) without juggling passwords. To verify:
- Impersonate Site Editor A β admin Items / Item sets / Sites show only site-a; site-b is hidden. They can add/edit items but the page editor is blocked.
- Impersonate Site Manager A β same isolation, but they can edit site-a's pages, title and navigation.
- Impersonate Site Researcher A β sees site-a content read-only (no add/edit buttons).
- Impersonate Site Editor B β the mirror image (only site-b).
- Editor / admin β everything is visible.
- Confirm the same filtering applies over the REST API, e.g.
GET /api/itemsauthenticated as Site Editor A returns only their items.
Playground: the browser playground provisions the same scenario from
blueprint.json(sites site-a / site-b withsite_researcher/site_editor/site_managerusers, per-site permissions, thelimit_to_granted_sitesuser setting, and the Impersonate module). Open the Try in your browser link and impersonate the demo users above (passwordpasswordin the playground) to compare the three roles. Multi-site blueprints require an up-to-date playground build.
After installing the module:
- (Optional) Go to Admin β Modules β IsolatedSites β Configure. The Enable this option to hide unallowed sites switch is a global kill switch for the read-side filtering. It is on by default; turning it off disables the per-user site/asset filtering for everyone.
- Go to Profiles β User Settings.
- Enable the options:
- Limit to granted sites
- Limit assets list to my own assets
- Save changes.
Depending on the settings enabled, the admin interface will be dynamically filtered to show only the permitted resources.
- Omeka S version 3.x or 4.x
- PHP 7.4 or newer
- Composer (only for building or developing)
- New User Settings: Two flags are added per user:
limit_to_granted_siteslimit_to_own_assets
- Global Toggle: The
activate_IsolatedSitesmodule setting (module Configure page) globally enables or disables the read-sideapi.search.queryfiltering. It is on by default; the per-userlimit_to_granted_sites/limit_to_own_assetsflags still gate behaviour when it is on. - Event Listeners:
- Listeners attached to
api.search.queryevents filter the resources dynamically at query time. - API event listeners handle custom settings in user API operations.
- Listeners attached to
- Resource Filters:
- Items: Filtered based on granted sites.
- Item Sets: Filtered based on granted sites and ownership.
- Assets: Filtered based on ownership.
- Sites: Filtered based on granted site permissions.
- Admin Users: Administrators are exempt from restrictions.
- API Integration: Custom user settings are accessible through both REST API and PHP API.
- No Permission Changes: This module only changes admin UI visibility and adds API access to custom settings, it does not alter underlying Omeka S permission checks.
The custom user settings (limit_to_granted_sites, limit_to_own_assets) are fully integrated with Omeka-S API:
Reading user data (GET /api/users/{id}):
{
"o:id": 1,
"o:name": "John Doe",
"o:email": "john@example.com",
"o:role": "editor",
"o:is_active": true,
"o-module-isolatedsites:limit_to_granted_sites": true,
"o-module-isolatedsites:limit_to_own_assets": false
}Updating user data (PUT /api/users/{id}):
{
"o:name": "Updated Name",
"o-module-isolatedsites:limit_to_granted_sites": false,
"o-module-isolatedsites:limit_to_own_assets": true
}Reading settings (with the service manager in $services and Omeka\ApiManager in $api):
$response = $api->read('users', $id);
$user = $response->getContent();
$userSettingsService = $services->get('Omeka\Settings\User');
$userSettingsService->setTargetId($user->id());
$userSettingsService->get('limit_to_granted_sites', false);
$userSettingsService->get('limit_to_own_assets', false);Updating settings:
$api->update('users', 1, [
'o:name' => 'Updated Name',
'o-module-isolatedsites:limit_to_granted_sites' => true,
'o-module-isolatedsites:limit_to_own_assets' => false,
], [], ['isPartial' => true]);Note: For PHP API calls, custom settings must be accessed via getJsonLd() or helper methods. See API_INTEGRATION_README.md for complete documentation.
This module is released under the GNU General Public License v3.0 (GPL-3.0).
For questions, suggestions, or contributions, please open an Issue or submit a Pull Request.
The module adds three site-scoped roles. All three are isolated to the sites a
user is granted on (via the limit_to_granted_sites setting); they differ only in
what they can write:
| Role | Inherits | Can do | Cannot do |
|---|---|---|---|
site_researcher |
researcher |
Read items, item sets, media and pages of their granted sites | Create or edit any content; edit the site |
site_editor |
editor |
Everything site_researcher can plus create/edit/delete content (items, item sets, media) reachable through a granted site (or owned) |
Edit the site itself β pages, title, navigation, theme |
site_manager |
editor |
Everything site_editor can plus edit the site β pages, title, navigation and theme β of their granted sites |
Create or delete sites; manage a site's user permissions |
In short: site_editor manages content, site_manager also manages the site, and
site_researcher is read-only. None of them can create/delete sites, manage other
users, change resource templates, or see system information β those stay with global
administrators.
| Capability | editor (core) | site_researcher | site_editor | site_manager |
|---|---|---|---|---|
| Read items / item sets / media | All sites | Granted sites only | Granted sites only | Granted sites only |
| Create / edit content | All sites | β | β (granted sites / owned) | β (granted sites / owned) |
| Assign an item set to a site | All sites (Sites > Resources) | β | β (granted sites, item-set Sites tab) | β (granted sites, item-set Sites tab or Sites > Resources) |
| Edit pages, title, navigation, theme | All sites | β | β | β (granted sites) |
| Create / delete sites | β | β | β | β |
| Manage site user permissions | β | β | β | β |
| Resource templates | Full | Read-only | Read-only | Read-only |
| User management | Any user | Own profile only | Own profile only | Own profile only |
Read isolation is enforced by the
api.search.querylisteners + thelimit_to_granted_sitesuser setting (role-independent); write isolation is enforced by the ACL rules above + the per-site access assertion. Page editing forsite_manageris additionally gated by Omeka core's per-site permission.
Core exposes item-set site assignment only on Sites > Resources, which
site_editorcannot reach, so the module adds a Sites tab to the item-set add/edit form. Only the sites you have permissions on are listed, and assignments to any other site are preserved untouched when you save β a Site Editor can never detach an item set from a site they cannot see. New item sets are pre-selected from your Default sites for new items user setting. This tab is independent ofactivate_IsolatedSitesandlimit_to_granted_sites: both govern read-side visibility, while assignment follows from site permissions alone.
The admin UI surfaces a warning whenever a content-managing site role (
site_editor/site_manager) is missing the required isolation settings.
- Assign the role in Admin > Users, then grant the user a permission for each site they should access (Sites > Permissions):
vieweris enough forsite_researcher,editor/adminforsite_editor/site_manager. - Set Default sites for new items in Admin > Users > User settings so new items (and item sets) a content role creates belong to those sites.
- Enable
limit_to_granted_sitesin the same panel to activate the site-based filtering. - Remind users they will only see and manage content linked to their permitted sites; content elsewhere remains hidden.
Run make test-coverage with PCOV or Xdebug enabled. Coverage includes Module.php
and every PHP class in src/, including untested files. The command and CI fail
below 90% line coverage. CI uploads Clover to Codecov with GitHub OIDC; project
and patch targets are both 90%.