[client] Authorize daemon IPC callers by their local identity (#6967)

This commit is contained in:
Viktor Liu
2026-07-29 20:32:26 +02:00
committed by GitHub
parent 0b7e6a9f46
commit 0f5d2d91fb
58 changed files with 3799 additions and 167 deletions
+20 -7
View File
@@ -1,6 +1,6 @@
import { WindowManager } from "@bindings/services";
type ClassifiedError = { short: string; long: string };
type ClassifiedError = { short: string; long: string; command: string };
const asObject = (v: unknown): Record<string, unknown> | null =>
v && typeof v === "object" ? (v as Record<string, unknown>) : null;
@@ -22,20 +22,24 @@ const toWailsEnvelope = (e: unknown): Record<string, unknown> | null => {
return asObject(obj.cause) ?? parseJsonObject(obj.message);
};
// Read { short, long } from wherever the classified error sits in the envelope
// Read { short, long, command } from wherever the classified error sits in the envelope
const toClassifiedError = (v: unknown): ClassifiedError | null => {
const o = asObject(v);
if (!o) return null;
const short = typeof o.short === "string" ? o.short : "";
const long = typeof o.long === "string" ? o.long : "";
return short || long ? { short, long } : null;
const command = typeof o.command === "string" ? o.command : "";
return short || long ? { short, long, command } : null;
};
const classify = (e: unknown): ClassifiedError | null => {
const envelope = toWailsEnvelope(e);
return toClassifiedError(envelope?.cause) ?? toClassifiedError(envelope);
};
export const formatErrorMessage = (e: unknown): string => {
const envelope = toWailsEnvelope(e);
// Prefer the structured { short, long } the daemon classifier produced.
const classified = toClassifiedError(envelope?.cause) ?? toClassifiedError(envelope);
const classified = classify(e);
if (classified) {
const { short, long } = classified;
if (short && long && long !== short) return `${short} Details: ${long}`;
@@ -44,17 +48,26 @@ export const formatErrorMessage = (e: unknown): string => {
}
// Unclassified (a service returned the raw daemon error)
const envelope = toWailsEnvelope(e);
const message = envelope?.message;
if (typeof message === "string" && message) return message;
if (e instanceof Error) return e.message;
return String(e);
};
// errorCommand returns a command the user can run to complete an operation the
// daemon refused, when the error carries one (a change that needs elevated
// privileges). Empty for every other error.
export const errorCommand = (e: unknown): string => classify(e)?.command ?? "";
export type ErrorDialogOptions = {
Title: string;
Message: string;
// Command is shown for copying below the message. Defaults to the one the
// error carries, so callers only pass it to override.
Command?: string;
};
export function errorDialog(options: ErrorDialogOptions): Promise<void> {
return WindowManager.OpenError(options.Title, options.Message);
return WindowManager.OpenError(options.Title, options.Message, options.Command ?? "");
}