Shared Asset Locations Developer Guide - edmozley/freeitsm GitHub Wiki
Shared asset locations - developer guide
User-facing page: Shared asset locations.
Locations were scoped as data, not config, on purpose: the Multi-Tenancy Developer Guide used them as the example of a tree with no shared defaults. A customer asked for locations shared across companies, and Ed chose "shared + own". So this is an exception to that rule, not a reversal of it: every company still owns its own tree.
The column, and why the row has no company
asset_locations.is_shared TINYINT(1) NOT NULL DEFAULT 0 (in database/freeitsm.sql and includes/db_verify_schema.php).
A shared row is stored with tenant_id NULL. A company-owned shared location would disappear from every client the day its owner was deleted, because fk_asset_locations_tenant cascades. It also matches what already existed: the REST API and the CSV importer resolve locations as "global + this company's", and treat NULL as global.
One home: includes/asset_locations.php
| Function | Does |
|---|---|
assetLocationsSharedReady() |
Does the column exist yet? Every guard checks it first. |
assetLocationScope($conn, $tenantId, $alias) |
The locations one company sees: tenantScopeSqlFor() OR is_shared = 1, in one bracket. |
assetLocationIsShared() |
For the rules below. |
tenantScopeSqlFor() and analystHasAllTenantAccess() live in includes/tenancy.php. The latter compares the analyst's reachable companies with the real tenant list, because access can also come through teams.
The rules, enforced in the endpoints
get_asset_locations.phpusesassetLocationScope()and returnsis_sharedper row pluscan_share, which Settings uses to show the tick. The settings tree and every picker build from this one endpoint, so scoping it scopes them all.save_asset_location.php:- only
analystHasAllTenantAccess()may setis_sharedor edit a shared row, from any company context; - a shared location's parent must be shared, or another company's tree would show an orphan;
- unsharing is refused while another company's assets use it, or they would point at a location their company cannot see; and refused while shared children sit inside it;
- the parent check uses
assetLocationScope(), so a company can nest its own location inside a shared one.
- only
delete_asset_location.php: shared rows need all-company access.
⚠️ The Settings form sends is_shared on every save, so it is pre-set when editing. Leaving it unticked on a shared location would unshare it on an unrelated rename.
🔴 Before Database Verification
The column does not exist until Database Verification runs, and the asset screens must keep working on an install that has pulled the update but not run it. Every read selects 0 AS is_shared when the column is absent, and sharing is simply unavailable (can_share false). This was tested with the column absent before it was added.
Verified
On a real database with throwaway rows (all removed): a company saw its own locations plus the shared one and not Default's private one; a shared child under a private parent was refused; unsharing with two other-company assets in place was refused with the count; and Settings showed the badge and pre-set the tick. The column was added through the real Database Verification, whose preview showed 1 add, 0 drops, 0 repairs.