Skip to content

Commit 00b72a4

Browse files
committed
feat: 新增 polkit agent
1 parent a99f654 commit 00b72a4

File tree

22 files changed

+688
-88
lines changed

22 files changed

+688
-88
lines changed

build.zig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,16 @@ pub fn build(b: *std.Build) void {
165165
}) catch @panic("OOM");
166166
exe_options.addOption([]const u8, "buildTime", time);
167167
}
168+
169+
{
170+
const opt_polkit_agent_helper = b.option([]const u8, "polkit-agent-helper", "Override polkit-agent-helper path. Default is `/usr/lib/polkit-1/polkit-agent-helper-1`.");
171+
if (opt_polkit_agent_helper) |polkit_agent_helper| {
172+
exe_options.addOption([]const u8, "polkitAgentHelper", polkit_agent_helper);
173+
} else {
174+
const path = std.process.getEnvVarOwned(b.allocator, "POLKIT_AGENT_HELPER_PATH") catch "/usr/lib/polkit-1/polkit-agent-helper-1";
175+
exe_options.addOption([]const u8, "polkitAgentHelper", path);
176+
}
177+
}
168178
}
169179

170180
b.installArtifact(exe);

example/config.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,15 @@
33
"bongocat": "/example/bongocat.html"
44
},
55
"startup": ["example.bar", "example.dock"],
6-
"services": ["notifd.added:/notify.html"]
6+
"services": [
7+
{
8+
"event": "notifd.added",
9+
"page": "/notify.html"
10+
},
11+
{
12+
"event": "polkitAgent.begin",
13+
"page": "/example/polkitAgent.html",
14+
"single": false
15+
}
16+
]
717
}

example/example/polkitAgent.html

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Polkit Agent Example</title>
5+
<script>
6+
mikaShell.window.init({});
7+
mikaShell.polkitAgent.on("cancel", () => {
8+
mikaShell.window.close();
9+
});
10+
let user = null;
11+
const $ = document.querySelector.bind(document);
12+
const auth = () => {
13+
$("#error").textContent = "Authenticating...";
14+
$("#approve").disabled = true;
15+
if (user === null) {
16+
$("#error").textContent = "User not found.";
17+
$("#approve").disabled = false;
18+
return;
19+
}
20+
const password = $("#password").value;
21+
mikaShell.polkitAgent
22+
.auth(data.cookie, user.name, password)
23+
.then((result) => {
24+
if (result.ok) {
25+
mikaShell.window.close();
26+
} else {
27+
$("#error").textContent = result.err;
28+
}
29+
})
30+
.finally(() => {
31+
$("#approve").disabled = false;
32+
});
33+
};
34+
const cancel = () => {
35+
mikaShell.polkitAgent.cancel(data.cookie);
36+
mikaShell.window.close();
37+
};
38+
</script>
39+
</head>
40+
<body>
41+
<h1>Polkit Agent Example</h1>
42+
<p id="actionId"></p>
43+
<p id="message"></p>
44+
<p>Enter your password to approve the action:</p>
45+
<p>User: <span id="username"></span></p>
46+
<input id="password" type="password" />
47+
<button onclick="cancel()">Cancel</button>
48+
<button id="approve" onclick="auth()">Approve</button>
49+
<br />
50+
<p id="error"></p>
51+
<script>
52+
const data = JSON.parse(new URLSearchParams(window.location.search).get("data"));
53+
console.log(data);
54+
$("#actionId").textContent = data.actionId;
55+
$("#message").textContent = data.message;
56+
for (const identity of data.identities) {
57+
if (identity["unixUser"]) {
58+
mikaShell.os.getUserInfo(identity["unixUser"]).then((u) => {
59+
user = u;
60+
$("#username").textContent = u.name;
61+
});
62+
break;
63+
}
64+
}
65+
</script>
66+
</body>
67+
</html>

nix/devshell.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
webkitgtk_6_0,
99
gtk4-layer-shell,
1010
zlib,
11+
polkit,
1112
glib-networking,
1213
openssl,
1314
devhelp,
@@ -102,5 +103,6 @@ in
102103
TERMINAL = "kitty";
103104
shellHook = ''
104105
export XDG_DATA_DIRS=${docs}:$XDG_DATA_DIRS
106+
export POLKIT_AGENT_HELPER_PATH="$(strings ${polkit.out}/lib/libpolkit-agent-1.so | grep "polkit-agent-helper-1")"
105107
'';
106108
}

