Media File Access Rights Setup in 1C-Bitrix
The Bitrix Media Library supports access rights at the collection (folder) level, but not at the individual file level. This means: either the user sees the entire collection or sees nothing. For finer-grained access — for example, "a content editor sees only their own uploads, not files from other departments" — additional configuration is required.
Built-in Media Library Permissions System
Collection permissions are stored in the b_medialib_coll_right table. Structure: COLLECTION_ID, GROUP_ID, PERMISSION. Permission levels:
-
R— read (view files) -
W— write (add files to a collection) -
X— manage (edit, delete)
Permissions are set via the interface: Content → Media Library → [right-click on collection] → Access Rights. Or programmatically:
CMedialib::SetCollectionRights($collectionId, [
['GROUP_ID' => $groupId, 'PERMISSION' => 'W'],
]);
Restricting Access to Physical Files
The problem is that files in /upload/ are accessible directly by URL without authorization — the web server serves them statically, bypassing PHP. To restrict access to files:
- Move restricted files to a directory outside
DocumentRootor to/upload/protected/ - Configure the web server so that requests for protected files go through a PHP handler
For Nginx, a location block is added:
location ~* ^/upload/protected/ {
internal;
alias /var/www/upload/protected/;
}
The PHP script checks user permissions and serves the file via X-Accel-Redirect:
if (!$USER->IsAuthorized() || !checkFileAccess($fileId)) {
header('HTTP/1.0 403 Forbidden');
exit;
}
header('X-Accel-Redirect: /upload/protected/' . $filePath);
header('Content-Type: ' . $mimeType);
File-Level Permissions
For permissions on specific files (not collections), a separate table is created:
CREATE TABLE bl_medialib_file_rights (
file_id INT NOT NULL,
group_id INT NOT NULL,
permission CHAR(1) NOT NULL DEFAULT 'R',
PRIMARY KEY (file_id, group_id)
);
When a protected file is accessed, PHP checks the user's group membership ($USER->IsInGroup($groupId)) and the presence of a record with the required permission level.
Access Segregation for Multiple Departments
A typical setup for a large store with multiple content departments:
| Collection | Group | Rights |
|---|---|---|
| /Catalog/Electronics | Electronics Managers | W (read + write) |
| /Catalog/Clothing | Clothing Managers | W |
| /Marketing/Banners | Marketers | X (full) |
| /Archive | All content managers | R (read-only) |
Groups are created via CGroup::Add(), users are added via CUser::Update() with the GROUP_ID field.
Access Auditing
To track who accessed protected files and when, a log is created in the bl_file_access_log table with fields file_id, user_id, accessed_at, ip, result (allowed/denied). The log is written in the PHP file request handler.
What Is Included in the Setup
- Audit of the current collection structure and existing permissions
- Configuring collection permissions by user groups
- Web server configuration to protect files in
/upload/ - If needed — implementation of file-level permissions
- PHP handler to check permissions and serve files via X-Accel-Redirect
- Configuration of access logs for protected files

