Skip to main content

CnObjectAccessTab

Manage who can reach one object: its visibility scope, and the users, groups, email invitations and public links granted on it. This is the UI for OpenRegister's per-object grant primitive (object-level-sharing-and-private-scope).

Not to be confused with CnSharesTab / CnShareCreate

Three similarly-named things exist, and they are genuinely different:

ComponentShares whatBacked by
CnObjectAccessTab (this)the objecta share on the object's folder
CnSharesTabfiles attached to the objectthe shares integration leaf
CnShareCreateone file inside the object's foldercore IShare on that file

The distinction is enforced server-side, not just by convention: OpenRegister deliberately does not treat a file share as an object grant, so attaching a document to an object and sharing that document never hands over the object's own data.

Two deliberate absences

There is no "can re-share" control. OpenRegister strips core's PERMISSION_SHARE (16) from every object grant. Because a grant is a share on the object's folder, leaving that bit set would let the recipient pass the object on through core's Files UI — producing a perfectly valid object grant created by somebody who was never allowed to create one. A checkbox that is silently cleared would be worse than no checkbox.

Revoking needs no "may take a moment" copy. The grant resolver reads through core's shares at decision time and memoises for a single request only, so the next request already denies.

Read-only mode

A 403 from either endpoint renders the tab read-only rather than as an error. A caller may legitimately be able to see an object without being allowed to manage its sharing — every write endpoint is owner-or-admin — and that is not a failure worth alarming about.

Usage

import { CnObjectAccessTab } from '@conduction/nextcloud-vue'
<CnObjectAccessTab
:object-id="objectUuid"
register="mydash"
schema="dashboard"
@granted="onGranted"
@revoked="onRevoked"
@scope-changed="onScopeChanged" />

As a detail-page tab, register it the same way as any other sidebar tab and pass the object context through.

Props

PropTypeDefaultNotes
objectIdString— (required)Object uuid.
registerString— (required)Register slug or uuid.
schemaString— (required)Schema slug or uuid.
apiBaseString/apps/openregister/apiAPI root.
emptyLabelStringtranslatedEmpty-state text.

Events

EventPayloadWhen
grantedthe created grantafter a successful share
revokedthe removed grantafter a successful revoke
scope-changed'private' | 'organisation'after the scope switch is persisted

Endpoints

All of these are owner-or-admin server-side:

GET    {apiBase}/objects/{register}/{schema}/{id}/scope
PUT {apiBase}/objects/{register}/{schema}/{id}/scope { scope }
GET {apiBase}/objects/{register}/{schema}/{id}/shares
POST {apiBase}/objects/{register}/{schema}/{id}/shares { shareType, shareWith, permissions }
DELETE {apiBase}/objects/{register}/{schema}/{id}/shares/{shareId}
POST {apiBase}/objects/{register}/{schema}/{id}/links { password?, expiration? }
POST {apiBase}/objects/{register}/{schema}/{id}/invitations { email, password?, expiration? }

Requests go through buildHeaders() and prefixUrl() so the CSRF token and the /index.php prefix are handled — a raw fetch would be rejected on every write.