From 1ead5dc14aaece51bf4017ed5053522ba8e11beb Mon Sep 17 00:00:00 2001 From: trevor-signal <131492920+trevor-signal@users.noreply.github.com> Date: Mon, 23 Mar 2026 15:34:27 -0400 Subject: [PATCH] Handle unregistered actions when prompting for OS auth --- ts/util/os/promptOSAuthMain.main.ts | 57 ++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/ts/util/os/promptOSAuthMain.main.ts b/ts/util/os/promptOSAuthMain.main.ts index 382dfc7ebc..7365c93479 100644 --- a/ts/util/os/promptOSAuthMain.main.ts +++ b/ts/util/os/promptOSAuthMain.main.ts @@ -11,6 +11,7 @@ import { import { createLogger } from '../../logging/log.std.js'; import OS from './osMain.node.js'; import { missingCaseError } from '../missingCaseError.std.js'; +import { toLogFormat } from '../../types/errors.std.js'; const log = createLogger('promptOSAuthMain'); @@ -92,9 +93,17 @@ async function promptOSAuthWindows( async function promptOSAuthLinux( reason: PromptOSAuthReasonType ): Promise { - const isAvailable = await isPromptOSAuthAvailableLinux(); - if (!isAvailable) { - return 'unsupported'; + try { + const isAvailable = await isPromptOSAuthAvailableLinux(reason); + if (!isAvailable) { + return 'unsupported'; + } + } catch (e) { + log.error( + 'promptOSAuthLinux: error when checking for os auth availability', + toLogFormat(e) + ); + return 'error'; } // Avoid string interpolation in exec() command @@ -125,10 +134,48 @@ async function promptOSAuthLinux( }); } -async function isPromptOSAuthAvailableLinux(): Promise { - return new Promise((resolve, _reject) => { +async function isPromptOSAuthAvailableLinux( + reason: PromptOSAuthReasonType +): Promise { + const isPkCheckInstalled = await new Promise((resolve, _reject) => { exec('command -v pkcheck').on('exit', code => { resolve(code === 0); }); }); + if (!isPkCheckInstalled) { + log.warn('isPromptOsAuthAvailable: pkcheck not installed'); + return false; + } + + // Avoid string interpolation in exec() command + let actionCommand: string; + if (reason === 'enable-backups') { + actionCommand = 'pkaction --action-id org.signalapp.enable-backups'; + } else if (reason === 'view-aep') { + actionCommand = 'pkaction --action-id org.signalapp.view-aep'; + } else if (reason === 'plaintext-export') { + actionCommand = 'pkaction --action-id org.signalapp.plaintext-export'; + } else { + throw missingCaseError(reason); + } + + const isActionRegistered = await new Promise((resolve, _reject) => { + exec(actionCommand).on('exit', code => { + resolve(code === 0); + }); + }); + + if (!isActionRegistered) { + if (OS.isAppImage()) { + log.warn( + 'isPromptOsAuthAvailable: action not registered due to AppImage' + ); + } else { + throw new Error( + `isPromptOsAuthAvailable: ${reason} action not registered` + ); + } + } + + return isActionRegistered; }