latchkey 2.21.0 → 3.0.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/README.md +36 -4
- package/dist/skills/generic/latchkey/SKILL.md +21 -0
- package/dist/skills/openclaw/latchkey/SKILL.md +21 -0
- package/dist/src/apiCredentials/account.d.ts +28 -0
- package/dist/src/apiCredentials/account.d.ts.map +1 -0
- package/dist/src/apiCredentials/account.js +49 -0
- package/dist/src/apiCredentials/account.js.map +1 -0
- package/dist/src/apiCredentials/store.d.ts +70 -4
- package/dist/src/apiCredentials/store.d.ts.map +1 -1
- package/dist/src/apiCredentials/store.js +161 -19
- package/dist/src/apiCredentials/store.js.map +1 -1
- package/dist/src/apiCredentials/utils.d.ts +2 -2
- package/dist/src/apiCredentials/utils.d.ts.map +1 -1
- package/dist/src/apiCredentials/utils.js +5 -5
- package/dist/src/apiCredentials/utils.js.map +1 -1
- package/dist/src/cli.js +1 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/cliCommands.d.ts.map +1 -1
- package/dist/src/cliCommands.js +118 -22
- package/dist/src/cliCommands.js.map +1 -1
- package/dist/src/config.d.ts +6 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +8 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/configDataStore.d.ts +3 -0
- package/dist/src/configDataStore.d.ts.map +1 -1
- package/dist/src/configDataStore.js +1 -0
- package/dist/src/configDataStore.js.map +1 -1
- package/dist/src/curl.d.ts +21 -16
- package/dist/src/curl.d.ts.map +1 -1
- package/dist/src/curl.js +17 -24
- package/dist/src/curl.js.map +1 -1
- package/dist/src/curlInjection.d.ts +8 -2
- package/dist/src/curlInjection.d.ts.map +1 -1
- package/dist/src/curlInjection.js +13 -8
- package/dist/src/curlInjection.js.map +1 -1
- package/dist/src/errorMessages.d.ts +2 -2
- package/dist/src/errorMessages.d.ts.map +1 -1
- package/dist/src/errorMessages.js +22 -6
- package/dist/src/errorMessages.js.map +1 -1
- package/dist/src/gateway/gatewayEndpoint.d.ts +1 -1
- package/dist/src/gateway/gatewayEndpoint.d.ts.map +1 -1
- package/dist/src/gateway/gatewayEndpoint.js +3 -1
- package/dist/src/gateway/gatewayEndpoint.js.map +1 -1
- package/dist/src/gateway/latchkeyEndpoint.d.ts +6 -0
- package/dist/src/gateway/latchkeyEndpoint.d.ts.map +1 -1
- package/dist/src/gateway/latchkeyEndpoint.js +6 -4
- package/dist/src/gateway/latchkeyEndpoint.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- 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 +27 -1
- package/dist/src/migrations.d.ts.map +1 -1
- package/dist/src/migrations.js +141 -4
- package/dist/src/migrations.js.map +1 -1
- package/dist/src/oauthUtils.d.ts +2 -2
- package/dist/src/oauthUtils.d.ts.map +1 -1
- package/dist/src/oauthUtils.js +5 -5
- package/dist/src/oauthUtils.js.map +1 -1
- package/dist/src/services/aws.d.ts +1 -0
- package/dist/src/services/aws.d.ts.map +1 -1
- package/dist/src/services/aws.js +13 -0
- package/dist/src/services/aws.js.map +1 -1
- package/dist/src/services/calendly.d.ts +2 -0
- package/dist/src/services/calendly.d.ts.map +1 -1
- package/dist/src/services/calendly.js +7 -0
- package/dist/src/services/calendly.js.map +1 -1
- package/dist/src/services/coolify.d.ts +3 -1
- package/dist/src/services/coolify.d.ts.map +1 -1
- package/dist/src/services/coolify.js +10 -1
- package/dist/src/services/coolify.js.map +1 -1
- package/dist/src/services/core/base.d.ts +43 -1
- package/dist/src/services/core/base.d.ts.map +1 -1
- package/dist/src/services/core/base.js +29 -9
- package/dist/src/services/core/base.js.map +1 -1
- package/dist/src/services/core/registered.d.ts +1 -0
- package/dist/src/services/core/registered.d.ts.map +1 -1
- package/dist/src/services/core/registered.js +5 -0
- package/dist/src/services/core/registered.js.map +1 -1
- package/dist/src/services/discord.d.ts +1 -0
- package/dist/src/services/discord.d.ts.map +1 -1
- package/dist/src/services/discord.js +9 -0
- package/dist/src/services/discord.js.map +1 -1
- package/dist/src/services/dropbox.d.ts +2 -1
- package/dist/src/services/dropbox.d.ts.map +1 -1
- package/dist/src/services/dropbox.js +17 -11
- package/dist/src/services/dropbox.js.map +1 -1
- package/dist/src/services/figma.d.ts +2 -0
- package/dist/src/services/figma.d.ts.map +1 -1
- package/dist/src/services/figma.js +7 -0
- package/dist/src/services/figma.js.map +1 -1
- package/dist/src/services/github.d.ts +1 -0
- package/dist/src/services/github.d.ts.map +1 -1
- package/dist/src/services/github.js +9 -0
- package/dist/src/services/github.js.map +1 -1
- package/dist/src/services/gitlab.d.ts +2 -0
- package/dist/src/services/gitlab.d.ts.map +1 -1
- package/dist/src/services/gitlab.js +9 -0
- package/dist/src/services/gitlab.js.map +1 -1
- package/dist/src/services/google/analytics.d.ts +0 -1
- package/dist/src/services/google/analytics.d.ts.map +1 -1
- package/dist/src/services/google/analytics.js +0 -3
- package/dist/src/services/google/analytics.js.map +1 -1
- package/dist/src/services/google/base.d.ts +11 -0
- package/dist/src/services/google/base.d.ts.map +1 -1
- package/dist/src/services/google/base.js +26 -7
- package/dist/src/services/google/base.js.map +1 -1
- package/dist/src/services/google/calendar.d.ts +0 -1
- package/dist/src/services/google/calendar.d.ts.map +1 -1
- package/dist/src/services/google/calendar.js +0 -3
- package/dist/src/services/google/calendar.js.map +1 -1
- package/dist/src/services/google/directions.d.ts +1 -0
- package/dist/src/services/google/directions.d.ts.map +1 -1
- package/dist/src/services/google/directions.js +5 -0
- package/dist/src/services/google/directions.js.map +1 -1
- package/dist/src/services/google/docs.d.ts +0 -1
- package/dist/src/services/google/docs.d.ts.map +1 -1
- package/dist/src/services/google/docs.js +0 -3
- package/dist/src/services/google/docs.js.map +1 -1
- package/dist/src/services/google/drive.d.ts +0 -1
- package/dist/src/services/google/drive.d.ts.map +1 -1
- package/dist/src/services/google/drive.js +0 -3
- package/dist/src/services/google/drive.js.map +1 -1
- package/dist/src/services/google/gmail.d.ts +0 -1
- package/dist/src/services/google/gmail.d.ts.map +1 -1
- package/dist/src/services/google/gmail.js +0 -3
- package/dist/src/services/google/gmail.js.map +1 -1
- package/dist/src/services/google/people.d.ts +0 -1
- package/dist/src/services/google/people.d.ts.map +1 -1
- package/dist/src/services/google/people.js +0 -3
- package/dist/src/services/google/people.js.map +1 -1
- package/dist/src/services/google/sheets.d.ts +0 -1
- package/dist/src/services/google/sheets.d.ts.map +1 -1
- package/dist/src/services/google/sheets.js +0 -3
- package/dist/src/services/google/sheets.js.map +1 -1
- package/dist/src/services/google/slides.d.ts +0 -1
- package/dist/src/services/google/slides.d.ts.map +1 -1
- package/dist/src/services/google/slides.js +0 -3
- package/dist/src/services/google/slides.js.map +1 -1
- package/dist/src/services/index.d.ts +1 -1
- package/dist/src/services/index.d.ts.map +1 -1
- package/dist/src/services/index.js.map +1 -1
- package/dist/src/services/linear.d.ts +2 -1
- package/dist/src/services/linear.d.ts.map +1 -1
- package/dist/src/services/linear.js +8 -1
- package/dist/src/services/linear.js.map +1 -1
- package/dist/src/services/mailchimp.d.ts +2 -0
- package/dist/src/services/mailchimp.d.ts.map +1 -1
- package/dist/src/services/mailchimp.js +7 -0
- package/dist/src/services/mailchimp.js.map +1 -1
- package/dist/src/services/notion-mcp.d.ts +3 -2
- package/dist/src/services/notion-mcp.d.ts.map +1 -1
- package/dist/src/services/notion-mcp.js +111 -14
- package/dist/src/services/notion-mcp.js.map +1 -1
- package/dist/src/services/notion.d.ts +2 -0
- package/dist/src/services/notion.d.ts.map +1 -1
- package/dist/src/services/notion.js +17 -0
- package/dist/src/services/notion.js.map +1 -1
- package/dist/src/services/ramp.d.ts +11 -2
- package/dist/src/services/ramp.d.ts.map +1 -1
- package/dist/src/services/ramp.js +35 -9
- package/dist/src/services/ramp.js.map +1 -1
- package/dist/src/services/sentry.d.ts +3 -2
- package/dist/src/services/sentry.d.ts.map +1 -1
- package/dist/src/services/sentry.js +12 -27
- package/dist/src/services/sentry.js.map +1 -1
- package/dist/src/services/slack.d.ts +3 -2
- package/dist/src/services/slack.d.ts.map +1 -1
- package/dist/src/services/slack.js +19 -13
- package/dist/src/services/slack.js.map +1 -1
- package/dist/src/services/stripe.d.ts +7 -0
- package/dist/src/services/stripe.d.ts.map +1 -1
- package/dist/src/services/stripe.js +15 -0
- package/dist/src/services/stripe.js.map +1 -1
- package/dist/src/services/telegram.d.ts +1 -0
- package/dist/src/services/telegram.d.ts.map +1 -1
- package/dist/src/services/telegram.js +7 -0
- package/dist/src/services/telegram.js.map +1 -1
- package/dist/src/services/todoist.d.ts +2 -1
- package/dist/src/services/todoist.d.ts.map +1 -1
- package/dist/src/services/todoist.js +9 -1
- package/dist/src/services/todoist.js.map +1 -1
- package/dist/src/services/umami.d.ts +3 -1
- package/dist/src/services/umami.d.ts.map +1 -1
- package/dist/src/services/umami.js +11 -1
- package/dist/src/services/umami.js.map +1 -1
- package/dist/src/services/yelp.d.ts +1 -0
- package/dist/src/services/yelp.d.ts.map +1 -1
- package/dist/src/services/yelp.js +5 -0
- package/dist/src/services/yelp.js.map +1 -1
- package/dist/src/services/zoom.d.ts +8 -0
- package/dist/src/services/zoom.d.ts.map +1 -1
- package/dist/src/services/zoom.js +16 -0
- package/dist/src/services/zoom.js.map +1 -1
- package/dist/src/sharedOperations.d.ts +30 -10
- package/dist/src/sharedOperations.d.ts.map +1 -1
- package/dist/src/sharedOperations.js +67 -29
- package/dist/src/sharedOperations.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/tests/apiCredentialStore.test.js +155 -2
- package/dist/tests/apiCredentialStore.test.js.map +1 -1
- package/dist/tests/apiCredentialsUtils.test.js +1 -1
- package/dist/tests/apiCredentialsUtils.test.js.map +1 -1
- package/dist/tests/cli.test.js +334 -147
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/config.test.js +5 -0
- package/dist/tests/config.test.js.map +1 -1
- package/dist/tests/gateway.test.js +8 -18
- package/dist/tests/gateway.test.js.map +1 -1
- package/dist/tests/latchkeyEndpoint.test.js +18 -28
- package/dist/tests/latchkeyEndpoint.test.js.map +1 -1
- package/dist/tests/migrations.test.js +299 -39
- package/dist/tests/migrations.test.js.map +1 -1
- package/dist/tests/mockService.d.ts +25 -0
- package/dist/tests/mockService.d.ts.map +1 -0
- package/dist/tests/mockService.js +40 -0
- package/dist/tests/mockService.js.map +1 -0
- package/dist/tests/oauthUtils.test.js +12 -12
- package/dist/tests/oauthUtils.test.js.map +1 -1
- package/dist/tests/serviceAccounts.test.d.ts +12 -0
- package/dist/tests/serviceAccounts.test.d.ts.map +1 -0
- package/dist/tests/serviceAccounts.test.js +278 -0
- package/dist/tests/serviceAccounts.test.js.map +1 -0
- package/dist/tests/sharedOperations.test.js +327 -58
- package/dist/tests/sharedOperations.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauthUtils.test.js","sourceRoot":"","sources":["../../tests/oauthUtils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,+BAA+B,GAChC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AAEvC,SAAS,CAAC,GAAG,EAAE;IACb,EAAE,CAAC,eAAe,EAAE,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,KAAK,wBAAwB,CAAC;AAC9B,KAAK,uBAAuB,CAAC;AAC7B,KAAK,+BAA+B,CAAC;AAErC,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,wEAAwE;QACxE,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAC7C,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,yCAAyC;QACzC,MAAM,CAAC,qBAAqB,CAAC,6CAA6C,CAAC,CAAC,CAAC,IAAI,CAC/E,6CAA6C,CAC9C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,SAAS,GAAG,qBAAqB,CAAC,oBAAoB,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,2CAA2C,EAAE,
|
|
1
|
+
{"version":3,"file":"oauthUtils.test.js","sourceRoot":"","sources":["../../tests/oauthUtils.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the credential check and for account determination.
|
|
3
|
+
*
|
|
4
|
+
* The credential check runs a single curl call whose output is the response
|
|
5
|
+
* body followed by the HTTP status code on the final line (produced by
|
|
6
|
+
* `-w '\n%{http_code}'`). Account determination (`getAccount`) runs its own
|
|
7
|
+
* curl call against an identity-revealing endpoint and parses the account
|
|
8
|
+
* from the raw response body. These tests mock the async subprocess runner
|
|
9
|
+
* to feed service implementations recorded response bodies.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=serviceAccounts.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serviceAccounts.test.d.ts","sourceRoot":"","sources":["../../tests/serviceAccounts.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the credential check and for account determination.
|
|
3
|
+
*
|
|
4
|
+
* The credential check runs a single curl call whose output is the response
|
|
5
|
+
* body followed by the HTTP status code on the final line (produced by
|
|
6
|
+
* `-w '\n%{http_code}'`). Account determination (`getAccount`) runs its own
|
|
7
|
+
* curl call against an identity-revealing endpoint and parses the account
|
|
8
|
+
* from the raw response body. These tests mock the async subprocess runner
|
|
9
|
+
* to feed service implementations recorded response bodies.
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
12
|
+
import { ApiCredentialStatus, AuthorizationBearer, OAuthCredentials, } from '../src/apiCredentials/base.js';
|
|
13
|
+
import { resetAsyncSubprocessRunner, setAsyncSubprocessRunner } from '../src/curl.js';
|
|
14
|
+
import { RegisteredService } from '../src/services/core/registered.js';
|
|
15
|
+
import { AWS } from '../src/services/aws.js';
|
|
16
|
+
import { CALENDLY } from '../src/services/calendly.js';
|
|
17
|
+
import { DISCORD } from '../src/services/discord.js';
|
|
18
|
+
import { DROPBOX } from '../src/services/dropbox.js';
|
|
19
|
+
import { FIGMA } from '../src/services/figma.js';
|
|
20
|
+
import { GITHUB } from '../src/services/github.js';
|
|
21
|
+
import { GITLAB } from '../src/services/gitlab.js';
|
|
22
|
+
import { GOOGLE_GMAIL } from '../src/services/google/gmail.js';
|
|
23
|
+
import { LINEAR } from '../src/services/linear.js';
|
|
24
|
+
import { MAILCHIMP } from '../src/services/mailchimp.js';
|
|
25
|
+
import { NOTION } from '../src/services/notion.js';
|
|
26
|
+
import { NOTION_MCP } from '../src/services/notion-mcp.js';
|
|
27
|
+
import { SENTRY } from '../src/services/sentry.js';
|
|
28
|
+
import { SLACK } from '../src/services/slack.js';
|
|
29
|
+
import { STRIPE } from '../src/services/stripe.js';
|
|
30
|
+
import { TELEGRAM } from '../src/services/telegram.js';
|
|
31
|
+
import { ZOOM } from '../src/services/zoom.js';
|
|
32
|
+
const BEARER = new AuthorizationBearer('test-token');
|
|
33
|
+
function mockCurlOutput(stdout) {
|
|
34
|
+
setAsyncSubprocessRunner(() => Promise.resolve({ returncode: 0, stdout: Buffer.from(stdout), stderr: '' }));
|
|
35
|
+
}
|
|
36
|
+
function withStatusLine(body, statusCode = '200') {
|
|
37
|
+
return `${body}\n${statusCode}`;
|
|
38
|
+
}
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
resetAsyncSubprocessRunner();
|
|
41
|
+
});
|
|
42
|
+
describe('base credential check', () => {
|
|
43
|
+
it('reports valid credentials on a 200 response', async () => {
|
|
44
|
+
mockCurlOutput(withStatusLine('{}'));
|
|
45
|
+
const status = await GITHUB.checkApiCredentials(BEARER);
|
|
46
|
+
expect(status).toBe(ApiCredentialStatus.Valid);
|
|
47
|
+
});
|
|
48
|
+
it('reports invalid credentials on non-200 responses', async () => {
|
|
49
|
+
mockCurlOutput(withStatusLine('{"message":"Bad credentials"}', '401'));
|
|
50
|
+
const status = await GITHUB.checkApiCredentials(BEARER);
|
|
51
|
+
expect(status).toBe(ApiCredentialStatus.Invalid);
|
|
52
|
+
});
|
|
53
|
+
it('reports missing credentials when injection fails', async () => {
|
|
54
|
+
const tokenlessCredentials = new OAuthCredentials('client-id', 'client-secret');
|
|
55
|
+
const status = await GITHUB.checkApiCredentials(tokenlessCredentials);
|
|
56
|
+
expect(status).toBe(ApiCredentialStatus.Missing);
|
|
57
|
+
});
|
|
58
|
+
it('reports unknown status for registered services without a request', async () => {
|
|
59
|
+
const registered = new RegisteredService('my-service', 'https://example.com/api/');
|
|
60
|
+
const status = await registered.checkApiCredentials();
|
|
61
|
+
expect(status).toBe(ApiCredentialStatus.Unknown);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('base account determination', () => {
|
|
65
|
+
it('returns null when the body carries no identity', async () => {
|
|
66
|
+
mockCurlOutput('{}');
|
|
67
|
+
const account = await GITHUB.getAccount(BEARER);
|
|
68
|
+
expect(account).toBeNull();
|
|
69
|
+
});
|
|
70
|
+
it('returns null when credential injection fails', async () => {
|
|
71
|
+
const tokenlessCredentials = new OAuthCredentials('client-id', 'client-secret');
|
|
72
|
+
const account = await GITHUB.getAccount(tokenlessCredentials);
|
|
73
|
+
expect(account).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
it('never crashes on a malformed body', async () => {
|
|
76
|
+
mockCurlOutput('this is not JSON');
|
|
77
|
+
const account = await GITHUB.getAccount(BEARER);
|
|
78
|
+
expect(account).toBeNull();
|
|
79
|
+
});
|
|
80
|
+
it('returns null for registered services without a request', async () => {
|
|
81
|
+
const registered = new RegisteredService('my-service', 'https://example.com/api/');
|
|
82
|
+
const account = await registered.getAccount();
|
|
83
|
+
expect(account).toBeNull();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('account parsing', () => {
|
|
87
|
+
it('github uses the login handle', async () => {
|
|
88
|
+
mockCurlOutput('{"login":"octocat","email":null}');
|
|
89
|
+
const account = await GITHUB.getAccount(BEARER);
|
|
90
|
+
expect(account).toBe('octocat');
|
|
91
|
+
});
|
|
92
|
+
it('gitlab uses the e-mail', async () => {
|
|
93
|
+
mockCurlOutput('{"username":"jane","email":"jane@example.com"}');
|
|
94
|
+
const account = await GITLAB.getAccount(BEARER);
|
|
95
|
+
expect(account).toBe('jane@example.com');
|
|
96
|
+
});
|
|
97
|
+
it('calendly uses the e-mail from the resource', async () => {
|
|
98
|
+
mockCurlOutput('{"resource":{"email":"host@example.com","name":"Host Person"}}');
|
|
99
|
+
const account = await CALENDLY.getAccount(BEARER);
|
|
100
|
+
expect(account).toBe('host@example.com');
|
|
101
|
+
});
|
|
102
|
+
it('figma uses the e-mail', async () => {
|
|
103
|
+
mockCurlOutput('{"email":"designer@example.com","handle":"Designer"}');
|
|
104
|
+
const account = await FIGMA.getAccount(BEARER);
|
|
105
|
+
expect(account).toBe('designer@example.com');
|
|
106
|
+
});
|
|
107
|
+
it('discord prefers the e-mail over the username', async () => {
|
|
108
|
+
mockCurlOutput('{"username":"gamer","email":"gamer@example.com","id":"1234"}');
|
|
109
|
+
const account = await DISCORD.getAccount(BEARER);
|
|
110
|
+
expect(account).toBe('gamer@example.com');
|
|
111
|
+
});
|
|
112
|
+
it('dropbox uses the e-mail from get_current_account', async () => {
|
|
113
|
+
mockCurlOutput('{"account_id":"dbid:abc","email":"user@example.com"}');
|
|
114
|
+
const account = await DROPBOX.getAccount(BEARER);
|
|
115
|
+
expect(account).toBe('user@example.com');
|
|
116
|
+
});
|
|
117
|
+
it('linear uses the viewer e-mail', async () => {
|
|
118
|
+
mockCurlOutput('{"data":{"viewer":{"id":"uuid-1","email":"dev@example.com"}}}');
|
|
119
|
+
const account = await LINEAR.getAccount(BEARER);
|
|
120
|
+
expect(account).toBe('dev@example.com');
|
|
121
|
+
});
|
|
122
|
+
it('mailchimp uses the login e-mail', async () => {
|
|
123
|
+
mockCurlOutput('{"accountname":"Acme","login":{"email":"marketer@example.com"}}');
|
|
124
|
+
const account = await MAILCHIMP.getAccount(BEARER);
|
|
125
|
+
expect(account).toBe('marketer@example.com');
|
|
126
|
+
});
|
|
127
|
+
it('notion combines the bot name and workspace', async () => {
|
|
128
|
+
mockCurlOutput('{"name":"My Integration","bot":{"workspace_name":"Acme Inc"}}');
|
|
129
|
+
const account = await NOTION.getAccount(BEARER);
|
|
130
|
+
expect(account).toBe('My Integration@Acme Inc');
|
|
131
|
+
});
|
|
132
|
+
it('telegram uses the bot username', async () => {
|
|
133
|
+
mockCurlOutput('{"ok":true,"result":{"id":42,"username":"my_bot"}}');
|
|
134
|
+
const account = await TELEGRAM.getAccount(BEARER);
|
|
135
|
+
expect(account).toBe('my_bot');
|
|
136
|
+
});
|
|
137
|
+
it('aws uses the caller ARN from the XML response', async () => {
|
|
138
|
+
mockCurlOutput('<GetCallerIdentityResponse><GetCallerIdentityResult>' +
|
|
139
|
+
'<Arn>arn:aws:iam::123456789012:user/alice</Arn>' +
|
|
140
|
+
'<UserId>AIDAEXAMPLE</UserId><Account>123456789012</Account>' +
|
|
141
|
+
'</GetCallerIdentityResult></GetCallerIdentityResponse>');
|
|
142
|
+
const account = await AWS.getAccount(BEARER);
|
|
143
|
+
expect(account).toBe('arn:aws:iam::123456789012:user/alice');
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe('slack', () => {
|
|
147
|
+
it('treats ok:false as invalid even though the HTTP status is 200', async () => {
|
|
148
|
+
mockCurlOutput(withStatusLine('{"ok":false,"error":"invalid_auth"}'));
|
|
149
|
+
const status = await SLACK.checkApiCredentials(BEARER);
|
|
150
|
+
expect(status).toBe(ApiCredentialStatus.Invalid);
|
|
151
|
+
});
|
|
152
|
+
it('treats ok:true as valid', async () => {
|
|
153
|
+
mockCurlOutput(withStatusLine('{"ok":true,"url":"https://acme.slack.com/","user":"jane"}'));
|
|
154
|
+
const status = await SLACK.checkApiCredentials(BEARER);
|
|
155
|
+
expect(status).toBe(ApiCredentialStatus.Valid);
|
|
156
|
+
});
|
|
157
|
+
it('combines the user and the workspace subdomain', async () => {
|
|
158
|
+
mockCurlOutput('{"ok":true,"url":"https://acme.slack.com/","team":"Acme Inc","user":"jane"}');
|
|
159
|
+
const account = await SLACK.getAccount(BEARER);
|
|
160
|
+
expect(account).toBe('jane@acme');
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe('sentry', () => {
|
|
164
|
+
it('requires the user field for validity', async () => {
|
|
165
|
+
mockCurlOutput(withStatusLine('{"user":null}'));
|
|
166
|
+
const status = await SENTRY.checkApiCredentials(BEARER);
|
|
167
|
+
expect(status).toBe(ApiCredentialStatus.Invalid);
|
|
168
|
+
});
|
|
169
|
+
it('uses the user e-mail as the account', async () => {
|
|
170
|
+
mockCurlOutput('{"user":{"email":"dev@example.com"}}');
|
|
171
|
+
const account = await SENTRY.getAccount(BEARER);
|
|
172
|
+
expect(account).toBe('dev@example.com');
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
describe('google', () => {
|
|
176
|
+
it('google services determine the account via the OpenID userinfo endpoint', async () => {
|
|
177
|
+
let requestedUrl;
|
|
178
|
+
setAsyncSubprocessRunner((args) => {
|
|
179
|
+
requestedUrl = args[args.length - 1];
|
|
180
|
+
return Promise.resolve({
|
|
181
|
+
returncode: 0,
|
|
182
|
+
stdout: Buffer.from('{"email":"user@gmail.com","sub":"1"}'),
|
|
183
|
+
stderr: '',
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
const credentials = new OAuthCredentials('client-id', 'client-secret', 'access-token');
|
|
187
|
+
const account = await GOOGLE_GMAIL.getAccount(credentials);
|
|
188
|
+
expect(account).toBe('user@gmail.com');
|
|
189
|
+
expect(requestedUrl).toBe('https://openidconnect.googleapis.com/v1/userinfo');
|
|
190
|
+
});
|
|
191
|
+
it('google services report token-less prepared credentials as missing', async () => {
|
|
192
|
+
const prepared = new OAuthCredentials('client-id', 'client-secret');
|
|
193
|
+
const status = await GOOGLE_GMAIL.checkApiCredentials(prepared);
|
|
194
|
+
expect(status).toBe(ApiCredentialStatus.Missing);
|
|
195
|
+
});
|
|
196
|
+
it('google services report tokens rejected by userinfo as invalid', async () => {
|
|
197
|
+
mockCurlOutput(withStatusLine('{"error":"invalid_token"}', '401'));
|
|
198
|
+
const credentials = new OAuthCredentials('client-id', 'client-secret', 'access-token');
|
|
199
|
+
const status = await GOOGLE_GMAIL.checkApiCredentials(credentials);
|
|
200
|
+
expect(status).toBe(ApiCredentialStatus.Invalid);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
describe('account determination via a separate endpoint', () => {
|
|
204
|
+
it('stripe asks the account endpoint and prefers the e-mail', async () => {
|
|
205
|
+
let requestedUrl;
|
|
206
|
+
setAsyncSubprocessRunner((args) => {
|
|
207
|
+
requestedUrl = args[args.length - 1];
|
|
208
|
+
return Promise.resolve({
|
|
209
|
+
returncode: 0,
|
|
210
|
+
stdout: Buffer.from('{"id":"acct_123","email":"owner@example.com"}'),
|
|
211
|
+
stderr: '',
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
const account = await STRIPE.getAccount(BEARER);
|
|
215
|
+
expect(account).toBe('owner@example.com');
|
|
216
|
+
expect(requestedUrl).toBe('https://api.stripe.com/v1/account');
|
|
217
|
+
});
|
|
218
|
+
it('stripe leaves the account undetermined when the key may not read it', async () => {
|
|
219
|
+
mockCurlOutput('{"error":{"type":"invalid_request_error"}}');
|
|
220
|
+
const account = await STRIPE.getAccount(BEARER);
|
|
221
|
+
expect(account).toBeNull();
|
|
222
|
+
});
|
|
223
|
+
it('zoom leaves the account undetermined for server-to-server tokens', async () => {
|
|
224
|
+
mockCurlOutput('{"code":124,"message":"Invalid access token."}');
|
|
225
|
+
const account = await ZOOM.getAccount(BEARER);
|
|
226
|
+
expect(account).toBeNull();
|
|
227
|
+
});
|
|
228
|
+
it('zoom uses the e-mail from /users/me', async () => {
|
|
229
|
+
mockCurlOutput('{"id":"abc","email":"host@example.com"}');
|
|
230
|
+
const account = await ZOOM.getAccount(BEARER);
|
|
231
|
+
expect(account).toBe('host@example.com');
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
describe('notion-mcp account determination via the get-users MCP tool', () => {
|
|
235
|
+
// SSE-framed response as actually returned by mcp.notion.com.
|
|
236
|
+
const recordedGetSelfResponse = 'event: message\n' +
|
|
237
|
+
'data: {"result":{"content":[{"type":"text","text":"{\\"results\\":[{\\"type\\":\\"person\\",\\"id\\":\\"uuid-1\\",\\"name\\":\\"Jane Doe\\",\\"email\\":\\"jane@example.com\\"}],\\"has_more\\":false}"}]},"jsonrpc":"2.0","id":2}\n';
|
|
238
|
+
it('resolves the e-mail via a single stateless tools/call', async () => {
|
|
239
|
+
let observedArguments = [];
|
|
240
|
+
setAsyncSubprocessRunner((args) => {
|
|
241
|
+
observedArguments = args;
|
|
242
|
+
return Promise.resolve({
|
|
243
|
+
returncode: 0,
|
|
244
|
+
stdout: Buffer.from(recordedGetSelfResponse),
|
|
245
|
+
stderr: '',
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
const account = await NOTION_MCP.getAccount(BEARER);
|
|
249
|
+
expect(account).toBe('jane@example.com');
|
|
250
|
+
expect(observedArguments[observedArguments.length - 1]).toBe('https://mcp.notion.com/mcp');
|
|
251
|
+
const payloadArgument = observedArguments[observedArguments.indexOf('-d') + 1] ?? '{}';
|
|
252
|
+
expect(JSON.parse(payloadArgument)).toMatchObject({
|
|
253
|
+
method: 'tools/call',
|
|
254
|
+
params: { name: 'notion-get-users', arguments: { user_id: 'self' } },
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
it('falls back to the name when the user has no e-mail (bots)', async () => {
|
|
258
|
+
const toolResultText = JSON.stringify({
|
|
259
|
+
results: [{ type: 'bot', id: 'uuid-2', name: 'My Bot' }],
|
|
260
|
+
has_more: false,
|
|
261
|
+
});
|
|
262
|
+
mockCurlOutput(JSON.stringify({ result: { content: [{ type: 'text', text: toolResultText }] }, id: 2 }));
|
|
263
|
+
const account = await NOTION_MCP.getAccount(BEARER);
|
|
264
|
+
expect(account).toBe('My Bot');
|
|
265
|
+
});
|
|
266
|
+
it('leaves the account undetermined on an error or malformed response', async () => {
|
|
267
|
+
mockCurlOutput('{"jsonrpc":"2.0","id":2,"error":{"code":-32600,"message":"unauthorized"}}');
|
|
268
|
+
expect(await NOTION_MCP.getAccount(BEARER)).toBeNull();
|
|
269
|
+
mockCurlOutput('not json at all');
|
|
270
|
+
expect(await NOTION_MCP.getAccount(BEARER)).toBeNull();
|
|
271
|
+
});
|
|
272
|
+
it('leaves the account undetermined for token-less prepared credentials', async () => {
|
|
273
|
+
const prepared = new OAuthCredentials('client-id', '');
|
|
274
|
+
const account = await NOTION_MCP.getAccount(prepared);
|
|
275
|
+
expect(account).toBeNull();
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
//# sourceMappingURL=serviceAccounts.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serviceAccounts.test.js","sourceRoot":"","sources":["../../tests/serviceAccounts.test.ts"],"names":[],"mappings":"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"}
|