Permissions API

This page documents the Lua API for managing PipeWire client permissions: the Perm constants that name the permission flags, and the PermissionManager object that computes and maintains per-object permissions for clients.

For the architecture these APIs are part of, see Client Access Control. For the configuration file equivalents, see Access configuration.

Constants

Perm

PipeWire client permission flags:

Constant

Meaning

Perm.NONE

no permissions

Perm.R

read: the object is visible to the client

Perm.W

write: the client may modify the object

Perm.X

execute: the client may call methods on it

Perm.M

metadata: the client may set metadata on it

Perm.L

link: the client may link to it

The combinations Perm.RW, Perm.RX, Perm.WX, Perm.RWX, Perm.RWXM, Perm.RWXML and Perm.ALL are also provided. Note that Perm.ALL is RWXM and does not include L.

See The permission model for what each flag actually allows.

Permission Manager

The PermissionManager object manages per-object permissions for clients. It is created with the global PermissionManager() constructor and configured with default permissions, core permissions, and match rules. It must be activated with Features.ALL before it can be attached to a client with Client.attach_permission_manager(); see Permission managers for how the permission list is computed and when it is refreshed.

PermissionManager()

Creates a new permission manager. Its default permissions start out as Perm.RWX.

Returns:

a new permission manager

Return type:

WpPermissionManager

PermissionManager.set_default_permissions(self, perms)

Binds wp_permission_manager_set_default_permissions()

Sets the default permissions applied to all objects that don't match any rule.

Parameters:
  • self -- the permission manager

  • perms -- a permission string (e.g. "rx") or an integer bitmask (e.g. Perm.RX)

PermissionManager.get_default_permissions(self)

Binds wp_permission_manager_get_default_permissions()

Returns the default permissions as an integer bitmask. This can be compared against the Perm constants using bitwise operators.

Example:

local pm = client:get_permission_manager()
local perms = pm:get_default_permissions()
if (perms & Perm.RX) == Perm.RX then
  -- client has at least read + execute
end
Parameters:

self -- the permission manager

Returns:

the default permissions bitmask

Return type:

integer

PermissionManager.set_core_permissions(self, perms)

Binds wp_permission_manager_set_core_permissions()

Sets the permissions applied specifically to the PipeWire core object (ID 0). If not set, the core inherits the default permissions.

Parameters:
  • self -- the permission manager

  • perms -- a permission string or an integer bitmask

PermissionManager.add_rules_match(self, rules)

Binds wp_permission_manager_add_rules_match()

Adds a set of match rules that grant specific permissions to objects matching the given constraints. The rules use the standard matches/actions form, with a set-permissions action whose value is a permission string.

Parameters:
  • self -- the permission manager

  • rules (WpSpaJson) -- a JSON array of match rules

Returns:

the match id (can be used with remove_match)

Return type:

integer

PermissionManager.add_interest_match(self, callback, interest)

Binds wp_permission_manager_add_interest_match_closure()

Adds a dynamic match that calls the given callback to determine permissions for objects matching the given interest. The callback is called with the permission manager, the client whose permissions are being computed, and the matched object, and must return a permission bitmask.

Example:

pm:add_interest_match (
  function (_, client, object)
    return client:get_property ("my.sandbox.id") ==
           object:get_property ("my.sandbox.id") and Perm.ALL or Perm.NONE
  end,
  Interest {
    type = "node",
    Constraint { "media.class", "=", "Audio/Sink" },
  }
)
Parameters:
  • self -- the permission manager

  • callback (function) -- a function that returns the permissions for the matched object

  • interest (WpObjectInterest) -- the interest to match

Returns:

the match id

Return type:

integer

PermissionManager.add_interest_match_simple(self, perms, interest)

Binds wp_permission_manager_add_interest_match_simple()

Adds a static match that grants the given permissions to objects matching the given interest.

Parameters:
  • self -- the permission manager

  • perms (integer) -- the permissions bitmask to grant

  • interest (WpObjectInterest) -- the interest to match

Returns:

the match id

Return type:

integer

PermissionManager.remove_match(self, match_id)

Binds wp_permission_manager_remove_match()

Removes a previously added match.

Parameters:
  • self -- the permission manager

  • match_id (integer) -- the match id returned by an add_*_match method

PermissionManager.update_permissions(self)

Binds wp_permission_manager_update_permissions()

Forces a recalculation and update of permissions on all attached clients. This is needed when a decision made by an add_interest_match callback depends on external state that has changed, since the permission manager only recomputes automatically when objects are added to or removed from the graph.

Parameters:

self -- the permission manager

Signals

client-properties-changed

Emitted when the properties of an attached client change. The callback receives the permission manager and the client.

Example:

pm:connect ("client-properties-changed", function (pm, client)
  if client:get_property ("my.gated") == "true" then
    client:update_permissions { [0] = "rwx" }
  end
end)

Introspecting a client's permissions

Scripts that need to know how much a client is trusted before acting on its behalf can retrieve the permission manager attached to it with Client.get_permission_manager():

local client_om = ObjectManager { Interest { type = "client" } }
client_om:activate()

-- Check if a client has at least read + execute permissions
local pm = client:get_permission_manager()
if pm then
  local perms = pm:get_default_permissions()
  if (perms & Perm.RX) == Perm.RX then
    -- Client has sufficient permissions
  end
end

Note that this returns nil for clients whose permissions were set directly instead of through a permission manager, i.e. those matched by an access.rules entry that sets default_permissions.