Skip to content

Commit 78a68fb

Browse files
committed
scope/polkit: add service module to write PolKit agents
1 parent 3e32ae5 commit 78a68fb

File tree

9 files changed

+835
-1
lines changed

9 files changed

+835
-1
lines changed

BUILD.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ To disable: `-DSERVICE_PAM=OFF`
192192

193193
Dependencies: `pam`
194194

195+
### Polkit
196+
This feature enables creating Polkit agents that can prompt user for authentication.
197+
198+
To disable: `-DSERVICE_POLKIT=OFF`
199+
200+
Dependencies: `polkit-qt-1`
201+
195202
### Hyprland
196203
This feature enables hyprland specific integrations. It requires wayland support
197204
but has no extra dependencies.

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ boption(SERVICE_STATUS_NOTIFIER "System Tray" ON)
6767
boption(SERVICE_PIPEWIRE "PipeWire" ON)
6868
boption(SERVICE_MPRIS "Mpris" ON)
6969
boption(SERVICE_PAM "Pam" ON)
70+
boption(SERVICE_POLKIT "Polkit" ON)
7071
boption(SERVICE_GREETD "Greetd" ON)
7172
boption(SERVICE_UPOWER "UPower" ON)
7273
boption(SERVICE_NOTIFICATIONS "Notifications" ON)

default.nix

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
ninja,
1111
spirv-tools,
1212
qt6,
13+
kdePackages,
1314
breakpad,
1415
jemalloc,
1516
cli11,
@@ -43,6 +44,7 @@
4344
withPam ? true,
4445
withHyprland ? true,
4546
withI3 ? true,
47+
withPolkit ? true,
4648
}: let
4749
unwrapped = stdenv.mkDerivation {
4850
pname = "quickshell${lib.optionalString debug "-debug"}";
@@ -76,7 +78,8 @@
7678
++ lib.optionals (withWayland && libgbm != null) [ libdrm libgbm ]
7779
++ lib.optional withX11 xorg.libxcb
7880
++ lib.optional withPam pam
79-
++ lib.optional withPipewire pipewire;
81+
++ lib.optional withPipewire pipewire
82+
++ lib.optional withPolkit kdePackages.polkit-qt-1;
8083

8184
cmakeBuildType = if debug then "Debug" else "RelWithDebInfo";
8285

@@ -91,6 +94,7 @@
9194
(lib.cmakeBool "SCREENCOPY" (libgbm != null))
9295
(lib.cmakeBool "SERVICE_PIPEWIRE" withPipewire)
9396
(lib.cmakeBool "SERVICE_PAM" withPam)
97+
(lib.cmakeBool "SERVICE_POLKIT" withPolkit)
9498
(lib.cmakeBool "HYPRLAND" withHyprland)
9599
(lib.cmakeBool "I3" withI3)
96100
];

quickshell.scm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
libxcb
4343
libxkbcommon
4444
linux-pam
45+
polkit-qt
4546
mesa
4647
pipewire
4748
qtbase

src/services/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ if (SERVICE_PAM)
1414
add_subdirectory(pam)
1515
endif()
1616

17+
if (SERVICE_POLKIT)
18+
add_subdirectory(polkit)
19+
endif()
20+
1721
if (SERVICE_GREETD)
1822
add_subdirectory(greetd)
1923
endif()

src/services/polkit/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
find_package(PkgConfig REQUIRED)
2+
pkg_check_modules(polkit REQUIRED IMPORTED_TARGET polkit-qt6-core-1 polkit-qt6-agent-1)
3+
4+
qt_add_library(quickshell-service-polkit STATIC
5+
qml.cpp
6+
)
7+
8+
qt_add_qml_module(quickshell-service-polkit
9+
URI Quickshell.Services.Polkit
10+
VERSION 0.1
11+
DEPENDENCIES QtQml
12+
)
13+
14+
install_qml_module(quickshell-service-polkit)
15+
16+
target_link_libraries(quickshell-service-polkit PRIVATE
17+
Qt::Qml PkgConfig::polkit
18+
Qt::Quick # pch
19+
)
20+
21+
qs_module_pch(quickshell-service-polkit)
22+
23+
target_link_libraries(quickshell PRIVATE quickshell-service-polkitplugin)

src/services/polkit/module.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name = "Quickshell.Services.Polkit"
2+
description = "Polkit API"
3+
headers = [qml.hpp]
4+
-----
5+
6+
## Purpose of a Polkit Agent
7+
8+
PolKit is a system for privileged applications to query if a user is permitted to execute an action.
9+
You have probably seen it in the form of a "Please enter your password to continue with X" dialog box before.
10+
This dialog box is presented by your *PolKit agent*, it is a process running as your user that accepts authentication requests from the *daemon* and presents them to you to accept or deny.
11+
12+
This service enables writing a PolKit agent in Quickshell.
13+
14+
## Implementing a Polkit Agent
15+
16+
The backend logic of communicating with the daemon is handled by the @@PolkitAgent object.
17+
It exposes incoming requests as properties and provides appropriate signals.
18+
19+
### Flow of an authentication request
20+
21+
Incoming authentication requests are queued in the order that they arrive.
22+
If none is queued, a request starts processing right away.
23+
Otherwise, it will wait until prior requests are done.
24+
25+
A request starts by emitting the @@PolkitAgent.authenticationRequestStarted signal.
26+
At this point, information like the action to be performed and permitted users that can authenticate is available.
27+
28+
An authentication *session* for the request is immediately started, which internally starts a PAM conversation that is likely to prompt for user input.
29+
* Additional prompts may be shared with the user by way of the @@PolkitAgent.subMessageChanged signal and the @@PolkitAgent.subMessage property. A common message might be 'Please input your password'.
30+
* An input request is forwarded via the @@PolkitAgent.inputRequestChanged signal and @@PolkitAgent.inputRequest property. Note that the request specifies whether the text box should show the typed input on screen or replace it with placeholders.
31+
32+
User replies can be submitted via the @@PolkitAgent.submit method.
33+
A conversation can take multiple turns, for example if second factors are involved.
34+
35+
If authentication fails, we automatically create a fresh session so the user can try again.
36+
The @@PolkitAgent.authenticationFailed signal is emitted in this case.
37+
38+
If authentication is successful, you receive the @@PolkitAgent.authenticationSucceeeded signal. At this point, the dialog can be closed.
39+
If additional requests are queued, you will receive the @@PolkitAgent.authenticationRequestStarted signal again.
40+
41+
#### Cancelled requests
42+
43+
Requests may either be canceled by the user or the PolKit daemon.
44+
In this case, we clean up any state and proceed to the next request, if any.
45+
46+
If the request was cancelled by the daemon and not the user, you also receive the @@PolkitAgent.authenticationRequestCancelled signal.
47+
48+
## Limitations
49+
50+
- If multiple authentication requests are queued, we cannot determine which one is canceled (if one is canceled)

0 commit comments

Comments
 (0)