123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- MEDIA_ROLE_NONE = 0
- MEDIA_ROLE_CAMERA = 1 << 0
- function hasPermission (permissions, app_id, lookup)
- if permissions then
- for key, values in pairs(permissions) do
- if key == app_id then
- for _, v in pairs(values) do
- if v == lookup then
- return true
- end
- end
- end
- end
- end
- return false
- end
- function parseMediaRoles (media_roles_str)
- local media_roles = MEDIA_ROLE_NONE
- for role in media_roles_str:gmatch('[^,%s]+') do
- if role == "Camera" then
- media_roles = media_roles | MEDIA_ROLE_CAMERA
- end
- end
- return media_roles
- end
- function setPermissions (client, allow_client, allow_nodes)
- local client_id = client["bound-id"]
- Log.info(client, "Granting ALL access to client " .. client_id)
- -- Update permissions on client
- client:update_permissions { [client_id] = allow_client and "all" or "-" }
- -- Update permissions on camera source nodes
- for node in nodes_om:iterate() do
- local node_id = node["bound-id"]
- client:update_permissions { [node_id] = allow_nodes and "all" or "-" }
- end
- end
- function updateClientPermissions (client, permissions)
- local client_id = client["bound-id"]
- local str_prop = nil
- local app_id = nil
- local media_roles = nil
- local allowed = false
- -- Make sure the client is not the portal itself
- str_prop = client.properties["pipewire.access.portal.is_portal"]
- if str_prop == "yes" then
- Log.info (client, "client is the portal itself")
- return
- end
- -- Make sure the client has a portal app Id
- str_prop = client.properties["pipewire.access.portal.app_id"]
- if str_prop == nil then
- Log.info (client, "Portal managed client did not set app_id")
- return
- end
- if str_prop == "" then
- Log.info (client, "Ignoring portal check for non-sandboxed client")
- setPermissions (client, true, true)
- return
- end
- app_id = str_prop
- -- Make sure the client has portal media roles
- str_prop = client.properties["pipewire.access.portal.media_roles"]
- if str_prop == nil then
- Log.info (client, "Portal managed client did not set media_roles")
- return
- end
- media_roles = parseMediaRoles (str_prop)
- if (media_roles & MEDIA_ROLE_CAMERA) == 0 then
- Log.info (client, "Ignoring portal check for clients without camera role")
- return
- end
- -- Update permissions
- allowed = hasPermission (permissions, app_id, "yes")
- Log.info (client, "setting permissions: " .. tostring(allowed))
- setPermissions (client, allowed, allowed)
- end
- -- Create portal clients object manager
- clients_om = ObjectManager {
- Interest {
- type = "client",
- Constraint { "pipewire.access", "=", "portal" },
- }
- }
- -- Set permissions to portal clients from the permission store if loaded
- pps_plugin = Plugin.find("portal-permissionstore")
- if pps_plugin then
- nodes_om = ObjectManager {
- Interest {
- type = "node",
- Constraint { "media.role", "=", "Camera" },
- Constraint { "media.class", "=", "Video/Source" },
- }
- }
- nodes_om:activate()
- clients_om:connect("object-added", function (om, client)
- local new_perms = pps_plugin:call("lookup", "devices", "camera");
- updateClientPermissions (client, new_perms)
- end)
- nodes_om:connect("object-added", function (om, node)
- local new_perms = pps_plugin:call("lookup", "devices", "camera");
- for client in clients_om:iterate() do
- updateClientPermissions (client, new_perms)
- end
- end)
- pps_plugin:connect("changed", function (p, table, id, deleted, permissions)
- if table == "devices" or id == "camera" then
- for app_id, _ in pairs(permissions) do
- for client in clients_om:iterate {
- Constraint { "pipewire.access.portal.app_id", "=", app_id }
- } do
- updateClientPermissions (client, permissions)
- end
- end
- end
- end)
- else
- -- Otherwise, just set all permissions to all portal clients
- clients_om:connect("object-added", function (om, client)
- local id = client["bound-id"]
- Log.info(client, "Granting ALL access to client " .. id)
- client:update_permissions { ["any"] = "all" }
- end)
- end
- clients_om:activate()
|