@localauth/cli 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/ask.ts +2 -2
- package/cli/cli.ts +1 -0
- package/package.json +1 -1
- package/shared/ask.ts +4 -2
- package/shared/validation.ts +2 -2
package/cli/ask.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process'
|
|
2
2
|
import * as fs from 'node:fs/promises'
|
|
3
3
|
import * as path from 'node:path'
|
|
4
|
-
import { answerFields, isAskRequest, isFieldName, isReservedName } from '../shared/ask.ts'
|
|
4
|
+
import { answerFields, isAskRequest, isFieldName, isReservedName, MAX_APPROVAL_DESCRIPTION } from '../shared/ask.ts'
|
|
5
5
|
import { setTimeout as sleep } from 'node:timers/promises'
|
|
6
6
|
import type { AnswerData, AskRequest, RunData } from '../shared/protocol.ts'
|
|
7
7
|
import { isAnswer } from '../shared/validation.ts'
|
|
@@ -184,7 +184,7 @@ export async function approve(connection: Connection, options: ApproveOptions, s
|
|
|
184
184
|
let expiresAt = Date.now() + Math.ceil(options.timeout * 60_000)
|
|
185
185
|
let request: AskRequest = { title: options.title, description: options.description, fields: [{ name: 'APPROVE', label: 'Approve', secret: false, required: true }] }
|
|
186
186
|
let data: RunData = { authenticatedMessages: true, kind: 'ask', approval: true, title: options.title, ask: request, expiresAt, command: '', flows: [], output: '', exitCode: null, attempt: 1, retryUntil: null }
|
|
187
|
-
if (!isAskRequest(data.ask)) throw new Error('Invalid approval request.')
|
|
187
|
+
if (!isAskRequest(data.ask, MAX_APPROVAL_DESCRIPTION)) throw new Error('Invalid approval request.')
|
|
188
188
|
let run = await createRun(connection, [], say, { retry: false, link: false }, data)
|
|
189
189
|
let stop = new AbortController(), interrupted = 0
|
|
190
190
|
let listeners = Object.entries({ SIGINT: 130, SIGTERM: 143, SIGHUP: 129 }).map(([signal, code]) => {
|
package/cli/cli.ts
CHANGED
|
@@ -35,6 +35,7 @@ Usage:
|
|
|
35
35
|
localauth approve --title <text> [--description <text>] [--timeout <minutes>]
|
|
36
36
|
Wait for the owner to allow something. They answer from their
|
|
37
37
|
signed-in list with a fresh passkey check; no link is made
|
|
38
|
+
Description: max 8000
|
|
38
39
|
Needs end-to-end encryption; exits 0 if approved, 1 otherwise
|
|
39
40
|
localauth finish [<callback-url>] Hand a pasted http://localhost:... address to the waiting command
|
|
40
41
|
(reads it from stdin when omitted, keeping it out of ps)
|
package/package.json
CHANGED
package/shared/ask.ts
CHANGED
|
@@ -10,10 +10,12 @@ export function isFieldName(name: unknown): name is string {
|
|
|
10
10
|
function object(value: unknown): value is Record<string, unknown> {
|
|
11
11
|
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
/** An approval may have to show everything being approved, such as a whole diff. */
|
|
14
|
+
export const MAX_APPROVAL_DESCRIPTION = 8000
|
|
15
|
+
export function isAskRequest(value: unknown, maxDescription = 2000): value is AskRequest {
|
|
14
16
|
if (!object(value)
|
|
15
17
|
|| (value.title !== undefined && (typeof value.title !== 'string' || !value.title.length || value.title.length > 120))
|
|
16
|
-
|| (value.description !== undefined && (typeof value.description !== 'string' || value.description.length >
|
|
18
|
+
|| (value.description !== undefined && (typeof value.description !== 'string' || value.description.length > maxDescription))
|
|
17
19
|
|| !Array.isArray(value.fields) || value.fields.length < 1 || value.fields.length > 10) return false
|
|
18
20
|
let names = new Set<string>()
|
|
19
21
|
return value.fields.every(field => {
|
package/shared/validation.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { InputData, CallbackData, RunData } from './protocol.ts'
|
|
2
|
-
import { isAskRequest } from './ask.ts'
|
|
2
|
+
import { isAskRequest, MAX_APPROVAL_DESCRIPTION } from './ask.ts'
|
|
3
3
|
export { isAnswer } from './ask.ts'
|
|
4
4
|
export function isCallback(value: unknown): value is CallbackData {
|
|
5
5
|
let v = value as CallbackData | null
|
|
@@ -13,7 +13,7 @@ export function isRunData(value: unknown): value is RunData {
|
|
|
13
13
|
&& (v.approval === undefined || (v.approval === true && v.kind === 'ask'))
|
|
14
14
|
&& (v.inputEnabled === undefined || typeof v.inputEnabled === 'boolean')
|
|
15
15
|
&& (v.secret === undefined || typeof v.secret === 'boolean')
|
|
16
|
-
&& (v.ask === undefined || (v.kind === 'ask' && isAskRequest(v.ask)))
|
|
16
|
+
&& (v.ask === undefined || (v.kind === 'ask' && isAskRequest(v.ask, v.approval ? MAX_APPROVAL_DESCRIPTION : undefined)))
|
|
17
17
|
&& (v.answerNote === undefined || (typeof v.answerNote === 'string' && v.answerNote.length <= 240))
|
|
18
18
|
&& (v.expiresAt === undefined || (Number.isSafeInteger(v.expiresAt) && v.expiresAt >= 0))
|
|
19
19
|
&& (v.machineName === undefined || (typeof v.machineName === 'string' && v.machineName.length <= 253))
|