Skip to content

Shared Asset Locations Developer Guide

Ed Mozley edited this page Sep 24, 2026 · 1 revision

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.php uses assetLocationScope() and returns is_shared per row plus can_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 set is_shared or 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.
  • 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.


See also

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally