latchkey 3.8.0 → 3.9.0
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/dist/scripts/recordBrowserSession.js +4 -3
- package/dist/scripts/recordBrowserSession.js.map +1 -1
- package/dist/src/apiCredentials/base.d.ts +7 -1
- package/dist/src/apiCredentials/base.d.ts.map +1 -1
- package/dist/src/apiCredentials/base.js.map +1 -1
- package/dist/src/apiCredentials/store.d.ts +5 -0
- package/dist/src/apiCredentials/store.d.ts.map +1 -1
- package/dist/src/apiCredentials/store.js +7 -0
- package/dist/src/apiCredentials/store.js.map +1 -1
- package/dist/src/atomicWrite.d.ts +4 -1
- package/dist/src/atomicWrite.d.ts.map +1 -1
- package/dist/src/atomicWrite.js +34 -3
- package/dist/src/atomicWrite.js.map +1 -1
- package/dist/src/cli.js +0 -3
- package/dist/src/cli.js.map +1 -1
- package/dist/src/cliCommands.d.ts +8 -0
- package/dist/src/cliCommands.d.ts.map +1 -1
- package/dist/src/cliCommands.js +88 -13
- package/dist/src/cliCommands.js.map +1 -1
- package/dist/src/curl.d.ts +36 -0
- package/dist/src/curl.d.ts.map +1 -1
- package/dist/src/curl.js +42 -0
- package/dist/src/curl.js.map +1 -1
- package/dist/src/curlInjection.d.ts +5 -4
- package/dist/src/curlInjection.d.ts.map +1 -1
- package/dist/src/curlInjection.js +8 -7
- package/dist/src/curlInjection.js.map +1 -1
- package/dist/src/gateway/gatewayEndpoint.d.ts.map +1 -1
- package/dist/src/gateway/gatewayEndpoint.js +6 -3
- package/dist/src/gateway/gatewayEndpoint.js.map +1 -1
- package/dist/src/gateway/server.d.ts.map +1 -1
- package/dist/src/gateway/server.js +14 -3
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/migrations.d.ts +6 -0
- package/dist/src/migrations.d.ts.map +1 -1
- package/dist/src/migrations.js +21 -8
- package/dist/src/migrations.js.map +1 -1
- package/dist/src/serviceRegistry.d.ts +14 -1
- package/dist/src/serviceRegistry.d.ts.map +1 -1
- package/dist/src/serviceRegistry.js +22 -2
- package/dist/src/serviceRegistry.js.map +1 -1
- package/dist/src/services/aws.d.ts +11 -2
- package/dist/src/services/aws.d.ts.map +1 -1
- package/dist/src/services/aws.js +72 -5
- package/dist/src/services/aws.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/tests/apiCredentialStore.test.js +8 -0
- package/dist/tests/apiCredentialStore.test.js.map +1 -1
- package/dist/tests/apiCredentials.test.js +84 -1
- package/dist/tests/apiCredentials.test.js.map +1 -1
- package/dist/tests/atomicWrite.test.js +42 -1
- package/dist/tests/atomicWrite.test.js.map +1 -1
- package/dist/tests/builtinServiceRegistry.d.ts +10 -0
- package/dist/tests/builtinServiceRegistry.d.ts.map +1 -0
- package/dist/tests/builtinServiceRegistry.js +10 -0
- package/dist/tests/builtinServiceRegistry.js.map +1 -0
- package/dist/tests/cli.test.js +155 -7
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/devShim.test.d.ts +2 -0
- package/dist/tests/devShim.test.d.ts.map +1 -0
- package/dist/tests/devShim.test.js +240 -0
- package/dist/tests/devShim.test.js.map +1 -0
- package/dist/tests/gateway.test.js +87 -2
- package/dist/tests/gateway.test.js.map +1 -1
- package/dist/tests/gatewayExtensions.test.js +2 -0
- package/dist/tests/gatewayExtensions.test.js.map +1 -1
- package/dist/tests/github.test.js +2 -2
- package/dist/tests/github.test.js.map +1 -1
- package/dist/tests/huggingface.test.js +2 -2
- package/dist/tests/huggingface.test.js.map +1 -1
- package/dist/tests/latchkeyEndpoint.test.js +9 -5
- package/dist/tests/latchkeyEndpoint.test.js.map +1 -1
- package/dist/tests/manualCredentialForms.test.js +2 -2
- package/dist/tests/manualCredentialForms.test.js.map +1 -1
- package/dist/tests/serviceRegistry.test.js +104 -20
- package/dist/tests/serviceRegistry.test.js.map +1 -1
- package/dist/tests/servicesAgainstRecordings.test.js +2 -2
- package/dist/tests/servicesAgainstRecordings.test.js.map +1 -1
- package/dist/tests/tailscale.test.js +2 -2
- package/dist/tests/tailscale.test.js.map +1 -1
- package/package.json +4 -1
|
@@ -3,7 +3,11 @@ import { AuthorizationBearer, AuthorizationBare, RawCurlCredentials, } from '../
|
|
|
3
3
|
import { deserializeCredentials, serializeCredentials, ApiCredentialsSchema, } from '../src/apiCredentials/serialization.js';
|
|
4
4
|
import { SlackApiCredentials } from '../src/services/slack.js';
|
|
5
5
|
import { TelegramBotCredentials } from '../src/services/telegram.js';
|
|
6
|
-
import { AwsCredentials } from '../src/services/aws.js';
|
|
6
|
+
import { AwsCredentials, AwsRequestBodyNotAvailableError, AwsRequestBodyNotSignableError, } from '../src/services/aws.js';
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { mkdtempSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { tmpdir } from 'node:os';
|
|
10
|
+
import { join } from 'node:path';
|
|
7
11
|
import { GoogleApiKeyCredentials } from '../src/services/google/base.js';
|
|
8
12
|
import { ZoomServerToServerCredentials } from '../src/services/zoom.js';
|
|
9
13
|
describe('AuthorizationBearer', () => {
|
|
@@ -139,6 +143,85 @@ describe('AwsCredentials', () => {
|
|
|
139
143
|
const result = await credentials.injectIntoCurlCall(['-v']);
|
|
140
144
|
expect(result).toEqual(['-v']);
|
|
141
145
|
});
|
|
146
|
+
it('should sign the out-of-band body instead of the @- placeholder', async () => {
|
|
147
|
+
const credentials = new AwsCredentials('AKIAIOSFODNN7EXAMPLE', 'wJalrXUtnFEMI/K7MDENG');
|
|
148
|
+
const body = '{"logGroupName":"/aws/lambda/test"}';
|
|
149
|
+
const curlArguments = [
|
|
150
|
+
'-X',
|
|
151
|
+
'POST',
|
|
152
|
+
'-H',
|
|
153
|
+
'Content-Type: application/x-amz-json-1.1',
|
|
154
|
+
'--data-binary',
|
|
155
|
+
'@-',
|
|
156
|
+
'https://logs.us-east-1.amazonaws.com/',
|
|
157
|
+
];
|
|
158
|
+
const result = (await credentials.injectIntoCurlCall(curlArguments, Buffer.from(body, 'utf-8')));
|
|
159
|
+
const payloadHashHeader = result.find((argument) => argument.startsWith('x-amz-content-sha256: '));
|
|
160
|
+
const expectedHash = createHash('sha256').update(body, 'utf-8').digest('hex');
|
|
161
|
+
expect(payloadHashHeader).toBe(`x-amz-content-sha256: ${expectedHash}`);
|
|
162
|
+
expect(payloadHashHeader).not.toBe(`x-amz-content-sha256: ${createHash('sha256').update('@-', 'utf-8').digest('hex')}`);
|
|
163
|
+
});
|
|
164
|
+
it('should read a @file body reference when signing', async () => {
|
|
165
|
+
const credentials = new AwsCredentials('AKIAIOSFODNN7EXAMPLE', 'wJalrXUtnFEMI/K7MDENG');
|
|
166
|
+
const body = '{"limit":10}';
|
|
167
|
+
const bodyFile = join(mkdtempSync(join(tmpdir(), 'latchkey-aws-')), 'body.json');
|
|
168
|
+
writeFileSync(bodyFile, body);
|
|
169
|
+
const result = (await credentials.injectIntoCurlCall([
|
|
170
|
+
'-X',
|
|
171
|
+
'POST',
|
|
172
|
+
'--data-binary',
|
|
173
|
+
`@${bodyFile}`,
|
|
174
|
+
'https://logs.us-east-1.amazonaws.com/',
|
|
175
|
+
]));
|
|
176
|
+
const expectedHash = createHash('sha256').update(body, 'utf-8').digest('hex');
|
|
177
|
+
expect(result).toContain(`x-amz-content-sha256: ${expectedHash}`);
|
|
178
|
+
});
|
|
179
|
+
it('should report a clear error when the body only exists on curl stdin', async () => {
|
|
180
|
+
const credentials = new AwsCredentials('AKIAIOSFODNN7EXAMPLE', 'wJalrXUtnFEMI/K7MDENG');
|
|
181
|
+
await expect(credentials.injectIntoCurlCall([
|
|
182
|
+
'-X',
|
|
183
|
+
'POST',
|
|
184
|
+
'--data-binary',
|
|
185
|
+
'@-',
|
|
186
|
+
'https://logs.us-east-1.amazonaws.com/',
|
|
187
|
+
])).rejects.toBeInstanceOf(AwsRequestBodyNotAvailableError);
|
|
188
|
+
});
|
|
189
|
+
it('should refuse to sign bodies curl assembles from several data arguments', async () => {
|
|
190
|
+
const credentials = new AwsCredentials('AKIAIOSFODNN7EXAMPLE', 'wJalrXUtnFEMI/K7MDENG');
|
|
191
|
+
const bodyFile = join(mkdtempSync(join(tmpdir(), 'latchkey-aws-')), 'body.json');
|
|
192
|
+
writeFileSync(bodyFile, '{"limit":10}');
|
|
193
|
+
await expect(credentials.injectIntoCurlCall([
|
|
194
|
+
'-X',
|
|
195
|
+
'POST',
|
|
196
|
+
'-d',
|
|
197
|
+
`@${bodyFile}`,
|
|
198
|
+
'-d',
|
|
199
|
+
'extra=1',
|
|
200
|
+
'https://logs.us-east-1.amazonaws.com/',
|
|
201
|
+
])).rejects.toBeInstanceOf(AwsRequestBodyNotSignableError);
|
|
202
|
+
await expect(credentials.injectIntoCurlCall([
|
|
203
|
+
'-X',
|
|
204
|
+
'POST',
|
|
205
|
+
'--data-urlencode',
|
|
206
|
+
`@${bodyFile}`,
|
|
207
|
+
'https://logs.us-east-1.amazonaws.com/',
|
|
208
|
+
])).rejects.toBeInstanceOf(AwsRequestBodyNotSignableError);
|
|
209
|
+
});
|
|
210
|
+
it('should sign x-amz-* headers supplied by the caller', async () => {
|
|
211
|
+
const credentials = new AwsCredentials('AKIAIOSFODNN7EXAMPLE', 'wJalrXUtnFEMI/K7MDENG');
|
|
212
|
+
const result = (await credentials.injectIntoCurlCall([
|
|
213
|
+
'-X',
|
|
214
|
+
'POST',
|
|
215
|
+
'-H',
|
|
216
|
+
'Content-Type: application/x-amz-json-1.1',
|
|
217
|
+
'-H',
|
|
218
|
+
'X-Amz-Target: Logs_20140328.DescribeLogGroups',
|
|
219
|
+
'--data-binary',
|
|
220
|
+
'@-',
|
|
221
|
+
'https://logs.us-east-1.amazonaws.com/',
|
|
222
|
+
], Buffer.from('{}', 'utf-8')));
|
|
223
|
+
expect(result[1]).toContain('SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target');
|
|
224
|
+
});
|
|
142
225
|
});
|
|
143
226
|
describe('serialization roundtrip', () => {
|
|
144
227
|
const cases = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiCredentials.test.js","sourceRoot":"","sources":["../../tests/apiCredentials.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAExE,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,WAAW,GAAG,IAAI,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;QAC9D,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChE,IAAI;YACJ,sCAAsC;SACvC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,WAAW,GAAG,IAAI,iBAAiB,CAAC,eAAe,CAAC,CAAC;QAC3D,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChE,IAAI;YACJ,8BAA8B;SAC/B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,WAAW,GAAG,IAAI,mBAAmB,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;QAC5E,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChE,IAAI;YACJ,kCAAkC;YAClC,IAAI;YACJ,0BAA0B;SAC3B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC9F,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChE,IAAI;YACJ,iBAAiB;YACjB,IAAI;YACJ,gBAAgB;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,WAAW,GAAG,IAAI,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;QACjE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC,CAAC,gCAAgC,CAAC,CAAC,CACnE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,kDAAkD,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,WAAW,GAAG,IAAI,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;QACjE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC;YAC7B,IAAI;YACJ,gCAAgC;YAChC,+BAA+B;SAChC,CAAC,CACH,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,gCAAgC,EAAE,+BAA+B,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,WAAW,GAAG,IAAI,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;QACjE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,gCAAgC,CAAC,CAAC,CACjF,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,kDAAkD,CAAC,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,WAAW,GAAG,IAAI,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;QACpE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC,CAAC,2DAA2D,CAAC,CAAC,CAC9F,CAAC,QAAQ,CAAC,OAAO,CAAC;YACjB,IAAI;YACJ,kCAAkC;YAClC,2DAA2D;SAC5D,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,WAAW,GAAG,IAAI,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;QACpE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC;YAC7B,IAAI;YACJ,gCAAgC;YAChC,+BAA+B;SAChC,CAAC,CACH,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,gCAAgC,EAAE,+BAA+B,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC;YAClD,wEAAwE;SACzE,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,MAAkB,CAAC;QACzC,MAAM,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAC9B,oEAAoE,CACrE,CAAC;QACF,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAC/D,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC;QACzE,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC3B,wEAAwE,CACzE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC;YAClD,IAAI;YACJ,gCAAgC;YAChC,IAAI;YACJ,IAAI;YACJ,6DAA6D;SAC9D,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,MAAkB,CAAC;QACzC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAE,CAAC;QACrC,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,iEAAiE,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC;YAClD,+CAA+C;SAChD,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,MAAkB,CAAC;QACzC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAE,CAAC;QACrC,yEAAyE;QACzE,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC;YAClD,yDAAyD;SAC1D,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,MAAkB,CAAC;QACzC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAE,CAAC;QACrC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,MAAM,KAAK,GAGL;QACJ,EAAE,IAAI,EAAE,qBAAqB,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,CAAC,YAAY,CAAC,EAAE;QACzF,EAAE,IAAI,EAAE,mBAAmB,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,iBAAiB,CAAC,YAAY,CAAC,EAAE;QACrF;YACE,IAAI,EAAE,qBAAqB;YAC3B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC;SAC9D;QACD;YACE,IAAI,EAAE,oBAAoB;YAC1B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,kBAAkB,CAAC,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;SACnE;QACD;YACE,IAAI,EAAE,wBAAwB;YAC9B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,sBAAsB,CAAC,gBAAgB,CAAC;SAChE;QACD;YACE,IAAI,EAAE,gBAAgB;YACtB,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,cAAc,CAAC,sBAAsB,EAAE,WAAW,CAAC;SAC3E;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,uBAAuB,CAAC,kBAAkB,CAAC;SACnE;QACD;YACE,IAAI,EAAE,+BAA+B;YACrC,WAAW,EAAE,GAAG,EAAE,CAChB,IAAI,6BAA6B,CAC/B,YAAY,EACZ,WAAW,EACX,eAAe,EACf,cAAc,EACd,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAC9C;SACJ;KACF,CAAC;IAEF,KAAK,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,iBAAiB,EAAE,IAAI,KAAK,EAAE,CAAC;QAC7D,EAAE,CAAC,oBAAoB,IAAI,gCAAgC,EAAE,GAAG,EAAE;YAChE,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,YAAY,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;YACxD,MAAM,CAAC,YAAY,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC1D,MAAM,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mBAAmB,IAAI,4BAA4B,EAAE,GAAG,EAAE;YAC3D,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,CAAC,oBAAoB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC;IAED,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC;YAC5C,UAAU,EAAE,SAAS;YACrB,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"apiCredentials.test.js","sourceRoot":"","sources":["../../tests/apiCredentials.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,cAAc,EACd,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAExE,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,WAAW,GAAG,IAAI,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;QAC9D,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChE,IAAI;YACJ,sCAAsC;SACvC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,WAAW,GAAG,IAAI,iBAAiB,CAAC,eAAe,CAAC,CAAC;QAC3D,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChE,IAAI;YACJ,8BAA8B;SAC/B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,WAAW,GAAG,IAAI,mBAAmB,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;QAC5E,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChE,IAAI;YACJ,kCAAkC;YAClC,IAAI;YACJ,0BAA0B;SAC3B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC9F,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChE,IAAI;YACJ,iBAAiB;YACjB,IAAI;YACJ,gBAAgB;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,WAAW,GAAG,IAAI,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;QACjE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC,CAAC,gCAAgC,CAAC,CAAC,CACnE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,kDAAkD,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,WAAW,GAAG,IAAI,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;QACjE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC;YAC7B,IAAI;YACJ,gCAAgC;YAChC,+BAA+B;SAChC,CAAC,CACH,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,gCAAgC,EAAE,+BAA+B,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,WAAW,GAAG,IAAI,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;QACjE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,gCAAgC,CAAC,CAAC,CACjF,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,kDAAkD,CAAC,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,WAAW,GAAG,IAAI,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;QACpE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC,CAAC,2DAA2D,CAAC,CAAC,CAC9F,CAAC,QAAQ,CAAC,OAAO,CAAC;YACjB,IAAI;YACJ,kCAAkC;YAClC,2DAA2D;SAC5D,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,WAAW,GAAG,IAAI,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;QACpE,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC;YAC7B,IAAI;YACJ,gCAAgC;YAChC,+BAA+B;SAChC,CAAC,CACH,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,gCAAgC,EAAE,+BAA+B,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC;YAClD,wEAAwE;SACzE,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,MAAkB,CAAC;QACzC,MAAM,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAC9B,oEAAoE,CACrE,CAAC;QACF,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAC/D,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC;QACzE,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC3B,wEAAwE,CACzE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC;YAClD,IAAI;YACJ,gCAAgC;YAChC,IAAI;YACJ,IAAI;YACJ,6DAA6D;SAC9D,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,MAAkB,CAAC;QACzC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAE,CAAC;QACrC,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,iEAAiE,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC;YAClD,+CAA+C;SAChD,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,MAAkB,CAAC;QACzC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAE,CAAC;QACrC,yEAAyE;QACzE,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC;YAClD,yDAAyD;SAC1D,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,MAAkB,CAAC;QACzC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAE,CAAC;QACrC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,IAAI,GAAG,qCAAqC,CAAC;QACnD,MAAM,aAAa,GAAG;YACpB,IAAI;YACJ,MAAM;YACN,IAAI;YACJ,0CAA0C;YAC1C,eAAe;YACf,IAAI;YACJ,uCAAuC;SACxC,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,MAAM,WAAW,CAAC,kBAAkB,CAClD,aAAa,EACb,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAC3B,CAAa,CAAC;QAEf,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACjD,QAAQ,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAC9C,CAAC;QACF,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9E,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,yBAAyB,YAAY,EAAE,CAAC,CAAC;QACxE,MAAM,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,IAAI,CAChC,yBAAyB,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACpF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,IAAI,GAAG,cAAc,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QACjF,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAE9B,MAAM,MAAM,GAAG,CAAC,MAAM,WAAW,CAAC,kBAAkB,CAAC;YACnD,IAAI;YACJ,MAAM;YACN,eAAe;YACf,IAAI,QAAQ,EAAE;YACd,uCAAuC;SACxC,CAAC,CAAa,CAAC;QAEhB,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9E,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yBAAyB,YAAY,EAAE,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QAExF,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC;YAC7B,IAAI;YACJ,MAAM;YACN,eAAe;YACf,IAAI;YACJ,uCAAuC;SACxC,CAAC,CACH,CAAC,OAAO,CAAC,cAAc,CAAC,+BAA+B,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QACxF,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QACjF,aAAa,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAExC,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC;YAC7B,IAAI;YACJ,MAAM;YACN,IAAI;YACJ,IAAI,QAAQ,EAAE;YACd,IAAI;YACJ,SAAS;YACT,uCAAuC;SACxC,CAAC,CACH,CAAC,OAAO,CAAC,cAAc,CAAC,8BAA8B,CAAC,CAAC;QAEzD,MAAM,MAAM,CACV,WAAW,CAAC,kBAAkB,CAAC;YAC7B,IAAI;YACJ,MAAM;YACN,kBAAkB;YAClB,IAAI,QAAQ,EAAE;YACd,uCAAuC;SACxC,CAAC,CACH,CAAC,OAAO,CAAC,cAAc,CAAC,8BAA8B,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;QAExF,MAAM,MAAM,GAAG,CAAC,MAAM,WAAW,CAAC,kBAAkB,CAClD;YACE,IAAI;YACJ,MAAM;YACN,IAAI;YACJ,0CAA0C;YAC1C,IAAI;YACJ,+CAA+C;YAC/C,eAAe;YACf,IAAI;YACJ,uCAAuC;SACxC,EACD,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAC3B,CAAa,CAAC;QAEf,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CACzB,8EAA8E,CAC/E,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,MAAM,KAAK,GAGL;QACJ,EAAE,IAAI,EAAE,qBAAqB,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,CAAC,YAAY,CAAC,EAAE;QACzF,EAAE,IAAI,EAAE,mBAAmB,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,iBAAiB,CAAC,YAAY,CAAC,EAAE;QACrF;YACE,IAAI,EAAE,qBAAqB;YAC3B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC;SAC9D;QACD;YACE,IAAI,EAAE,oBAAoB;YAC1B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,kBAAkB,CAAC,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;SACnE;QACD;YACE,IAAI,EAAE,wBAAwB;YAC9B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,sBAAsB,CAAC,gBAAgB,CAAC;SAChE;QACD;YACE,IAAI,EAAE,gBAAgB;YACtB,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,cAAc,CAAC,sBAAsB,EAAE,WAAW,CAAC;SAC3E;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,uBAAuB,CAAC,kBAAkB,CAAC;SACnE;QACD;YACE,IAAI,EAAE,+BAA+B;YACrC,WAAW,EAAE,GAAG,EAAE,CAChB,IAAI,6BAA6B,CAC/B,YAAY,EACZ,WAAW,EACX,eAAe,EACf,cAAc,EACd,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAC9C;SACJ;KACF,CAAC;IAEF,KAAK,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,iBAAiB,EAAE,IAAI,KAAK,EAAE,CAAC;QAC7D,EAAE,CAAC,oBAAoB,IAAI,gCAAgC,EAAE,GAAG,EAAE;YAChE,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,YAAY,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;YACxD,MAAM,CAAC,YAAY,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC1D,MAAM,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mBAAmB,IAAI,4BAA4B,EAAE,GAAG,EAAE;YAC3D,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,CAAC,oBAAoB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC;IAED,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC;YAC5C,UAAU,EAAE,SAAS;YACrB,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { mkdtempSync, rmSync, readFileSync, statSync, mkdirSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { mkdtempSync, rmSync, readFileSync, statSync, lstatSync, mkdirSync, readdirSync, symlinkSync, writeFileSync, } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { writeFileAtomic, AtomicWriteError } from '../src/atomicWrite.js';
|
|
@@ -78,6 +78,47 @@ describe('writeFileAtomic', () => {
|
|
|
78
78
|
writeFileAtomic(filePath, content);
|
|
79
79
|
expect(readFileSync(filePath, 'utf-8')).toBe(content);
|
|
80
80
|
});
|
|
81
|
+
it('should write through a symlink instead of replacing it', () => {
|
|
82
|
+
const realPath = join(tempDir, 'real.txt');
|
|
83
|
+
const linkPath = join(tempDir, 'link.txt');
|
|
84
|
+
writeFileSync(realPath, 'original', 'utf-8');
|
|
85
|
+
symlinkSync(realPath, linkPath);
|
|
86
|
+
writeFileAtomic(linkPath, 'updated');
|
|
87
|
+
expect(lstatSync(linkPath).isSymbolicLink()).toBe(true);
|
|
88
|
+
expect(readFileSync(realPath, 'utf-8')).toBe('updated');
|
|
89
|
+
});
|
|
90
|
+
it('should follow a chain of symlinks', () => {
|
|
91
|
+
const realPath = join(tempDir, 'real.txt');
|
|
92
|
+
const middleLinkPath = join(tempDir, 'middle.txt');
|
|
93
|
+
const outerLinkPath = join(tempDir, 'outer.txt');
|
|
94
|
+
writeFileSync(realPath, 'original', 'utf-8');
|
|
95
|
+
symlinkSync(realPath, middleLinkPath);
|
|
96
|
+
symlinkSync(middleLinkPath, outerLinkPath);
|
|
97
|
+
writeFileAtomic(outerLinkPath, 'updated');
|
|
98
|
+
expect(lstatSync(outerLinkPath).isSymbolicLink()).toBe(true);
|
|
99
|
+
expect(lstatSync(middleLinkPath).isSymbolicLink()).toBe(true);
|
|
100
|
+
expect(readFileSync(realPath, 'utf-8')).toBe('updated');
|
|
101
|
+
});
|
|
102
|
+
it('should create the target of a dangling symlink', () => {
|
|
103
|
+
const realPath = join(tempDir, 'not-yet-there.txt');
|
|
104
|
+
const linkPath = join(tempDir, 'link.txt');
|
|
105
|
+
symlinkSync(realPath, linkPath);
|
|
106
|
+
writeFileAtomic(linkPath, 'created');
|
|
107
|
+
expect(lstatSync(linkPath).isSymbolicLink()).toBe(true);
|
|
108
|
+
expect(readFileSync(realPath, 'utf-8')).toBe('created');
|
|
109
|
+
});
|
|
110
|
+
it('should write through a symlink pointing into another directory', () => {
|
|
111
|
+
const otherDir = join(tempDir, 'other');
|
|
112
|
+
mkdirSync(otherDir);
|
|
113
|
+
const realPath = join(otherDir, 'real.txt');
|
|
114
|
+
const linkPath = join(tempDir, 'link.txt');
|
|
115
|
+
writeFileSync(realPath, 'original', 'utf-8');
|
|
116
|
+
symlinkSync('other/real.txt', linkPath);
|
|
117
|
+
writeFileAtomic(linkPath, 'updated', { mode: 0o600 });
|
|
118
|
+
expect(lstatSync(linkPath).isSymbolicLink()).toBe(true);
|
|
119
|
+
expect(readFileSync(realPath, 'utf-8')).toBe('updated');
|
|
120
|
+
expect(readdirSync(tempDir).sort()).toEqual(['link.txt', 'other']);
|
|
121
|
+
});
|
|
81
122
|
it('should not corrupt the target file if rename would fail', () => {
|
|
82
123
|
// Write initial content
|
|
83
124
|
const filePath = join(tempDir, 'existing.txt');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomicWrite.test.js","sourceRoot":"","sources":["../../tests/atomicWrite.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,
|
|
1
|
+
{"version":3,"file":"atomicWrite.test.js","sourceRoot":"","sources":["../../tests/atomicWrite.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A registry over the services latchkey ships with.
|
|
3
|
+
*
|
|
4
|
+
* The CLI and the gateway each build their own registry with
|
|
5
|
+
* `createServiceRegistry`, since theirs also carry whatever config.json holds.
|
|
6
|
+
* Tests that only care about the built-in services share this one.
|
|
7
|
+
*/
|
|
8
|
+
import { ServiceRegistry } from '../src/serviceRegistry.js';
|
|
9
|
+
export declare const BUILTIN_SERVICE_REGISTRY: ServiceRegistry;
|
|
10
|
+
//# sourceMappingURL=builtinServiceRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtinServiceRegistry.d.ts","sourceRoot":"","sources":["../../tests/builtinServiceRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAoB,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE9E,eAAO,MAAM,wBAAwB,iBAAwC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A registry over the services latchkey ships with.
|
|
3
|
+
*
|
|
4
|
+
* The CLI and the gateway each build their own registry with
|
|
5
|
+
* `createServiceRegistry`, since theirs also carry whatever config.json holds.
|
|
6
|
+
* Tests that only care about the built-in services share this one.
|
|
7
|
+
*/
|
|
8
|
+
import { BUILTIN_SERVICES, ServiceRegistry } from '../src/serviceRegistry.js';
|
|
9
|
+
export const BUILTIN_SERVICE_REGISTRY = new ServiceRegistry(BUILTIN_SERVICES);
|
|
10
|
+
//# sourceMappingURL=builtinServiceRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtinServiceRegistry.js","sourceRoot":"","sources":["../../tests/builtinServiceRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE9E,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,eAAe,CAAC,gBAAgB,CAAC,CAAC"}
|
package/dist/tests/cli.test.js
CHANGED
|
@@ -5,12 +5,13 @@ import { tmpdir } from 'node:os';
|
|
|
5
5
|
import { execSync } from 'node:child_process';
|
|
6
6
|
import { Command } from 'commander';
|
|
7
7
|
import { registerCommands } from '../src/cliCommands.js';
|
|
8
|
-
import { CurlParseError, extractUrlFromCurlArguments } from '../src/curl.js';
|
|
8
|
+
import { CurlParseError, extractUrlFromCurlArguments, resolveCurlRequestBodySource, } from '../src/curl.js';
|
|
9
9
|
import { hasGraphicalEnvironment } from '../src/playwrightUtils.js';
|
|
10
10
|
import { EncryptedStorage } from '../src/encryptedStorage.js';
|
|
11
11
|
import { Config } from '../src/config.js';
|
|
12
12
|
import { ServiceRegistry } from '../src/serviceRegistry.js';
|
|
13
13
|
import { ApiCredentialStatus } from '../src/apiCredentials/base.js';
|
|
14
|
+
import { LATEST_VERSION } from '../src/migrations.js';
|
|
14
15
|
import { Service } from '../src/services/core/base.js';
|
|
15
16
|
import { createMockService, MockService } from './mockService.js';
|
|
16
17
|
import { RegisteredService } from '../src/services/core/registered.js';
|
|
@@ -183,6 +184,26 @@ describe('extractUrlFromCurlArguments', () => {
|
|
|
183
184
|
expect(extractUrlFromCurlArguments(arguments_)).toBe('https://example.com/api?query=from%3Ame');
|
|
184
185
|
});
|
|
185
186
|
});
|
|
187
|
+
describe('resolveCurlRequestBodySource', () => {
|
|
188
|
+
it('should report an inline body when no file reference is present', () => {
|
|
189
|
+
expect(resolveCurlRequestBodySource(['-d', '{"a":1}', 'https://example.com'], '{"a":1}')).toEqual({ kind: 'inline', text: '{"a":1}' });
|
|
190
|
+
});
|
|
191
|
+
it('should report an inline body for --data-raw, which treats @ literally', () => {
|
|
192
|
+
expect(resolveCurlRequestBodySource(['--data-raw', '@literal', 'https://example.com'], '@literal')).toEqual({ kind: 'inline', text: '@literal' });
|
|
193
|
+
});
|
|
194
|
+
it('should report a file reference', () => {
|
|
195
|
+
expect(resolveCurlRequestBodySource(['--data-binary', '@/tmp/payload.json', 'https://example.com'], '@/tmp/payload.json')).toEqual({ kind: 'file', path: '/tmp/payload.json' });
|
|
196
|
+
});
|
|
197
|
+
it('should report stdin for @-', () => {
|
|
198
|
+
expect(resolveCurlRequestBodySource(['--data-binary', '@-', 'https://example.com'], '@-')).toEqual({ kind: 'stdin' });
|
|
199
|
+
});
|
|
200
|
+
it('should report an unreconstructable body for combined data arguments', () => {
|
|
201
|
+
expect(resolveCurlRequestBodySource(['-d', '@/tmp/payload.json', '-d', 'extra=1', 'https://example.com'], '@/tmp/payload.json&extra=1')).toEqual({ kind: 'unreconstructable' });
|
|
202
|
+
});
|
|
203
|
+
it('should report an unreconstructable body for url-encoded file data', () => {
|
|
204
|
+
expect(resolveCurlRequestBodySource(['--data-urlencode', '@/tmp/payload.json', 'https://example.com'], '@/tmp/payload.json')).toEqual({ kind: 'unreconstructable' });
|
|
205
|
+
});
|
|
206
|
+
});
|
|
186
207
|
describe('hasGraphicalEnvironment', () => {
|
|
187
208
|
const originalPlatform = process.platform;
|
|
188
209
|
afterEach(() => {
|
|
@@ -345,6 +366,7 @@ describe('CLI commands with dependency injection', () => {
|
|
|
345
366
|
const mockRegistry = new ServiceRegistry([mockSlackService]);
|
|
346
367
|
return {
|
|
347
368
|
registry: mockRegistry,
|
|
369
|
+
builtinServices: [mockSlackService],
|
|
348
370
|
config: createMockConfig(),
|
|
349
371
|
runCurl: (args) => {
|
|
350
372
|
capturedArgs.push(...args);
|
|
@@ -973,11 +995,27 @@ describe('CLI commands with dependency injection', () => {
|
|
|
973
995
|
function withStdinKey(key, overrides = {}) {
|
|
974
996
|
return createMockDependencies({ readStdin: () => Promise.resolve(key), ...overrides });
|
|
975
997
|
}
|
|
976
|
-
// The
|
|
998
|
+
// The filenames used by the mock config.
|
|
977
999
|
const STORE_FILENAME = 'credentials.json';
|
|
978
|
-
|
|
979
|
-
|
|
1000
|
+
const BROWSER_STATE_FILENAME = 'browser_state.json';
|
|
1001
|
+
function writeStore(contents, preparations = {}) {
|
|
1002
|
+
writeSecureFile(join(tempDir, STORE_FILENAME), JSON.stringify({ ...nestAccounts(contents), preparations }));
|
|
1003
|
+
}
|
|
1004
|
+
function readPreparationsWithKey(path, key) {
|
|
1005
|
+
const raw = JSON.parse(new EncryptedStorage(key).readFile(path) ?? '{}');
|
|
1006
|
+
return raw.preparations ?? {};
|
|
980
1007
|
}
|
|
1008
|
+
// A destination that already holds a store must be in the current data
|
|
1009
|
+
// format, which real Latchkey directories record in this file.
|
|
1010
|
+
function stampDataFormatVersion(directory) {
|
|
1011
|
+
mkdirSync(directory, { recursive: true });
|
|
1012
|
+
writeFileSync(join(directory, 'data-format-version'), String(LATEST_VERSION));
|
|
1013
|
+
}
|
|
1014
|
+
const GITLAB_PREPARATION = {
|
|
1015
|
+
objectType: 'oauth',
|
|
1016
|
+
clientId: 'gitlab-client-id',
|
|
1017
|
+
clientSecret: 'gitlab-client-secret',
|
|
1018
|
+
};
|
|
981
1019
|
it('re-encrypts all stored credentials with the new key', async () => {
|
|
982
1020
|
writeStore({
|
|
983
1021
|
slack: { objectType: 'slack', token: 'tok', dCookie: 'cookie' },
|
|
@@ -1025,7 +1063,7 @@ describe('CLI commands with dependency injection', () => {
|
|
|
1025
1063
|
const reEncrypted = readWithKey(join(destinationDirectory, STORE_FILENAME), NEW_ENCRYPTION_KEY);
|
|
1026
1064
|
expect(Object.keys(reEncrypted)).toEqual(['slack']);
|
|
1027
1065
|
});
|
|
1028
|
-
it('errors when a requested service has
|
|
1066
|
+
it('errors when a requested service has neither credentials nor a preparation', async () => {
|
|
1029
1067
|
writeStore({ slack: { objectType: 'slack', token: 'tok', dCookie: 'cookie' } });
|
|
1030
1068
|
const destinationDirectory = join(tempDir, 'export');
|
|
1031
1069
|
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
@@ -1033,6 +1071,60 @@ describe('CLI commands with dependency injection', () => {
|
|
|
1033
1071
|
expect(exitCode).toBe(1);
|
|
1034
1072
|
expect(existsSync(join(destinationDirectory, STORE_FILENAME))).toBe(false);
|
|
1035
1073
|
});
|
|
1074
|
+
it('carries the preparations of the re-encrypted services', async () => {
|
|
1075
|
+
writeStore({ gitlab: { objectType: 'authorizationBearer', token: 'gitlab-token' } }, { gitlab: GITLAB_PREPARATION });
|
|
1076
|
+
const destinationDirectory = join(tempDir, 'export');
|
|
1077
|
+
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
1078
|
+
await runCommand(['auth', 're-encrypt', destinationDirectory], deps);
|
|
1079
|
+
expect(exitCode).toBeNull();
|
|
1080
|
+
const destination = join(destinationDirectory, STORE_FILENAME);
|
|
1081
|
+
expect(readPreparationsWithKey(destination, NEW_ENCRYPTION_KEY)).toEqual({
|
|
1082
|
+
gitlab: GITLAB_PREPARATION,
|
|
1083
|
+
});
|
|
1084
|
+
});
|
|
1085
|
+
it('includes services that only have a preparation', async () => {
|
|
1086
|
+
writeStore({ slack: { objectType: 'slack', token: 'tok', dCookie: 'cookie' } }, { gitlab: GITLAB_PREPARATION });
|
|
1087
|
+
const destinationDirectory = join(tempDir, 'export');
|
|
1088
|
+
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
1089
|
+
await runCommand(['auth', 're-encrypt', destinationDirectory], deps);
|
|
1090
|
+
expect(exitCode).toBeNull();
|
|
1091
|
+
const destination = join(destinationDirectory, STORE_FILENAME);
|
|
1092
|
+
expect(Object.keys(readWithKey(destination, NEW_ENCRYPTION_KEY))).toEqual(['slack']);
|
|
1093
|
+
expect(readPreparationsWithKey(destination, NEW_ENCRYPTION_KEY)).toEqual({
|
|
1094
|
+
gitlab: GITLAB_PREPARATION,
|
|
1095
|
+
});
|
|
1096
|
+
expect(logs.join('\n')).toContain('2 service(s)');
|
|
1097
|
+
});
|
|
1098
|
+
it('selects a service that only has a preparation with --services', async () => {
|
|
1099
|
+
writeStore({ slack: { objectType: 'slack', token: 'tok', dCookie: 'cookie' } }, { gitlab: GITLAB_PREPARATION });
|
|
1100
|
+
const destinationDirectory = join(tempDir, 'export');
|
|
1101
|
+
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
1102
|
+
await runCommand(['auth', 're-encrypt', destinationDirectory, '--services', 'gitlab'], deps);
|
|
1103
|
+
expect(exitCode).toBeNull();
|
|
1104
|
+
const destination = join(destinationDirectory, STORE_FILENAME);
|
|
1105
|
+
expect(readWithKey(destination, NEW_ENCRYPTION_KEY)).toEqual({});
|
|
1106
|
+
expect(readPreparationsWithKey(destination, NEW_ENCRYPTION_KEY)).toEqual({
|
|
1107
|
+
gitlab: GITLAB_PREPARATION,
|
|
1108
|
+
});
|
|
1109
|
+
});
|
|
1110
|
+
it('replaces an existing preparation in the destination', async () => {
|
|
1111
|
+
writeStore({}, { gitlab: GITLAB_PREPARATION });
|
|
1112
|
+
const destinationDirectory = join(tempDir, 'export');
|
|
1113
|
+
const destination = join(destinationDirectory, STORE_FILENAME);
|
|
1114
|
+
stampDataFormatVersion(destinationDirectory);
|
|
1115
|
+
new EncryptedStorage(NEW_ENCRYPTION_KEY).writeFile(destination, JSON.stringify({
|
|
1116
|
+
credentials: {},
|
|
1117
|
+
preparations: {
|
|
1118
|
+
gitlab: { objectType: 'oauth', clientId: 'old-id', clientSecret: 'old-secret' },
|
|
1119
|
+
},
|
|
1120
|
+
}));
|
|
1121
|
+
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
1122
|
+
await runCommand(['auth', 're-encrypt', destinationDirectory], deps);
|
|
1123
|
+
expect(exitCode).toBeNull();
|
|
1124
|
+
expect(readPreparationsWithKey(destination, NEW_ENCRYPTION_KEY)).toEqual({
|
|
1125
|
+
gitlab: GITLAB_PREPARATION,
|
|
1126
|
+
});
|
|
1127
|
+
});
|
|
1036
1128
|
it('errors for an invalid encryption key read from stdin', async () => {
|
|
1037
1129
|
writeStore({});
|
|
1038
1130
|
const destinationDirectory = join(tempDir, 'export');
|
|
@@ -1049,10 +1141,36 @@ describe('CLI commands with dependency injection', () => {
|
|
|
1049
1141
|
expect(exitCode).toBeNull();
|
|
1050
1142
|
expect(Object.keys(readWithKey(join(destinationDirectory, STORE_FILENAME), NEW_ENCRYPTION_KEY))).toEqual(['slack']);
|
|
1051
1143
|
});
|
|
1052
|
-
it('
|
|
1144
|
+
it('adds the services into an existing credential store, overwriting by service', async () => {
|
|
1145
|
+
writeStore({
|
|
1146
|
+
slack: { objectType: 'slack', token: 'new-tok', dCookie: 'new-cookie' },
|
|
1147
|
+
});
|
|
1148
|
+
const destinationDirectory = join(tempDir, 'export');
|
|
1149
|
+
const destination = join(destinationDirectory, STORE_FILENAME);
|
|
1150
|
+
stampDataFormatVersion(destinationDirectory);
|
|
1151
|
+
new EncryptedStorage(NEW_ENCRYPTION_KEY).writeFile(destination, JSON.stringify(nestAccounts({
|
|
1152
|
+
slack: { objectType: 'slack', token: 'old-tok', dCookie: 'old-cookie' },
|
|
1153
|
+
discord: { objectType: 'authorizationBearer', token: 'discord-token' },
|
|
1154
|
+
})));
|
|
1155
|
+
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
1156
|
+
await runCommand(['auth', 're-encrypt', destinationDirectory], deps);
|
|
1157
|
+
expect(exitCode).toBeNull();
|
|
1158
|
+
const reEncrypted = readWithKey(destination, NEW_ENCRYPTION_KEY);
|
|
1159
|
+
expect(Object.keys(reEncrypted).sort()).toEqual(['discord', 'slack']);
|
|
1160
|
+
expect(reEncrypted.slack).toEqual({
|
|
1161
|
+
objectType: 'slack',
|
|
1162
|
+
token: 'new-tok',
|
|
1163
|
+
dCookie: 'new-cookie',
|
|
1164
|
+
});
|
|
1165
|
+
expect(reEncrypted.discord).toEqual({
|
|
1166
|
+
objectType: 'authorizationBearer',
|
|
1167
|
+
token: 'discord-token',
|
|
1168
|
+
});
|
|
1169
|
+
});
|
|
1170
|
+
it('errors when the existing credential store cannot be read with the new key', async () => {
|
|
1053
1171
|
writeStore({ slack: { objectType: 'slack', token: 'tok', dCookie: 'cookie' } });
|
|
1054
1172
|
const destinationDirectory = join(tempDir, 'export');
|
|
1055
|
-
|
|
1173
|
+
stampDataFormatVersion(destinationDirectory);
|
|
1056
1174
|
const destination = join(destinationDirectory, STORE_FILENAME);
|
|
1057
1175
|
writeFileSync(destination, 'existing');
|
|
1058
1176
|
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
@@ -1060,6 +1178,36 @@ describe('CLI commands with dependency injection', () => {
|
|
|
1060
1178
|
expect(exitCode).toBe(1);
|
|
1061
1179
|
expect(readFileSync(destination, 'utf-8')).toBe('existing');
|
|
1062
1180
|
});
|
|
1181
|
+
it('re-encrypts the browser state with --browser-state', async () => {
|
|
1182
|
+
writeStore({ slack: { objectType: 'slack', token: 'tok', dCookie: 'cookie' } });
|
|
1183
|
+
new EncryptedStorage(TEST_ENCRYPTION_KEY).writeFile(join(tempDir, BROWSER_STATE_FILENAME), '{"cookies":[]}');
|
|
1184
|
+
const destinationDirectory = join(tempDir, 'export');
|
|
1185
|
+
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
1186
|
+
await runCommand(['auth', 're-encrypt', destinationDirectory, '--browser-state'], deps);
|
|
1187
|
+
expect(exitCode).toBeNull();
|
|
1188
|
+
const browserStateDestination = join(destinationDirectory, BROWSER_STATE_FILENAME);
|
|
1189
|
+
expect(new EncryptedStorage(NEW_ENCRYPTION_KEY).readFile(browserStateDestination)).toBe('{"cookies":[]}');
|
|
1190
|
+
expect(Object.keys(readWithKey(join(destinationDirectory, STORE_FILENAME), NEW_ENCRYPTION_KEY))).toEqual(['slack']);
|
|
1191
|
+
});
|
|
1192
|
+
it('errors with --browser-state when there is no browser state', async () => {
|
|
1193
|
+
writeStore({ slack: { objectType: 'slack', token: 'tok', dCookie: 'cookie' } });
|
|
1194
|
+
const destinationDirectory = join(tempDir, 'export');
|
|
1195
|
+
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
1196
|
+
await runCommand(['auth', 're-encrypt', destinationDirectory, '--browser-state'], deps);
|
|
1197
|
+
expect(exitCode).toBe(1);
|
|
1198
|
+
expect(existsSync(join(destinationDirectory, STORE_FILENAME))).toBe(false);
|
|
1199
|
+
});
|
|
1200
|
+
it('overwrites an existing browser state in the destination', async () => {
|
|
1201
|
+
writeStore({});
|
|
1202
|
+
new EncryptedStorage(TEST_ENCRYPTION_KEY).writeFile(join(tempDir, BROWSER_STATE_FILENAME), '{"cookies":["new"]}');
|
|
1203
|
+
const destinationDirectory = join(tempDir, 'export');
|
|
1204
|
+
const browserStateDestination = join(destinationDirectory, BROWSER_STATE_FILENAME);
|
|
1205
|
+
new EncryptedStorage(NEW_ENCRYPTION_KEY).writeFile(browserStateDestination, 'old');
|
|
1206
|
+
const deps = withStdinKey(NEW_ENCRYPTION_KEY);
|
|
1207
|
+
await runCommand(['auth', 're-encrypt', destinationDirectory, '--browser-state'], deps);
|
|
1208
|
+
expect(exitCode).toBeNull();
|
|
1209
|
+
expect(new EncryptedStorage(NEW_ENCRYPTION_KEY).readFile(browserStateDestination)).toBe('{"cookies":["new"]}');
|
|
1210
|
+
});
|
|
1063
1211
|
it('errors when the destination is an existing file, not a directory', async () => {
|
|
1064
1212
|
writeStore({ slack: { objectType: 'slack', token: 'tok', dCookie: 'cookie' } });
|
|
1065
1213
|
const destinationDirectory = join(tempDir, 'export');
|