nix/package.nix

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
glib-networking,
1010
openssl,
1111
dbus,
12+
polkit,
1213
callPackage,
1314
libwebp,
1415
glib,
@@ -75,6 +76,14 @@ in
7576
libinput
7677
libpng
7778
];
79+
# https://github.com/imvaskel/soteria/blob/1cb43e1049e23f27ff4f2beb6c1f517da0635f53/package.nix#L47
80+
# Takes advantage of nixpkgs manually editing PACKAGE_PREFIX by grabbing it from
81+
# the binary itself.
82+
# https://github.com/NixOS/nixpkgs/blob/9b5328b7f761a7bbdc0e332ac4cf076a3eedb89b/pkgs/development/libraries/polkit/default.nix#L142
83+
# https://github.com/polkit-org/polkit/blob/d89c3604e2a86f4904566896c89e1e6b037a6f50/src/polkitagent/polkitagentsession.c#L599
84+
preBuild = ''
85+
export POLKIT_AGENT_HELPER_PATH="$(strings ${polkit.out}/lib/libpolkit-agent-1.so | grep "polkit-agent-helper-1")"
86+
'';
7887
meta = {
7988
description = "Build your own desktop shell using HTML + CSS + JS";
8089
homepage = "https://github.com/MikaShell/mika-shell";

npm-package/core/events-define.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ export const Workspace = {
4040
"group-workspace-enter": 26,
4141
"group-workspace-leave": 27,
4242
};
43+
export const PolkitAgent = {
44+
begin: 28,
45+
cancel: 29,
46+
};

npm-package/core/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ export const network = globalThis.mikaShell.network;
1313
export const foreignToplevel = globalThis.mikaShell.foreignToplevel;
1414
export const libinput = globalThis.mikaShell.libinput;
1515
export const workspace = globalThis.mikaShell.workspace;
16+
export const polkitAgent = globalThis.mikaShell.polkitAgent;

npm-package/core/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import * as _foreignToplevel from "./foreign-toplevel";
1313
import * as _libinput from "./libinput";
1414
import * as _utils from "./utils";
1515
import * as _workspace from "./workspace";
16+
import * as _polkitAgent from "./polkit-agent";
17+
1618
const core = {
1719
mika: _mika,
1820
tray: _tray,
@@ -29,13 +31,16 @@ const core = {
2931
libinput: _libinput,
3032
workspace: _workspace,
3133
utils: _utils,
34+
polkitAgent: _polkitAgent,
3235
};
36+
3337
declare global {
3438
var mikaShell: typeof core & {
3539
backendPort: number;
3640
id: number;
3741
};
3842
}
43+
3944
export default core;
4045
export * as mika from "./mika";
4146
export * as tray from "./tray";
@@ -52,3 +57,4 @@ export * as foreignToplevel from "./foreign-toplevel";
5257
export * as libinput from "./libinput";
5358
export * as workspace from "./workspace";
5459
export * as utils from "./utils";
60+
export * as polkitAgent from "./polkit-agent";

npm-package/core/os.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ export type ExecOptions = {
3131
export function getSystemInfo(): Promise<SystemInfo> {
3232
return call("os.getSystemInfo");
3333
}
34-
export function getUserInfo(): Promise<UserInfo> {
35-
return call("os.getUserInfo");
34+
export function getUserInfo(uid: number = -1): Promise<UserInfo> {
35+
return call("os.getUserInfo", uid);
3636
}
3737
// 阻塞执行命令,进程退出时返回输出
3838
// 重载签名

npm-package/core/polkit-agent.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import call from "./call";
2+
import { PolkitAgent } from "./events-define";
3+
4+
export type Context = {
5+
actionId: string;
6+
message: string;
7+
iconName: string;
8+
details: any;
9+
cookie: string;
10+
// { unixUser: uid } or { unixGroup: gid }
11+
identities: { [key: string]: number }[];
12+
};
13+
export function auth(
14+
cookie: string,
15+
username: string,
16+
password: string
17+
): Promise<{ ok: boolean; err: string | null }> {
18+
return call("polkitAgent.auth", cookie, username, password);
19+
}
20+
export function cancel(cookie: string): Promise<void> {
21+
return call("polkitAgent.cancel", cookie);
22+
}
23+
type Events = keyof typeof PolkitAgent;
24+
type EventMap = {
25+
[K in Events]: K extends "cancel" ? (cookie: string) => void : never;
26+
};
27+
import * as events from "./events";
28+
export function on<K extends Events>(event: K, callback: (e: EventMap[K]) => void) {
29+
events.on(PolkitAgent[event], callback);
30+
}
31+
export function off<K extends Events>(event: K, callback: (e: EventMap[K]) => void) {
32+
events.off(PolkitAgent[event], callback);
33+
}
34+
export function once<K extends Events>(event: K, callback: (e: EventMap[K]) => void) {
35+
events.once(PolkitAgent[event], callback);
36+
}

0 commit comments

Comments
 (0)