fluxmail 0.4.1 → 0.6.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/README.md +6 -4
- package/dist/accounts/defaultGoogleOAuth.d.ts +4 -0
- package/dist/accounts/defaultGoogleOAuth.d.ts.map +1 -0
- package/dist/accounts/defaultGoogleOAuth.js +7 -0
- package/dist/accounts/defaultGoogleOAuth.js.map +1 -0
- package/dist/accounts/gmailConnection.js +2 -2
- package/dist/accounts/gmailConnection.js.map +1 -1
- package/dist/accounts/googleAuth.d.ts +16 -9
- package/dist/accounts/googleAuth.d.ts.map +1 -1
- package/dist/accounts/googleAuth.js +52 -20
- package/dist/accounts/googleAuth.js.map +1 -1
- package/dist/accounts/microsoftAuth.d.ts +5 -2
- package/dist/accounts/microsoftAuth.d.ts.map +1 -1
- package/dist/accounts/microsoftAuth.js +25 -22
- package/dist/accounts/microsoftAuth.js.map +1 -1
- package/dist/accounts/registry.d.ts +11 -9
- package/dist/accounts/registry.d.ts.map +1 -1
- package/dist/accounts/registry.js +169 -98
- package/dist/accounts/registry.js.map +1 -1
- package/dist/auth.d.ts +106 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +455 -0
- package/dist/auth.js.map +1 -0
- package/dist/authorization.d.ts +9 -0
- package/dist/authorization.d.ts.map +1 -0
- package/dist/authorization.js +23 -0
- package/dist/authorization.js.map +1 -0
- package/dist/cli.d.ts +15 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1096 -403
- package/dist/cli.js.map +1 -1
- package/dist/cliInstances.d.ts +51 -0
- package/dist/cliInstances.d.ts.map +1 -0
- package/dist/cliInstances.js +237 -0
- package/dist/cliInstances.js.map +1 -0
- package/dist/cliMail.d.ts +9 -0
- package/dist/cliMail.d.ts.map +1 -0
- package/dist/cliMail.js +450 -0
- package/dist/cliMail.js.map +1 -0
- package/dist/config.d.ts +95 -118
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +351 -286
- package/dist/config.js.map +1 -1
- package/dist/configMigration.d.ts +8 -0
- package/dist/configMigration.d.ts.map +1 -0
- package/dist/configMigration.js +234 -0
- package/dist/configMigration.js.map +1 -0
- package/dist/context.d.ts +8 -2
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +29 -8
- package/dist/context.js.map +1 -1
- package/dist/deploymentConfig.d.ts +190 -0
- package/dist/deploymentConfig.d.ts.map +1 -0
- package/dist/deploymentConfig.js +539 -0
- package/dist/deploymentConfig.js.map +1 -0
- package/dist/http/admin.d.ts +75 -3
- package/dist/http/admin.d.ts.map +1 -1
- package/dist/http/admin.js +347 -79
- package/dist/http/admin.js.map +1 -1
- package/dist/http/app.d.ts +4 -1
- package/dist/http/app.d.ts.map +1 -1
- package/dist/http/app.js +119 -63
- package/dist/http/app.js.map +1 -1
- package/dist/http/identity.d.ts +114 -0
- package/dist/http/identity.d.ts.map +1 -0
- package/dist/http/identity.js +936 -0
- package/dist/http/identity.js.map +1 -0
- package/dist/http/operationRoutes.d.ts +8 -0
- package/dist/http/operationRoutes.d.ts.map +1 -0
- package/dist/http/operationRoutes.js +13 -0
- package/dist/http/operationRoutes.js.map +1 -0
- package/dist/http/rest.d.ts +16 -4
- package/dist/http/rest.d.ts.map +1 -1
- package/dist/http/rest.js +213 -71
- package/dist/http/rest.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/instanceConfig.d.ts +36 -0
- package/dist/instanceConfig.d.ts.map +1 -0
- package/dist/instanceConfig.js +157 -0
- package/dist/instanceConfig.js.map +1 -0
- package/dist/licensing/activation.d.ts +2 -1
- package/dist/licensing/activation.d.ts.map +1 -1
- package/dist/licensing/activation.js +2 -3
- package/dist/licensing/activation.js.map +1 -1
- package/dist/licensing/entitlements.d.ts.map +1 -1
- package/dist/licensing/entitlements.js +2 -2
- package/dist/licensing/entitlements.js.map +1 -1
- package/dist/licensing/refresher.d.ts +6 -1
- package/dist/licensing/refresher.d.ts.map +1 -1
- package/dist/licensing/refresher.js +18 -7
- package/dist/licensing/refresher.js.map +1 -1
- package/dist/logging.d.ts +87 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +612 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp/buildServer.d.ts +3 -1
- package/dist/mcp/buildServer.d.ts.map +1 -1
- package/dist/mcp/buildServer.js +27 -24
- package/dist/mcp/buildServer.js.map +1 -1
- package/dist/permissions.d.ts +1 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +10 -4
- package/dist/permissions.js.map +1 -1
- package/dist/scheduler/sendScheduler.d.ts +4 -3
- package/dist/scheduler/sendScheduler.d.ts.map +1 -1
- package/dist/scheduler/sendScheduler.js +15 -3
- package/dist/scheduler/sendScheduler.js.map +1 -1
- package/dist/service/emailService.d.ts +10 -17
- package/dist/service/emailService.d.ts.map +1 -1
- package/dist/service/emailService.js +28 -38
- package/dist/service/emailService.js.map +1 -1
- package/dist/storage/adminAudit.d.ts +15 -2
- package/dist/storage/adminAudit.d.ts.map +1 -1
- package/dist/storage/adminAudit.js +22 -27
- package/dist/storage/adminAudit.js.map +1 -1
- package/dist/storage/apiKeys.d.ts +8 -8
- package/dist/storage/apiKeys.d.ts.map +1 -1
- package/dist/storage/apiKeys.js +16 -11
- package/dist/storage/apiKeys.js.map +1 -1
- package/dist/storage/db.d.ts +596 -31
- package/dist/storage/db.d.ts.map +1 -1
- package/dist/storage/db.js +383 -45
- package/dist/storage/db.js.map +1 -1
- package/dist/storage/fileLock.d.ts +7 -0
- package/dist/storage/fileLock.d.ts.map +1 -0
- package/dist/storage/fileLock.js +183 -0
- package/dist/storage/fileLock.js.map +1 -0
- package/dist/storage/gmailConnectionGrants.d.ts +3 -4
- package/dist/storage/gmailConnectionGrants.d.ts.map +1 -1
- package/dist/storage/gmailConnectionGrants.js +6 -6
- package/dist/storage/gmailConnectionGrants.js.map +1 -1
- package/dist/storage/members.d.ts +11 -0
- package/dist/storage/members.d.ts.map +1 -1
- package/dist/storage/members.js +70 -6
- package/dist/storage/members.js.map +1 -1
- package/dist/telemetry.d.ts +17 -2
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +34 -19
- package/dist/telemetry.js.map +1 -1
- package/dist/updateNotifier.d.ts +18 -0
- package/dist/updateNotifier.d.ts.map +1 -0
- package/dist/updateNotifier.js +128 -0
- package/dist/updateNotifier.js.map +1 -0
- package/package.json +38 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Fluxmail
|
|
2
2
|
|
|
3
|
-
Fluxmail is
|
|
3
|
+
Fluxmail is self-hosted email infrastructure for agents and apps. It connects to Gmail, Microsoft 365, Outlook.com, and IMAP/SMTP mailboxes. Agents use MCP, apps and backend workflows use the versioned REST API, and operators use the CLI to connect mailboxes, manage access, and run the service.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,15 +8,16 @@ Fluxmail requires Node.js 20.20.x, or Node.js 22.22 or later.
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install -g fluxmail
|
|
11
|
-
fluxmail
|
|
11
|
+
fluxmail setup --name "Your name" --email you@example.com
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
Then follow the [quickstart](https://fluxmail.ai/docs/quickstart) to connect a mailbox
|
|
14
|
+
Then follow the [quickstart](https://fluxmail.ai/docs/quickstart) to connect a mailbox and choose how you want to use Fluxmail: MCP, REST API, or CLI.
|
|
15
15
|
|
|
16
16
|
## Documentation
|
|
17
17
|
|
|
18
18
|
- [Overview](https://fluxmail.ai/docs/overview)
|
|
19
|
-
- [
|
|
19
|
+
- [MCP tools](https://fluxmail.ai/docs/tools)
|
|
20
|
+
- [Build with REST](https://fluxmail.ai/docs/build-with-rest)
|
|
20
21
|
- [REST API](https://fluxmail.ai/docs/rest-api)
|
|
21
22
|
- [Permissions](https://fluxmail.ai/docs/permissions)
|
|
22
23
|
- [Configuration](https://fluxmail.ai/docs/configuration)
|
|
@@ -24,6 +25,7 @@ Then follow the [quickstart](https://fluxmail.ai/docs/quickstart) to connect a m
|
|
|
24
25
|
- [Gmail setup](https://fluxmail.ai/docs/connect-gmail-to-mcp)
|
|
25
26
|
- [Outlook setup](https://fluxmail.ai/docs/connect-outlook-to-mcp)
|
|
26
27
|
- [IMAP setup](https://fluxmail.ai/docs/connect-an-imap-mailbox)
|
|
28
|
+
- [Authentication and instances](https://fluxmail.ai/docs/authentication-and-instances)
|
|
27
29
|
|
|
28
30
|
Fluxmail supports stdio for local MCP clients. Its HTTP server provides Streamable HTTP MCP and REST for local, Docker, and remote deployments. Use an exact package version instead of `@latest` when you need a reproducible installation.
|
|
29
31
|
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Fluxmail's public Desktop OAuth credentials for local CLI authorization. */
|
|
2
|
+
export declare const DEFAULT_GOOGLE_CLIENT_ID = "714401654473-is807s7srl0sk4g9fgsimu6mus3do9om.apps.googleusercontent.com";
|
|
3
|
+
export declare const DEFAULT_GOOGLE_CLIENT_SECRET = "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";
|
|
4
|
+
//# sourceMappingURL=defaultGoogleOAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultGoogleOAuth.d.ts","sourceRoot":"","sources":["../../src/accounts/defaultGoogleOAuth.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,6EAA6E,CAAC;AAKnH,eAAO,MAAM,4BAA4B,wCAAwC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Fluxmail's public Desktop OAuth credentials for local CLI authorization. */
|
|
2
|
+
export const DEFAULT_GOOGLE_CLIENT_ID = '714401654473-is807s7srl0sk4g9fgsimu6mus3do9om.apps.googleusercontent.com';
|
|
3
|
+
// This credential is intentionally checked in. An installed app cannot keep a
|
|
4
|
+
// client secret confidential, and Google documents embedding it in the app:
|
|
5
|
+
// https://developers.google.com/identity/protocols/oauth2#installed
|
|
6
|
+
export const DEFAULT_GOOGLE_CLIENT_SECRET = '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';
|
|
7
|
+
//# sourceMappingURL=defaultGoogleOAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultGoogleOAuth.js","sourceRoot":"","sources":["../../src/accounts/defaultGoogleOAuth.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,0EAA0E,CAAC;AAEnH,8EAA8E;AAC9E,4EAA4E;AAC5E,oEAAoE;AACpE,MAAM,CAAC,MAAM,4BAA4B,GAAG,qCAAqC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EmailError } from '@fluxmail/core';
|
|
2
2
|
import { createGmailConnectionGrant, createOutlookConnectionGrant, } from '../storage/gmailConnectionGrants.js';
|
|
3
|
-
import {
|
|
3
|
+
import { requireHostedGoogleConfig } from './googleAuth.js';
|
|
4
4
|
import { requireMicrosoftConfig } from './microsoftAuth.js';
|
|
5
5
|
function isLoopbackPublicUrl(publicUrl) {
|
|
6
6
|
const hostname = new URL(publicUrl).hostname;
|
|
@@ -23,7 +23,7 @@ export function selectGmailConnectionMode(config, options) {
|
|
|
23
23
|
: 'local';
|
|
24
24
|
}
|
|
25
25
|
export function prepareHostedGmailConnection(db, config, intent) {
|
|
26
|
-
|
|
26
|
+
requireHostedGoogleConfig(config);
|
|
27
27
|
const { token, expiresAt } = createGmailConnectionGrant(db, intent);
|
|
28
28
|
return {
|
|
29
29
|
connectionUrl: `${config.publicUrl}/auth/google/connect?token=${encodeURIComponent(token)}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gmailConnection.js","sourceRoot":"","sources":["../../src/accounts/gmailConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,GAE7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"gmailConnection.js","sourceRoot":"","sources":["../../src/accounts/gmailConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,GAE7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAI5D,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC;IAC7C,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,OAAO,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,QAAsC,EACtC,OAA8C;IAE9C,IAAI,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,6DAA6D,CAAC,CAAC;IACzG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,MAAsB,EACtB,OAA8C;IAE9C,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,+CAA+C,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAClD,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,kDAAkD,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,mBAAmB,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/G,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,OAAO,CAAC;AACd,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,EAAc,EACd,MAAsB,EACtB,MAA6B;IAE7B,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,0BAA0B,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACpE,OAAO;QACL,aAAa,EAAE,GAAG,MAAM,CAAC,SAAS,8BAA8B,kBAAkB,CAAC,KAAK,CAAC,EAAE;QAC3F,SAAS;KACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,EAAc,EACd,MAAsB,EACtB,MAA6B;IAE7B,MAAM,SAAS,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;QAC5B,MAAM,IAAI,UAAU,CAClB,iBAAiB,EACjB,gIAAgI,CACjI,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,4BAA4B,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACtE,OAAO;QACL,aAAa,EAAE,GAAG,MAAM,CAAC,SAAS,iCAAiC,kBAAkB,CAAC,KAAK,CAAC,EAAE;QAC9F,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { OAuth2Client, type Credentials } from 'google-auth-library';
|
|
2
2
|
import type { FluxmailConfig } from '../config.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* allows with https://mail.google.com/ (gmail.modify cannot call messages.delete).
|
|
6
|
-
* Users bring their own OAuth app, so they are consenting to their own credentials.
|
|
7
|
-
*/
|
|
3
|
+
import type { StoredGoogleOAuthApp } from '../instanceConfig.js';
|
|
4
|
+
/** The built-in app uses Fluxmail's approved Gmail permission. */
|
|
8
5
|
export declare const GMAIL_SCOPES: string[];
|
|
6
|
+
/** Custom OAuth apps retain full Gmail support, including permanent deletion. */
|
|
7
|
+
export declare const CUSTOM_GMAIL_SCOPES: string[];
|
|
9
8
|
export declare function requireGoogleConfig(config: FluxmailConfig): {
|
|
10
9
|
clientId: string;
|
|
11
10
|
clientSecret: string;
|
|
12
11
|
};
|
|
13
|
-
export declare function
|
|
14
|
-
|
|
12
|
+
export declare function requireHostedGoogleConfig(config: FluxmailConfig): {
|
|
13
|
+
clientId: string;
|
|
14
|
+
clientSecret: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function createOAuthClient(config: FluxmailConfig, redirectUri: string, oauthClient?: StoredGoogleOAuthApp): OAuth2Client;
|
|
17
|
+
export declare function gmailScopes(config: FluxmailConfig, oauthClient?: StoredGoogleOAuthApp): string[];
|
|
18
|
+
export declare function buildAuthUrl(client: OAuth2Client, state: string, scopes: string[], codeChallenge?: string): string;
|
|
15
19
|
/** Verify the OAuth id_token and extract the authenticated Google identity. */
|
|
16
20
|
export declare function identityFromIdToken(client: OAuth2Client, tokens: Credentials): Promise<{
|
|
17
21
|
email: string;
|
|
@@ -22,10 +26,13 @@ export interface OAuthResult {
|
|
|
22
26
|
displayName?: string;
|
|
23
27
|
tokens: Credentials;
|
|
24
28
|
}
|
|
25
|
-
export
|
|
29
|
+
export interface AuthorizedOAuthResult extends OAuthResult {
|
|
30
|
+
oauthClient: StoredGoogleOAuthApp;
|
|
31
|
+
}
|
|
32
|
+
export declare function exchangeCode(client: OAuth2Client, code: string, codeVerifier?: string): Promise<OAuthResult>;
|
|
26
33
|
/**
|
|
27
34
|
* Loopback OAuth flow for the CLI: listens once on config.oauthPort, prints the
|
|
28
35
|
* consent URL, and resolves when Google redirects back with a code.
|
|
29
36
|
*/
|
|
30
|
-
export declare function runLoopbackFlow<T =
|
|
37
|
+
export declare function runLoopbackFlow<T = AuthorizedOAuthResult>(config: FluxmailConfig, onAuthUrl: (url: string) => void, onAuthorized?: (result: AuthorizedOAuthResult) => T | Promise<T>): Promise<T>;
|
|
31
38
|
//# sourceMappingURL=googleAuth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"googleAuth.d.ts","sourceRoot":"","sources":["../../src/accounts/googleAuth.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"googleAuth.d.ts","sourceRoot":"","sources":["../../src/accounts/googleAuth.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAKjE,kEAAkE;AAClE,eAAO,MAAM,YAAY,UAA8E,CAAC;AAExG,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,UAA0D,CAAC;AAE3F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAQtG;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,cAAc,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAS5G;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,oBAAkD,GAC9D,YAAY,CAGd;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,cAAc,EACtB,WAAW,GAAE,oBAAkD,GAC9D,MAAM,EAAE,CAEV;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAQlH;AAED,+EAA+E;AAC/E,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAYlD;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,qBAAsB,SAAQ,WAAW;IACxD,WAAW,EAAE,oBAAoB,CAAC;CACnC;AAoDD,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAelH;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,CAAC,GAAG,qBAAqB,EAC7D,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAChC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAC/D,OAAO,CAAC,CAAC,CAAC,CA8DZ"}
|
|
@@ -1,30 +1,40 @@
|
|
|
1
1
|
import { createServer } from 'node:http';
|
|
2
2
|
import { randomBytes } from 'node:crypto';
|
|
3
|
-
import { OAuth2Client } from 'google-auth-library';
|
|
3
|
+
import { CodeChallengeMethod, OAuth2Client } from 'google-auth-library';
|
|
4
4
|
import { EmailError } from '@fluxmail/core';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*/
|
|
10
|
-
export const
|
|
5
|
+
import { DEFAULT_GOOGLE_CLIENT_ID } from './defaultGoogleOAuth.js';
|
|
6
|
+
const GOOGLE_IDENTITY_SCOPES = ['openid', 'email', 'profile'];
|
|
7
|
+
/** The built-in app uses Fluxmail's approved Gmail permission. */
|
|
8
|
+
export const GMAIL_SCOPES = ['https://www.googleapis.com/auth/gmail.modify', ...GOOGLE_IDENTITY_SCOPES];
|
|
9
|
+
/** Custom OAuth apps retain full Gmail support, including permanent deletion. */
|
|
10
|
+
export const CUSTOM_GMAIL_SCOPES = ['https://mail.google.com/', ...GOOGLE_IDENTITY_SCOPES];
|
|
11
11
|
export function requireGoogleConfig(config) {
|
|
12
12
|
if (!config.google) {
|
|
13
|
-
throw new EmailError('invalid_request', '
|
|
14
|
-
'(see README "Google setup") and set both environment variables.');
|
|
13
|
+
throw new EmailError('invalid_request', 'Google OAuth is not configured. Set GOOGLE_CLIENT_ID to use a custom OAuth app.');
|
|
15
14
|
}
|
|
16
15
|
return config.google;
|
|
17
16
|
}
|
|
18
|
-
export function
|
|
19
|
-
const
|
|
17
|
+
export function requireHostedGoogleConfig(config) {
|
|
18
|
+
const google = requireGoogleConfig(config);
|
|
19
|
+
if (google.clientId === DEFAULT_GOOGLE_CLIENT_ID || !google.clientSecret) {
|
|
20
|
+
throw new EmailError('invalid_request', 'Hosted Gmail connections require a custom Google Web application. Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.');
|
|
21
|
+
}
|
|
22
|
+
return { clientId: google.clientId, clientSecret: google.clientSecret };
|
|
23
|
+
}
|
|
24
|
+
export function createOAuthClient(config, redirectUri, oauthClient = requireGoogleConfig(config)) {
|
|
25
|
+
const { clientId, clientSecret } = oauthClient;
|
|
20
26
|
return new OAuth2Client({ clientId, clientSecret, redirectUri });
|
|
21
27
|
}
|
|
22
|
-
export function
|
|
28
|
+
export function gmailScopes(config, oauthClient = requireGoogleConfig(config)) {
|
|
29
|
+
return oauthClient.clientId === DEFAULT_GOOGLE_CLIENT_ID ? GMAIL_SCOPES : CUSTOM_GMAIL_SCOPES;
|
|
30
|
+
}
|
|
31
|
+
export function buildAuthUrl(client, state, scopes, codeChallenge) {
|
|
23
32
|
return client.generateAuthUrl({
|
|
24
33
|
access_type: 'offline',
|
|
25
34
|
prompt: 'consent',
|
|
26
|
-
scope:
|
|
35
|
+
scope: scopes,
|
|
27
36
|
state,
|
|
37
|
+
...(codeChallenge ? { code_challenge: codeChallenge, code_challenge_method: CodeChallengeMethod.S256 } : {}),
|
|
28
38
|
});
|
|
29
39
|
}
|
|
30
40
|
/** Verify the OAuth id_token and extract the authenticated Google identity. */
|
|
@@ -45,13 +55,27 @@ export async function identityFromIdToken(client, tokens) {
|
|
|
45
55
|
}
|
|
46
56
|
return { email: claims.email, ...(claims.name ? { displayName: claims.name } : {}) };
|
|
47
57
|
}
|
|
58
|
+
function oauthErrorText(value) {
|
|
59
|
+
if (typeof value !== 'string')
|
|
60
|
+
return undefined;
|
|
61
|
+
const text = value.replace(/\s+/g, ' ').trim();
|
|
62
|
+
return text ? text.slice(0, 300) : undefined;
|
|
63
|
+
}
|
|
64
|
+
function googleTokenError(err) {
|
|
65
|
+
const data = err?.response?.data;
|
|
66
|
+
const payload = data && typeof data === 'object' ? data : undefined;
|
|
67
|
+
const code = oauthErrorText(payload?.error);
|
|
68
|
+
const description = oauthErrorText(payload?.error_description);
|
|
69
|
+
const detail = description ?? code ?? oauthErrorText(err instanceof Error ? err.message : undefined) ?? 'unknown error';
|
|
70
|
+
return new EmailError('provider_unavailable', `Google OAuth token exchange failed: ${detail}`);
|
|
71
|
+
}
|
|
48
72
|
function oauthListenerError(err, port) {
|
|
49
73
|
const code = err.code;
|
|
50
74
|
if (code !== 'EADDRINUSE')
|
|
51
75
|
return err;
|
|
52
76
|
return new Error(`OAuth callback port ${port} is already in use.\n\n` +
|
|
53
77
|
'If Fluxmail is already running with Docker Compose, connect the account inside the container:\n\n' +
|
|
54
|
-
' docker compose exec fluxmail fluxmail accounts add gmail
|
|
78
|
+
' docker compose exec fluxmail fluxmail accounts add gmail\n\n' +
|
|
55
79
|
`Otherwise, stop the process using port ${port} and try again.`, { cause: err });
|
|
56
80
|
}
|
|
57
81
|
function escapeHtml(value) {
|
|
@@ -71,8 +95,14 @@ function callbackPage(title, message) {
|
|
|
71
95
|
`<h2>${escapeHtml(title)}</h2><p>${escapeHtml(message)}</p>` +
|
|
72
96
|
'<p>You can close this tab and return to the terminal.</p></body></html>');
|
|
73
97
|
}
|
|
74
|
-
export async function exchangeCode(client, code) {
|
|
75
|
-
|
|
98
|
+
export async function exchangeCode(client, code, codeVerifier) {
|
|
99
|
+
let tokens;
|
|
100
|
+
try {
|
|
101
|
+
({ tokens } = await client.getToken({ code, ...(codeVerifier ? { codeVerifier } : {}) }));
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
throw googleTokenError(err);
|
|
105
|
+
}
|
|
76
106
|
if (!tokens.refresh_token) {
|
|
77
107
|
throw new EmailError('invalid_request', "Google did not return a refresh token. Remove Fluxmail from the account's third-party access " +
|
|
78
108
|
'(myaccount.google.com/permissions) and try again.');
|
|
@@ -84,8 +114,10 @@ export async function exchangeCode(client, code) {
|
|
|
84
114
|
* consent URL, and resolves when Google redirects back with a code.
|
|
85
115
|
*/
|
|
86
116
|
export async function runLoopbackFlow(config, onAuthUrl, onAuthorized) {
|
|
87
|
-
const
|
|
88
|
-
const
|
|
117
|
+
const oauthClient = { ...requireGoogleConfig(config) };
|
|
118
|
+
const redirectUri = `http://127.0.0.1:${config.oauthPort}/oauth/callback`;
|
|
119
|
+
const client = createOAuthClient(config, redirectUri, oauthClient);
|
|
120
|
+
const { codeVerifier, codeChallenge } = await client.generateCodeVerifierAsync();
|
|
89
121
|
const state = randomBytes(16).toString('hex');
|
|
90
122
|
return new Promise((resolve, reject) => {
|
|
91
123
|
const server = createServer(async (req, res) => {
|
|
@@ -120,7 +152,7 @@ export async function runLoopbackFlow(config, onAuthUrl, onAuthorized) {
|
|
|
120
152
|
res.writeHead(400).end('Missing code parameter.');
|
|
121
153
|
return;
|
|
122
154
|
}
|
|
123
|
-
const result = await exchangeCode(client, code);
|
|
155
|
+
const result = { ...(await exchangeCode(client, code, codeVerifier)), oauthClient };
|
|
124
156
|
const accepted = onAuthorized ? await onAuthorized(result) : result;
|
|
125
157
|
finish(() => resolve(accepted));
|
|
126
158
|
res
|
|
@@ -140,7 +172,7 @@ export async function runLoopbackFlow(config, onAuthUrl, onAuthorized) {
|
|
|
140
172
|
});
|
|
141
173
|
server.on('error', (err) => reject(oauthListenerError(err, config.oauthPort)));
|
|
142
174
|
server.listen(config.oauthPort, config.oauthHost, () => {
|
|
143
|
-
onAuthUrl(buildAuthUrl(client, state));
|
|
175
|
+
onAuthUrl(buildAuthUrl(client, state, gmailScopes(config, oauthClient), codeChallenge));
|
|
144
176
|
});
|
|
145
177
|
});
|
|
146
178
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"googleAuth.js","sourceRoot":"","sources":["../../src/accounts/googleAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAoB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"googleAuth.js","sourceRoot":"","sources":["../../src/accounts/googleAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAoB,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,MAAM,sBAAsB,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;AAE9D,kEAAkE;AAClE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,8CAA8C,EAAE,GAAG,sBAAsB,CAAC,CAAC;AAExG,iFAAiF;AACjF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,0BAA0B,EAAE,GAAG,sBAAsB,CAAC,CAAC;AAE3F,MAAM,UAAU,mBAAmB,CAAC,MAAsB;IACxD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,UAAU,CAClB,iBAAiB,EACjB,iFAAiF,CAClF,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAsB;IAC9D,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,MAAM,CAAC,QAAQ,KAAK,wBAAwB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACzE,MAAM,IAAI,UAAU,CAClB,iBAAiB,EACjB,kHAAkH,CACnH,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAsB,EACtB,WAAmB,EACnB,cAAoC,mBAAmB,CAAC,MAAM,CAAC;IAE/D,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,WAAW,CAAC;IAC/C,OAAO,IAAI,YAAY,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,MAAsB,EACtB,cAAoC,mBAAmB,CAAC,MAAM,CAAC;IAE/D,OAAO,WAAW,CAAC,QAAQ,KAAK,wBAAwB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC;AAChG,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAoB,EAAE,KAAa,EAAE,MAAgB,EAAE,aAAsB;IACxG,OAAO,MAAM,CAAC,eAAe,CAAC;QAC5B,WAAW,EAAE,SAAS;QACtB,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,MAAM;QACb,KAAK;QACL,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,aAAa,EAAE,qBAAqB,EAAE,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7G,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAoB,EACpB,MAAmB;IAEnB,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;IAChC,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,mCAAmC,CAAC,CAAC;IAChG,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,sCAAsC,CAAC,CAAC;IAC5G,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACnC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,+BAA+B,CAAC,CAAC;IAC3F,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,oCAAoC,CAAC,CAAC;IACtG,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,iDAAiD,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACvF,CAAC;AAYD,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAY;IACpC,MAAM,IAAI,GAAI,GAAqD,EAAE,QAAQ,EAAE,IAAI,CAAC;IACpF,MAAM,OAAO,GAAG,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAgC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjG,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IAC/D,MAAM,MAAM,GACV,WAAW,IAAI,IAAI,IAAI,cAAc,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC;IAC3G,OAAO,IAAI,UAAU,CAAC,sBAAsB,EAAE,uCAAuC,MAAM,EAAE,CAAC,CAAC;AACjG,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAU,EAAE,IAAY;IAClD,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;IACjD,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,GAAG,CAAC;IAEtC,OAAO,IAAI,KAAK,CACd,uBAAuB,IAAI,yBAAyB;QAClD,mGAAmG;QACnG,gEAAgE;QAChE,0CAA0C,IAAI,iBAAiB,EACjE,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;QACxC,MAAM,QAAQ,GAA2B;YACvC,GAAG,EAAE,OAAO;YACZ,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,QAAQ;YACb,GAAG,EAAE,OAAO;SACb,CAAC;QACF,OAAO,QAAQ,CAAC,IAAI,CAAE,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,OAAe;IAClD,OAAO,CACL,8CAA8C;QAC9C,OAAO,UAAU,CAAC,KAAK,CAAC,WAAW,UAAU,CAAC,OAAO,CAAC,MAAM;QAC5D,yEAAyE,CAC1E,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAoB,EAAE,IAAY,EAAE,YAAqB;IAC1F,IAAI,MAAmB,CAAC;IACxB,IAAI,CAAC;QACH,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5F,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAClB,iBAAiB,EACjB,+FAA+F;YAC7F,mDAAmD,CACtD,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,GAAG,CAAC,MAAM,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAsB,EACtB,SAAgC,EAChC,YAAgE;IAEhE,MAAM,WAAW,GAAG,EAAE,GAAG,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;IACvD,MAAM,WAAW,GAAG,oBAAoB,MAAM,CAAC,SAAS,iBAAiB,CAAC;IAC1E,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IACnE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,EAAE,CAAC;IACjF,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9C,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YAC7C,2EAA2E;YAC3E,uEAAuE;YACvE,uBAAuB;YACvB,MAAM,MAAM,GAAG,CAAC,MAAkB,EAAE,EAAE;gBACpC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;oBACrB,MAAM,CAAC,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,mBAAmB,EAAE,CAAC;oBAC7B,MAAM,EAAE,CAAC;gBACX,CAAC,CAAC,CAAC;YACL,CAAC,CAAC;YACF,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,WAAW,CAAC,CAAC;gBACjD,IAAI,GAAG,CAAC,QAAQ,KAAK,iBAAiB,EAAE,CAAC;oBACvC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;oBACpC,OAAO;gBACT,CAAC;gBACD,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,EAAE,CAAC;oBAC5C,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;oBAC5D,OAAO;gBACT,CAAC;gBACD,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC5C,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,iBAAiB,EAAE,uBAAuB,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;oBACxF,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,6BAA6B,KAAK,2BAA2B,CAAC,CAAC;oBACtF,OAAO;gBACT,CAAC;gBACD,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC1C,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;oBAClD,OAAO;gBACT,CAAC;gBACD,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,MAAM,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;gBACpF,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAY,CAAC;gBAC3E,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAChC,GAAG;qBACA,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC;qBAC9D,GAAG,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,KAAK,2BAA2B,EAAE,8BAA8B,CAAC,CAAC,CAAC;YACnG,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC1B,MAAM,QAAQ,GAAG,GAAG,YAAY,UAAU,CAAC;gBAC3C,MAAM,OAAO,GAAG,QAAQ;oBACtB,CAAC,CAAC,GAAG,CAAC,OAAO;oBACb,CAAC,CAAC,oFAAoF,CAAC;gBACzF,GAAG;qBACA,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC;qBAC/E,GAAG,CAAC,YAAY,CAAC,yCAAyC,EAAE,OAAO,CAAC,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC/E,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE;YACrD,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FluxmailConfig } from '../config.js';
|
|
2
|
+
import type { StoredMicrosoftOAuthApp } from '../instanceConfig.js';
|
|
2
3
|
export declare const MICROSOFT_SCOPES: string[];
|
|
3
4
|
export interface MicrosoftCredentials {
|
|
4
5
|
accessToken: string;
|
|
@@ -7,6 +8,8 @@ export interface MicrosoftCredentials {
|
|
|
7
8
|
scope?: string;
|
|
8
9
|
/** Hosted callbacks use a confidential client; loopback callbacks use PKCE only. */
|
|
9
10
|
clientAuth?: 'public' | 'confidential';
|
|
11
|
+
/** OAuth application that issued the refresh token. */
|
|
12
|
+
fluxmailOAuthClient?: StoredMicrosoftOAuthApp;
|
|
10
13
|
}
|
|
11
14
|
export interface MicrosoftOAuthResult {
|
|
12
15
|
email: string;
|
|
@@ -14,8 +17,8 @@ export interface MicrosoftOAuthResult {
|
|
|
14
17
|
credentials: MicrosoftCredentials;
|
|
15
18
|
}
|
|
16
19
|
export declare function requireMicrosoftConfig(config: FluxmailConfig): NonNullable<FluxmailConfig['microsoft']>;
|
|
17
|
-
export declare function buildMicrosoftAuthUrl(config: FluxmailConfig, redirectUri: string, state: string, verifier: string): string;
|
|
20
|
+
export declare function buildMicrosoftAuthUrl(config: FluxmailConfig, redirectUri: string, state: string, verifier: string, oauthClient?: StoredMicrosoftOAuthApp): string;
|
|
18
21
|
export declare function refreshMicrosoftCredentials(config: FluxmailConfig, credentials: MicrosoftCredentials): Promise<MicrosoftCredentials>;
|
|
19
|
-
export declare function exchangeMicrosoftCode(config: FluxmailConfig, code: string, redirectUri: string, verifier: string, clientAuth?: 'public' | 'confidential'): Promise<MicrosoftOAuthResult>;
|
|
22
|
+
export declare function exchangeMicrosoftCode(config: FluxmailConfig, code: string, redirectUri: string, verifier: string, clientAuth?: 'public' | 'confidential', oauthClient?: StoredMicrosoftOAuthApp): Promise<MicrosoftOAuthResult>;
|
|
20
23
|
export declare function runMicrosoftLoopbackFlow<T = MicrosoftOAuthResult>(config: FluxmailConfig, onAuthUrl: (url: string) => void, onAuthorized?: (result: MicrosoftOAuthResult) => T | Promise<T>): Promise<T>;
|
|
21
24
|
//# sourceMappingURL=microsoftAuth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microsoftAuth.d.ts","sourceRoot":"","sources":["../../src/accounts/microsoftAuth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"microsoftAuth.d.ts","sourceRoot":"","sources":["../../src/accounts/microsoftAuth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,eAAO,MAAM,gBAAgB,UAS5B,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,UAAU,CAAC,EAAE,QAAQ,GAAG,cAAc,CAAC;IACvC,uDAAuD;IACvD,mBAAmB,CAAC,EAAE,uBAAuB,CAAC;CAC/C;AAWD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,oBAAoB,CAAC;CACnC;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAQvG;AAUD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,uBAAwD,GACpE,MAAM,CAeR;AAqDD,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,oBAAoB,GAChC,OAAO,CAAC,oBAAoB,CAAC,CAc/B;AA+CD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,GAAE,QAAQ,GAAG,cAAyB,EAChD,WAAW,GAAE,uBAAwD,GACpE,OAAO,CAAC,oBAAoB,CAAC,CAiB/B;AAkCD,wBAAsB,wBAAwB,CAAC,CAAC,GAAG,oBAAoB,EACrE,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAChC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAC9D,OAAO,CAAC,CAAC,CAAC,CA2DZ"}
|
|
@@ -9,6 +9,7 @@ export const MICROSOFT_SCOPES = [
|
|
|
9
9
|
'User.Read',
|
|
10
10
|
'Mail.ReadWrite',
|
|
11
11
|
'Mail.Send',
|
|
12
|
+
'MailboxSettings.Read',
|
|
12
13
|
];
|
|
13
14
|
export function requireMicrosoftConfig(config) {
|
|
14
15
|
if (!config.microsoft) {
|
|
@@ -16,18 +17,17 @@ export function requireMicrosoftConfig(config) {
|
|
|
16
17
|
}
|
|
17
18
|
return config.microsoft;
|
|
18
19
|
}
|
|
19
|
-
function tenantEndpoint(
|
|
20
|
-
|
|
21
|
-
return `https://login.microsoftonline.com/${encodeURIComponent(tenantId)}/oauth2/v2.0/${path}`;
|
|
20
|
+
function tenantEndpoint(microsoft, path) {
|
|
21
|
+
return `https://login.microsoftonline.com/${encodeURIComponent(microsoft.tenantId)}/oauth2/v2.0/${path}`;
|
|
22
22
|
}
|
|
23
23
|
function codeChallenge(verifier) {
|
|
24
24
|
return createHash('sha256').update(verifier).digest('base64url');
|
|
25
25
|
}
|
|
26
|
-
export function buildMicrosoftAuthUrl(config, redirectUri, state, verifier) {
|
|
27
|
-
const
|
|
28
|
-
const url = new URL(tenantEndpoint(
|
|
26
|
+
export function buildMicrosoftAuthUrl(config, redirectUri, state, verifier, oauthClient = requireMicrosoftConfig(config)) {
|
|
27
|
+
const microsoft = oauthClient;
|
|
28
|
+
const url = new URL(tenantEndpoint(microsoft, 'authorize'));
|
|
29
29
|
url.search = new URLSearchParams({
|
|
30
|
-
client_id: clientId,
|
|
30
|
+
client_id: microsoft.clientId,
|
|
31
31
|
response_type: 'code',
|
|
32
32
|
redirect_uri: redirectUri,
|
|
33
33
|
response_mode: 'query',
|
|
@@ -39,8 +39,7 @@ export function buildMicrosoftAuthUrl(config, redirectUri, state, verifier) {
|
|
|
39
39
|
}).toString();
|
|
40
40
|
return url.toString();
|
|
41
41
|
}
|
|
42
|
-
async function tokenRequest(
|
|
43
|
-
const microsoft = requireMicrosoftConfig(config);
|
|
42
|
+
async function tokenRequest(microsoft, params, clientAuth) {
|
|
44
43
|
if (clientAuth === 'confidential' && !microsoft.clientSecret) {
|
|
45
44
|
throw new EmailError('invalid_request', 'MICROSOFT_CLIENT_SECRET is required for hosted Outlook connections.');
|
|
46
45
|
}
|
|
@@ -49,7 +48,7 @@ async function tokenRequest(config, params, clientAuth) {
|
|
|
49
48
|
...params,
|
|
50
49
|
...(clientAuth === 'confidential' ? { client_secret: microsoft.clientSecret } : {}),
|
|
51
50
|
});
|
|
52
|
-
const response = await fetch(tenantEndpoint(
|
|
51
|
+
const response = await fetch(tenantEndpoint(microsoft, 'token'), {
|
|
53
52
|
method: 'POST',
|
|
54
53
|
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
55
54
|
body,
|
|
@@ -62,7 +61,7 @@ async function tokenRequest(config, params, clientAuth) {
|
|
|
62
61
|
}
|
|
63
62
|
return payload;
|
|
64
63
|
}
|
|
65
|
-
function credentialsFromToken(payload, clientAuth, previousRefreshToken) {
|
|
64
|
+
function credentialsFromToken(payload, clientAuth, microsoft, previousRefreshToken) {
|
|
66
65
|
if (!payload.access_token)
|
|
67
66
|
throw new EmailError('provider_unavailable', 'Microsoft did not return an access token');
|
|
68
67
|
const refreshToken = payload.refresh_token ?? previousRefreshToken;
|
|
@@ -74,17 +73,20 @@ function credentialsFromToken(payload, clientAuth, previousRefreshToken) {
|
|
|
74
73
|
refreshToken,
|
|
75
74
|
expiresAt: Date.now() + Math.max(payload.expires_in ?? 3_600, 60) * 1_000,
|
|
76
75
|
clientAuth,
|
|
76
|
+
fluxmailOAuthClient: { ...microsoft },
|
|
77
77
|
...(payload.scope ? { scope: payload.scope } : {}),
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
export async function refreshMicrosoftCredentials(config, credentials) {
|
|
81
|
-
const
|
|
82
|
-
const
|
|
81
|
+
const microsoft = credentials.fluxmailOAuthClient ?? requireMicrosoftConfig(config);
|
|
82
|
+
const clientAuth = credentials.clientAuth ?? (microsoft.clientSecret ? 'confidential' : 'public');
|
|
83
|
+
const refreshScope = credentials.scope?.trim();
|
|
84
|
+
const payload = await tokenRequest(microsoft, {
|
|
83
85
|
grant_type: 'refresh_token',
|
|
84
86
|
refresh_token: credentials.refreshToken,
|
|
85
|
-
scope:
|
|
87
|
+
...(refreshScope ? { scope: refreshScope } : {}),
|
|
86
88
|
}, clientAuth);
|
|
87
|
-
return credentialsFromToken(payload, clientAuth, credentials.refreshToken);
|
|
89
|
+
return credentialsFromToken(payload, clientAuth, microsoft, credentials.refreshToken);
|
|
88
90
|
}
|
|
89
91
|
async function microsoftIdentity(accessToken) {
|
|
90
92
|
const response = await fetch('https://graph.microsoft.com/v1.0/me?$select=mail,userPrincipalName,displayName', {
|
|
@@ -119,15 +121,16 @@ async function verifyMicrosoftMailbox(accessToken) {
|
|
|
119
121
|
throw new EmailError('provider_unavailable', "Microsoft Graph could not access this account's mailbox");
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
|
-
export async function exchangeMicrosoftCode(config, code, redirectUri, verifier, clientAuth = 'public') {
|
|
123
|
-
const
|
|
124
|
+
export async function exchangeMicrosoftCode(config, code, redirectUri, verifier, clientAuth = 'public', oauthClient = requireMicrosoftConfig(config)) {
|
|
125
|
+
const microsoft = { ...oauthClient };
|
|
126
|
+
const payload = await tokenRequest(microsoft, {
|
|
124
127
|
grant_type: 'authorization_code',
|
|
125
128
|
code,
|
|
126
129
|
redirect_uri: redirectUri,
|
|
127
130
|
code_verifier: verifier,
|
|
128
131
|
scope: MICROSOFT_SCOPES.join(' '),
|
|
129
132
|
}, clientAuth);
|
|
130
|
-
const credentials = credentialsFromToken(payload, clientAuth);
|
|
133
|
+
const credentials = credentialsFromToken(payload, clientAuth, microsoft);
|
|
131
134
|
const identity = await microsoftIdentity(credentials.accessToken);
|
|
132
135
|
await verifyMicrosoftMailbox(credentials.accessToken);
|
|
133
136
|
return { ...identity, credentials };
|
|
@@ -154,11 +157,11 @@ function listenerError(error, port) {
|
|
|
154
157
|
return error;
|
|
155
158
|
return new Error(`OAuth callback port ${port} is already in use.\n\n` +
|
|
156
159
|
'If Fluxmail is running with Docker Compose, connect the account inside the container:\n\n' +
|
|
157
|
-
' docker compose exec fluxmail fluxmail accounts add outlook
|
|
160
|
+
' docker compose exec fluxmail fluxmail accounts add outlook\n\n' +
|
|
158
161
|
`Otherwise, stop the process using port ${port} and try again.`, { cause: error });
|
|
159
162
|
}
|
|
160
163
|
export async function runMicrosoftLoopbackFlow(config, onAuthUrl, onAuthorized) {
|
|
161
|
-
requireMicrosoftConfig(config);
|
|
164
|
+
const oauthClient = { ...requireMicrosoftConfig(config) };
|
|
162
165
|
const redirectUri = `http://localhost:${config.oauthPort}/oauth/microsoft/callback`;
|
|
163
166
|
const state = randomBytes(16).toString('hex');
|
|
164
167
|
const verifier = randomBytes(48).toString('base64url');
|
|
@@ -193,7 +196,7 @@ export async function runMicrosoftLoopbackFlow(config, onAuthUrl, onAuthorized)
|
|
|
193
196
|
response.writeHead(400).end('Missing code parameter.');
|
|
194
197
|
return;
|
|
195
198
|
}
|
|
196
|
-
const result = await exchangeMicrosoftCode(config, code, redirectUri, verifier);
|
|
199
|
+
const result = await exchangeMicrosoftCode(config, code, redirectUri, verifier, 'public', oauthClient);
|
|
197
200
|
const accepted = onAuthorized ? await onAuthorized(result) : result;
|
|
198
201
|
finish(() => resolve(accepted));
|
|
199
202
|
response
|
|
@@ -213,7 +216,7 @@ export async function runMicrosoftLoopbackFlow(config, onAuthUrl, onAuthorized)
|
|
|
213
216
|
});
|
|
214
217
|
server.on('error', (error) => reject(listenerError(error, config.oauthPort)));
|
|
215
218
|
server.listen(config.oauthPort, config.oauthHost, () => {
|
|
216
|
-
onAuthUrl(buildMicrosoftAuthUrl(config, redirectUri, state, verifier));
|
|
219
|
+
onAuthUrl(buildMicrosoftAuthUrl(config, redirectUri, state, verifier, oauthClient));
|
|
217
220
|
});
|
|
218
221
|
});
|
|
219
222
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microsoftAuth.js","sourceRoot":"","sources":["../../src/accounts/microsoftAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"microsoftAuth.js","sourceRoot":"","sources":["../../src/accounts/microsoftAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { type Credentials } from 'google-auth-library';
|
|
2
|
-
import { type Account, type
|
|
2
|
+
import { type Account, type EmailProvider } from '@fluxmail/core';
|
|
3
3
|
import { type FolderWarning, type ImapCredentials } from '@fluxmail/provider-imap';
|
|
4
4
|
import type { FluxmailConfig } from '../config.js';
|
|
5
5
|
import { type FluxmailDb } from '../storage/db.js';
|
|
6
|
+
import type { StoredGoogleOAuthApp } from '../instanceConfig.js';
|
|
6
7
|
import { type MicrosoftCredentials } from './microsoftAuth.js';
|
|
7
8
|
export interface AccountAccessInput {
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
sharedWithAll: boolean;
|
|
10
|
+
grantedMemberIds?: readonly string[];
|
|
10
11
|
}
|
|
11
12
|
export declare class AccountRegistry {
|
|
12
13
|
private readonly db;
|
|
@@ -26,13 +27,16 @@ export declare class AccountRegistry {
|
|
|
26
27
|
resolveAccountId(accountId?: string): string;
|
|
27
28
|
getProvider(accountId: string): EmailProvider;
|
|
28
29
|
private loadCredentialRow;
|
|
29
|
-
private
|
|
30
|
+
private decryptCredentials;
|
|
30
31
|
private writeCredentials;
|
|
31
|
-
private
|
|
32
|
-
private
|
|
32
|
+
private gmailCredentials;
|
|
33
|
+
private writeTokenRows;
|
|
34
|
+
private writeTokensIfCurrent;
|
|
35
|
+
private updateCachedProvider;
|
|
36
|
+
private gmailTokens;
|
|
33
37
|
private buildGmailProvider;
|
|
34
38
|
private buildOutlookProvider;
|
|
35
|
-
addGmailAccount(email: string, tokens: Credentials, displayName?: string, memberId?: string, access?: AccountAccessInput): Account;
|
|
39
|
+
addGmailAccount(email: string, tokens: Credentials, displayName?: string, memberId?: string, access?: AccountAccessInput, oauthClient?: StoredGoogleOAuthApp): Account;
|
|
36
40
|
addOutlookAccount(email: string, credentials: MicrosoftCredentials, displayName?: string, memberId?: string, reauthorizeId?: string, access?: AccountAccessInput): Account;
|
|
37
41
|
testImapCredentials(email: string, credentials: ImapCredentials, displayName?: string, timeoutMs?: number): Promise<FolderWarning[]>;
|
|
38
42
|
testImapFolderOverrides(email: string, credentials: ImapCredentials, displayName?: string, timeoutMs?: number): Promise<FolderWarning[]>;
|
|
@@ -40,8 +44,6 @@ export declare class AccountRegistry {
|
|
|
40
44
|
addImapAccount(email: string, credentials: ImapCredentials, displayName?: string, memberId?: string, reauthorizeId?: string, access?: AccountAccessInput): Account;
|
|
41
45
|
loadImapCredentials(accountId: string): ImapCredentials;
|
|
42
46
|
saveImapCredentials(accountId: string, credentials: ImapCredentials): void;
|
|
43
|
-
/** Deprecated storage alias for assignAccountOwner. */
|
|
44
|
-
assignAccountMember(accountId: string, memberId: string | null): Account;
|
|
45
47
|
assignAccountOwner(accountId: string, memberId: string): Account;
|
|
46
48
|
setAccountAccess(accountId: string, access: AccountAccessInput): Account;
|
|
47
49
|
removeAccount(accountId: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/accounts/registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/accounts/registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AAE7F,OAAO,EAAmC,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEpH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAkE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAIjE,OAAO,EAAuD,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEpH,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAYD,qBAAa,eAAe;IAIxB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoE;gBAG3E,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,cAAc;IAGzC,OAAO,CAAC,aAAa;IAMrB,YAAY,IAAI,OAAO,EAAE;IAqCzB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAMtC,iGAAiG;IACjG,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAWjC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,WAAW;IAenB,0EAA0E;IAC1E,mBAAmB,IAAI,IAAI;IAc3B,kFAAkF;IAClF,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAoB5C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa;IAgC7C,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,oBAAoB;IAgC5B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,kBAAkB;IAkD1B,OAAO,CAAC,oBAAoB;IA8B5B,eAAe,CACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,kBAAkB,EAC3B,WAAW,CAAC,EAAE,oBAAoB,GACjC,OAAO;IAkDV,iBAAiB,CACf,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,oBAAoB,EACjC,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO;IAkDJ,mBAAmB,CACvB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,eAAe,EAC5B,WAAW,CAAC,EAAE,MAAM,EACpB,SAAS,SAAS,GACjB,OAAO,CAAC,aAAa,EAAE,CAAC;IAIrB,uBAAuB,CAC3B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,eAAe,EAC5B,WAAW,CAAC,EAAE,MAAM,EACpB,SAAS,SAAS,GACjB,OAAO,CAAC,aAAa,EAAE,CAAC;YAIb,aAAa;IAyC3B,cAAc,CACZ,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,eAAe,EAC5B,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO;IAsDV,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe;IAQvD,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,GAAG,IAAI;IAM1E,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAOhE,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO;IAMxE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAMtC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;CAG/D"}
|