@pattern-stack/codegen 0.6.4 → 0.6.5
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/CHANGELOG.md +10 -0
- package/README.md +2 -0
- package/dist/runtime/subsystems/auth/auth-oauth-state.schema.d.ts +81 -0
- package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js +12 -0
- package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js.map +1 -0
- package/dist/runtime/subsystems/auth/auth.module.d.ts +39 -24
- package/dist/runtime/subsystems/auth/auth.module.js +246 -13
- package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.tokens.d.ts +15 -2
- package/dist/runtime/subsystems/auth/auth.tokens.js +9 -1
- package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
- package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.d.ts +23 -0
- package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js +68 -0
- package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.d.ts +21 -0
- package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.js +51 -0
- package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/auth/controllers/auth.controller.d.ts +31 -0
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js +137 -0
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -0
- package/dist/runtime/subsystems/auth/index.d.ts +13 -4
- package/dist/runtime/subsystems/auth/index.js +253 -14
- package/dist/runtime/subsystems/auth/index.js.map +1 -1
- package/dist/runtime/subsystems/auth/protocols/integration-store.d.ts +36 -1
- package/dist/runtime/subsystems/auth/protocols/oauth-state-store.d.ts +33 -7
- package/dist/runtime/subsystems/auth/protocols/oauth-state-store.js +12 -0
- package/dist/runtime/subsystems/auth/protocols/oauth-state-store.js.map +1 -1
- package/dist/runtime/subsystems/auth/protocols/provider-strategy.d.ts +47 -0
- package/dist/runtime/subsystems/auth/protocols/provider-strategy.js +1 -0
- package/dist/runtime/subsystems/auth/protocols/provider-strategy.js.map +1 -0
- package/dist/runtime/subsystems/auth/protocols/user-context.d.ts +24 -0
- package/dist/runtime/subsystems/auth/protocols/user-context.js +1 -0
- package/dist/runtime/subsystems/auth/protocols/user-context.js.map +1 -0
- package/dist/runtime/subsystems/index.d.ts +9 -4
- package/dist/runtime/subsystems/index.js +247 -14
- package/dist/runtime/subsystems/index.js.map +1 -1
- package/dist/src/cli/index.js +574 -142
- package/dist/src/cli/index.js.map +1 -1
- package/package.json +1 -1
- package/runtime/subsystems/auth/auth-oauth-state.schema.ts +30 -0
- package/runtime/subsystems/auth/auth.module.ts +89 -32
- package/runtime/subsystems/auth/auth.tokens.ts +14 -1
- package/runtime/subsystems/auth/backends/state-store.drizzle-backend.ts +83 -0
- package/runtime/subsystems/auth/backends/state-store.memory-backend.ts +76 -0
- package/runtime/subsystems/auth/controllers/auth.controller.ts +155 -0
- package/runtime/subsystems/auth/index.ts +43 -4
- package/runtime/subsystems/auth/protocols/integration-store.ts +37 -0
- package/runtime/subsystems/auth/protocols/oauth-state-store.ts +38 -6
- package/runtime/subsystems/auth/protocols/provider-strategy.ts +41 -0
- package/runtime/subsystems/auth/protocols/user-context.ts +22 -0
- package/runtime/subsystems/index.ts +17 -2
- package/templates/subsystem/auth/app-module-hook.ejs.t +21 -0
- package/templates/subsystem/auth/auth-oauth-state.schema.ejs.t +35 -0
- package/templates/subsystem/auth/env-config.ejs.t +20 -0
- package/templates/subsystem/auth/prompt.js +46 -0
- package/templates/subsystem/auth-config/codegen-config-auth-block.ejs.t +20 -0
- package/templates/subsystem/auth-config/prompt.js +20 -0
- package/templates/subsystem/auth-integrations/app-module-hook.ejs.t +16 -0
- package/templates/subsystem/auth-integrations/prompt.js +23 -0
- package/dist/runtime/subsystems/auth/backends/oauth-state-store/in-memory.d.ts +0 -24
- package/dist/runtime/subsystems/auth/backends/oauth-state-store/in-memory.js +0 -24
- package/dist/runtime/subsystems/auth/backends/oauth-state-store/in-memory.js.map +0 -1
- package/runtime/subsystems/auth/backends/oauth-state-store/in-memory.ts +0 -42
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { OAuth2RefreshStrategy } from '../runtime/oauth2-refresh.strategy.js';
|
|
2
|
+
import './auth-strategy.js';
|
|
3
|
+
import './integration-store.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Auth subsystem — `ProviderStrategy` contract.
|
|
7
|
+
*
|
|
8
|
+
* Extension of `OAuth2RefreshStrategy` (which already covers the refresh
|
|
9
|
+
* path) that adds the two methods needed by the connect/callback dance:
|
|
10
|
+
*
|
|
11
|
+
* - `buildAuthorizeUrl({ state, redirectUri })` → consent-page URL.
|
|
12
|
+
* - `exchangeCodeForTokens({ code, redirectUri })` → tokens after consent.
|
|
13
|
+
*
|
|
14
|
+
* Concrete per-provider strategies (HubSpot, SFDC, Google, Gong, Fathom, …)
|
|
15
|
+
* stay consumer-side per ADR-031 ("every app has different combinations").
|
|
16
|
+
* They typically subclass `OAuth2RefreshStrategy` for the refresh path and
|
|
17
|
+
* implement these two methods structurally — that satisfies
|
|
18
|
+
* `ProviderStrategy` because TS lets interfaces extend classes by type.
|
|
19
|
+
*
|
|
20
|
+
* AuthController never imports a concrete strategy — it injects the
|
|
21
|
+
* `STRATEGY_REGISTRY` (a `ReadonlyMap<provider-slug, ProviderStrategy>`)
|
|
22
|
+
* and dispatches by slug.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
interface ExchangedTokens {
|
|
26
|
+
accessToken: string;
|
|
27
|
+
refreshToken?: string;
|
|
28
|
+
expiresAt?: Date;
|
|
29
|
+
scope?: string[];
|
|
30
|
+
externalAccountId?: string;
|
|
31
|
+
/** Provider-specific bag (SFDC `instance_url`, Google `sub`, …). */
|
|
32
|
+
providerMetadata?: Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
interface ProviderStrategy extends OAuth2RefreshStrategy {
|
|
35
|
+
buildAuthorizeUrl(args: {
|
|
36
|
+
state: string;
|
|
37
|
+
redirectUri: string;
|
|
38
|
+
}): string;
|
|
39
|
+
exchangeCodeForTokens(args: {
|
|
40
|
+
code: string;
|
|
41
|
+
redirectUri: string;
|
|
42
|
+
}): Promise<ExchangedTokens>;
|
|
43
|
+
}
|
|
44
|
+
/** The DI value type behind the `STRATEGY_REGISTRY` token. */
|
|
45
|
+
type ProviderStrategyRegistry = ReadonlyMap<string, ProviderStrategy>;
|
|
46
|
+
|
|
47
|
+
export type { ExchangedTokens, ProviderStrategy, ProviderStrategyRegistry };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=provider-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth subsystem — `IUserContext` port.
|
|
3
|
+
*
|
|
4
|
+
* Resolves "who is the current user" from a request. The shape is
|
|
5
|
+
* universal; the implementation is always app-specific:
|
|
6
|
+
*
|
|
7
|
+
* - WorkOS session: `req.session.user.id`
|
|
8
|
+
* - JWT bearer: `decode(req.headers.authorization).sub`
|
|
9
|
+
* - Test fixture: hardcoded UUID
|
|
10
|
+
*
|
|
11
|
+
* The auth subsystem cannot ship a default — every app does auth differently —
|
|
12
|
+
* but the port is universal, so the contract ships here. Consumers bind a
|
|
13
|
+
* concrete implementation under the `AUTH_USER_CONTEXT` token in their app
|
|
14
|
+
* module.
|
|
15
|
+
*
|
|
16
|
+
* `req` is typed as `unknown` deliberately: this protocol must not pull a
|
|
17
|
+
* dependency on `express` / `fastify` / NestJS request types. The concrete
|
|
18
|
+
* adapter narrows it (e.g. via a `Request` import).
|
|
19
|
+
*/
|
|
20
|
+
interface IUserContext {
|
|
21
|
+
getCurrentUserId(req: unknown): Promise<string>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type { IUserContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=user-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -21,15 +21,20 @@ export { ObservabilityModule, ObservabilityModuleOptions } from './observability
|
|
|
21
21
|
export { ObservabilityError } from './observability/observability-errors.js';
|
|
22
22
|
export { AuthCredentials, AuthResolveOptions, IAuthStrategy } from './auth/protocols/auth-strategy.js';
|
|
23
23
|
export { IEncryptionKey } from './auth/protocols/encryption-key.js';
|
|
24
|
-
export { IOAuthStateStore,
|
|
25
|
-
export { DecryptedIntegration, IIntegrationReader, IIntegrationTokenWriter, IntegrationTokenUpdate } from './auth/protocols/integration-store.js';
|
|
26
|
-
export {
|
|
24
|
+
export { IOAuthStateStore, OAuthStateError, OAuthStateRecord } from './auth/protocols/oauth-state-store.js';
|
|
25
|
+
export { DecryptedIntegration, IIntegrationGrantSink, IIntegrationReader, IIntegrationTokenWriter, IntegrationGrantInput, IntegrationTokenUpdate } from './auth/protocols/integration-store.js';
|
|
26
|
+
export { IUserContext } from './auth/protocols/user-context.js';
|
|
27
|
+
export { ExchangedTokens, ProviderStrategy, ProviderStrategyRegistry } from './auth/protocols/provider-strategy.js';
|
|
28
|
+
export { AUTH_INTEGRATION_GRANT_SINK, AUTH_INTEGRATION_READER, AUTH_INTEGRATION_TOKEN_WRITER, AUTH_OPTIONS, AUTH_USER_CONTEXT, ENCRYPTION_KEY, OAUTH_STATE_STORE, STRATEGY_REGISTRY } from './auth/auth.tokens.js';
|
|
27
29
|
export { OAuth2RefreshStrategy, ParsedRefreshResponse } from './auth/runtime/oauth2-refresh.strategy.js';
|
|
28
30
|
export { withAuthRetry } from './auth/runtime/with-auth-retry.js';
|
|
29
31
|
export { IntegrationBrokenError } from './auth/runtime/integration-broken.error.js';
|
|
30
32
|
export { SessionExpiredError, isSessionExpiredError } from './auth/runtime/session-expired.error.js';
|
|
33
|
+
export { AuthOAuthState, authOAuthState } from './auth/auth-oauth-state.schema.js';
|
|
31
34
|
export { EnvEncryptionKey } from './auth/backends/encryption-key/env.js';
|
|
32
|
-
export {
|
|
35
|
+
export { MemoryOAuthStateStore } from './auth/backends/state-store.memory-backend.js';
|
|
36
|
+
export { DrizzleOAuthStateStore } from './auth/backends/state-store.drizzle-backend.js';
|
|
37
|
+
export { AuthController } from './auth/controllers/auth.controller.js';
|
|
33
38
|
export { AuthModule } from './auth/auth.module.js';
|
|
34
39
|
export { CursorSnapshot } from './sync/sync-cursor-store.protocol.js';
|
|
35
40
|
export { StatusHistogram } from './bridge/bridge.protocol.js';
|
|
@@ -3971,11 +3971,25 @@ var ObservabilityError = class extends Error {
|
|
|
3971
3971
|
cause;
|
|
3972
3972
|
};
|
|
3973
3973
|
|
|
3974
|
+
// runtime/subsystems/auth/protocols/oauth-state-store.ts
|
|
3975
|
+
var OAuthStateError = class extends Error {
|
|
3976
|
+
constructor(message, reason) {
|
|
3977
|
+
super(message);
|
|
3978
|
+
this.reason = reason;
|
|
3979
|
+
this.name = "OAuthStateError";
|
|
3980
|
+
}
|
|
3981
|
+
reason;
|
|
3982
|
+
};
|
|
3983
|
+
|
|
3974
3984
|
// runtime/subsystems/auth/auth.tokens.ts
|
|
3975
3985
|
var ENCRYPTION_KEY = /* @__PURE__ */ Symbol("ENCRYPTION_KEY");
|
|
3976
3986
|
var OAUTH_STATE_STORE = /* @__PURE__ */ Symbol("OAUTH_STATE_STORE");
|
|
3977
3987
|
var AUTH_INTEGRATION_READER = /* @__PURE__ */ Symbol("AUTH_INTEGRATION_READER");
|
|
3978
3988
|
var AUTH_INTEGRATION_TOKEN_WRITER = /* @__PURE__ */ Symbol("AUTH_INTEGRATION_TOKEN_WRITER");
|
|
3989
|
+
var AUTH_INTEGRATION_GRANT_SINK = /* @__PURE__ */ Symbol("AUTH_INTEGRATION_GRANT_SINK");
|
|
3990
|
+
var AUTH_USER_CONTEXT = /* @__PURE__ */ Symbol("AUTH_USER_CONTEXT");
|
|
3991
|
+
var STRATEGY_REGISTRY = /* @__PURE__ */ Symbol("STRATEGY_REGISTRY");
|
|
3992
|
+
var AUTH_OPTIONS = /* @__PURE__ */ Symbol("AUTH_OPTIONS");
|
|
3979
3993
|
|
|
3980
3994
|
// runtime/subsystems/auth/runtime/integration-broken.error.ts
|
|
3981
3995
|
var IntegrationBrokenError = class extends Error {
|
|
@@ -4112,6 +4126,15 @@ async function withAuthRetry(authStrategy, integrationId, op, options = {}) {
|
|
|
4112
4126
|
}
|
|
4113
4127
|
}
|
|
4114
4128
|
|
|
4129
|
+
// runtime/subsystems/auth/auth-oauth-state.schema.ts
|
|
4130
|
+
import { pgTable as pgTable4, text as text4, timestamp as timestamp4 } from "drizzle-orm/pg-core";
|
|
4131
|
+
var authOAuthState = pgTable4("auth_oauth_state", {
|
|
4132
|
+
state: text4("state").primaryKey(),
|
|
4133
|
+
userId: text4("user_id").notNull(),
|
|
4134
|
+
redirect: text4("redirect"),
|
|
4135
|
+
expiresAt: timestamp4("expires_at", { withTimezone: true }).notNull()
|
|
4136
|
+
});
|
|
4137
|
+
|
|
4115
4138
|
// runtime/subsystems/auth/backends/encryption-key/env.ts
|
|
4116
4139
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
4117
4140
|
var ALGO = "aes-256-gcm";
|
|
@@ -4162,26 +4185,198 @@ var EnvEncryptionKey = class {
|
|
|
4162
4185
|
}
|
|
4163
4186
|
};
|
|
4164
4187
|
|
|
4165
|
-
// runtime/subsystems/auth/backends/
|
|
4166
|
-
|
|
4188
|
+
// runtime/subsystems/auth/backends/state-store.memory-backend.ts
|
|
4189
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
4190
|
+
var MemoryOAuthStateStore = class {
|
|
4167
4191
|
store = /* @__PURE__ */ new Map();
|
|
4168
4192
|
ttlMs;
|
|
4169
4193
|
now;
|
|
4194
|
+
generateToken;
|
|
4170
4195
|
constructor(opts = {}) {
|
|
4171
4196
|
this.ttlMs = opts.ttlMs ?? 10 * 60 * 1e3;
|
|
4172
4197
|
this.now = opts.now ?? (() => Date.now());
|
|
4198
|
+
this.generateToken = opts.generateToken ?? (() => randomBytes2(32).toString("base64url"));
|
|
4173
4199
|
}
|
|
4174
|
-
async
|
|
4175
|
-
|
|
4200
|
+
async generate(record) {
|
|
4201
|
+
const state = this.generateToken();
|
|
4202
|
+
this.store.set(state, {
|
|
4203
|
+
record: { ...record },
|
|
4204
|
+
expiresAt: this.now() + this.ttlMs
|
|
4205
|
+
});
|
|
4206
|
+
return state;
|
|
4176
4207
|
}
|
|
4177
4208
|
async consume(state) {
|
|
4178
4209
|
const slot = this.store.get(state);
|
|
4179
|
-
if (!slot)
|
|
4210
|
+
if (!slot) {
|
|
4211
|
+
throw new OAuthStateError(
|
|
4212
|
+
`OAuth state token unknown or already consumed`,
|
|
4213
|
+
"missing"
|
|
4214
|
+
);
|
|
4215
|
+
}
|
|
4180
4216
|
this.store.delete(state);
|
|
4181
|
-
if (slot.expiresAt <= this.now())
|
|
4182
|
-
|
|
4217
|
+
if (slot.expiresAt <= this.now()) {
|
|
4218
|
+
throw new OAuthStateError(`OAuth state token expired`, "expired");
|
|
4219
|
+
}
|
|
4220
|
+
return slot.record;
|
|
4221
|
+
}
|
|
4222
|
+
};
|
|
4223
|
+
|
|
4224
|
+
// runtime/subsystems/auth/backends/state-store.drizzle-backend.ts
|
|
4225
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
4226
|
+
import { eq as eq7 } from "drizzle-orm";
|
|
4227
|
+
var DrizzleOAuthStateStore = class {
|
|
4228
|
+
constructor(db, opts = {}) {
|
|
4229
|
+
this.db = db;
|
|
4230
|
+
this.ttlMs = opts.ttlMs ?? 10 * 60 * 1e3;
|
|
4231
|
+
this.now = opts.now ?? (() => Date.now());
|
|
4232
|
+
this.generateToken = opts.generateToken ?? (() => randomBytes3(32).toString("base64url"));
|
|
4233
|
+
}
|
|
4234
|
+
db;
|
|
4235
|
+
ttlMs;
|
|
4236
|
+
now;
|
|
4237
|
+
generateToken;
|
|
4238
|
+
async generate(record) {
|
|
4239
|
+
const state = this.generateToken();
|
|
4240
|
+
const expiresAt = new Date(this.now() + this.ttlMs);
|
|
4241
|
+
await this.db.insert(authOAuthState).values({
|
|
4242
|
+
state,
|
|
4243
|
+
userId: record.userId,
|
|
4244
|
+
redirect: record.redirect ?? null,
|
|
4245
|
+
expiresAt
|
|
4246
|
+
});
|
|
4247
|
+
return state;
|
|
4248
|
+
}
|
|
4249
|
+
async consume(state) {
|
|
4250
|
+
const rows = await this.db.delete(authOAuthState).where(eq7(authOAuthState.state, state)).returning();
|
|
4251
|
+
const row = rows[0];
|
|
4252
|
+
if (!row) {
|
|
4253
|
+
throw new OAuthStateError(
|
|
4254
|
+
`OAuth state token unknown or already consumed`,
|
|
4255
|
+
"missing"
|
|
4256
|
+
);
|
|
4257
|
+
}
|
|
4258
|
+
if (row.expiresAt.getTime() <= this.now()) {
|
|
4259
|
+
throw new OAuthStateError(`OAuth state token expired`, "expired");
|
|
4260
|
+
}
|
|
4261
|
+
return {
|
|
4262
|
+
userId: row.userId,
|
|
4263
|
+
redirect: row.redirect ?? void 0
|
|
4264
|
+
};
|
|
4265
|
+
}
|
|
4266
|
+
};
|
|
4267
|
+
|
|
4268
|
+
// runtime/subsystems/auth/controllers/auth.controller.ts
|
|
4269
|
+
import {
|
|
4270
|
+
Controller,
|
|
4271
|
+
Get,
|
|
4272
|
+
Inject as Inject16,
|
|
4273
|
+
Param,
|
|
4274
|
+
Query,
|
|
4275
|
+
Req,
|
|
4276
|
+
Res,
|
|
4277
|
+
HttpException,
|
|
4278
|
+
HttpStatus
|
|
4279
|
+
} from "@nestjs/common";
|
|
4280
|
+
var AuthController = class {
|
|
4281
|
+
constructor(registry, userContext, stateStore, grantSink, options) {
|
|
4282
|
+
this.registry = registry;
|
|
4283
|
+
this.userContext = userContext;
|
|
4284
|
+
this.stateStore = stateStore;
|
|
4285
|
+
this.grantSink = grantSink;
|
|
4286
|
+
this.options = options;
|
|
4287
|
+
}
|
|
4288
|
+
registry;
|
|
4289
|
+
userContext;
|
|
4290
|
+
stateStore;
|
|
4291
|
+
grantSink;
|
|
4292
|
+
options;
|
|
4293
|
+
async connect(slug, redirect, req, res) {
|
|
4294
|
+
const strategy = this.requireStrategy(slug);
|
|
4295
|
+
const userId = await this.userContext.getCurrentUserId(req);
|
|
4296
|
+
const state = await this.stateStore.generate({ userId, redirect });
|
|
4297
|
+
const url = strategy.buildAuthorizeUrl({
|
|
4298
|
+
state,
|
|
4299
|
+
redirectUri: this.redirectUriFor(slug)
|
|
4300
|
+
});
|
|
4301
|
+
return res.redirect(HttpStatus.FOUND, url);
|
|
4302
|
+
}
|
|
4303
|
+
async callback(slug, code, state, res) {
|
|
4304
|
+
const strategy = this.requireStrategy(slug);
|
|
4305
|
+
if (!code) {
|
|
4306
|
+
throw new HttpException(
|
|
4307
|
+
`Missing 'code' query param`,
|
|
4308
|
+
HttpStatus.BAD_REQUEST
|
|
4309
|
+
);
|
|
4310
|
+
}
|
|
4311
|
+
if (!state) {
|
|
4312
|
+
throw new HttpException(
|
|
4313
|
+
`Missing 'state' query param`,
|
|
4314
|
+
HttpStatus.BAD_REQUEST
|
|
4315
|
+
);
|
|
4316
|
+
}
|
|
4317
|
+
const { userId, redirect } = await this.stateStore.consume(state);
|
|
4318
|
+
const tokens = await strategy.exchangeCodeForTokens({
|
|
4319
|
+
code,
|
|
4320
|
+
redirectUri: this.redirectUriFor(slug)
|
|
4321
|
+
});
|
|
4322
|
+
await this.grantSink.createOrUpdateFromOAuthGrant({
|
|
4323
|
+
userId,
|
|
4324
|
+
provider: slug,
|
|
4325
|
+
accessToken: tokens.accessToken,
|
|
4326
|
+
refreshToken: tokens.refreshToken,
|
|
4327
|
+
expiresAt: tokens.expiresAt,
|
|
4328
|
+
scope: tokens.scope,
|
|
4329
|
+
externalAccountId: tokens.externalAccountId,
|
|
4330
|
+
providerMetadata: tokens.providerMetadata
|
|
4331
|
+
});
|
|
4332
|
+
return res.redirect(
|
|
4333
|
+
HttpStatus.FOUND,
|
|
4334
|
+
redirect ?? `/settings/integrations?connected=${encodeURIComponent(slug)}`
|
|
4335
|
+
);
|
|
4336
|
+
}
|
|
4337
|
+
requireStrategy(slug) {
|
|
4338
|
+
const strategy = this.registry.get(slug);
|
|
4339
|
+
if (!strategy) {
|
|
4340
|
+
throw new HttpException(
|
|
4341
|
+
`Unknown provider '${slug}'`,
|
|
4342
|
+
HttpStatus.NOT_FOUND
|
|
4343
|
+
);
|
|
4344
|
+
}
|
|
4345
|
+
return strategy;
|
|
4346
|
+
}
|
|
4347
|
+
redirectUriFor(slug) {
|
|
4348
|
+
const base = this.options.redirectUriBase;
|
|
4349
|
+
if (!base) {
|
|
4350
|
+
throw new Error(
|
|
4351
|
+
`AuthModule.forRoot: redirectUriBase is required when AuthController is enabled`
|
|
4352
|
+
);
|
|
4353
|
+
}
|
|
4354
|
+
const trimmed = base.replace(/\/+$/, "");
|
|
4355
|
+
return `${trimmed}/auth/${encodeURIComponent(slug)}/callback`;
|
|
4183
4356
|
}
|
|
4184
4357
|
};
|
|
4358
|
+
__decorateClass([
|
|
4359
|
+
Get(":provider/connect"),
|
|
4360
|
+
__decorateParam(0, Param("provider")),
|
|
4361
|
+
__decorateParam(1, Query("redirect")),
|
|
4362
|
+
__decorateParam(2, Req()),
|
|
4363
|
+
__decorateParam(3, Res())
|
|
4364
|
+
], AuthController.prototype, "connect", 1);
|
|
4365
|
+
__decorateClass([
|
|
4366
|
+
Get(":provider/callback"),
|
|
4367
|
+
__decorateParam(0, Param("provider")),
|
|
4368
|
+
__decorateParam(1, Query("code")),
|
|
4369
|
+
__decorateParam(2, Query("state")),
|
|
4370
|
+
__decorateParam(3, Res())
|
|
4371
|
+
], AuthController.prototype, "callback", 1);
|
|
4372
|
+
AuthController = __decorateClass([
|
|
4373
|
+
Controller("auth"),
|
|
4374
|
+
__decorateParam(0, Inject16(STRATEGY_REGISTRY)),
|
|
4375
|
+
__decorateParam(1, Inject16(AUTH_USER_CONTEXT)),
|
|
4376
|
+
__decorateParam(2, Inject16(OAUTH_STATE_STORE)),
|
|
4377
|
+
__decorateParam(3, Inject16(AUTH_INTEGRATION_GRANT_SINK)),
|
|
4378
|
+
__decorateParam(4, Inject16(AUTH_OPTIONS))
|
|
4379
|
+
], AuthController);
|
|
4185
4380
|
|
|
4186
4381
|
// runtime/subsystems/auth/auth.module.ts
|
|
4187
4382
|
import { Module as Module7 } from "@nestjs/common";
|
|
@@ -4192,24 +4387,54 @@ function resolveEncryptionKeyProvider(choice) {
|
|
|
4192
4387
|
return { provide: ENCRYPTION_KEY, ...choice };
|
|
4193
4388
|
}
|
|
4194
4389
|
function resolveOAuthStateStoreProvider(choice) {
|
|
4195
|
-
if (choice === "
|
|
4196
|
-
return { provide: OAUTH_STATE_STORE, useClass:
|
|
4390
|
+
if (choice === "memory") {
|
|
4391
|
+
return { provide: OAUTH_STATE_STORE, useClass: MemoryOAuthStateStore };
|
|
4392
|
+
}
|
|
4393
|
+
if (choice === "drizzle") {
|
|
4394
|
+
return {
|
|
4395
|
+
provide: OAUTH_STATE_STORE,
|
|
4396
|
+
useFactory: (db) => {
|
|
4397
|
+
if (!db) {
|
|
4398
|
+
throw new Error(
|
|
4399
|
+
"AuthModule.forRoot: oauthStateStore: 'drizzle' selected but DRIZZLE provider is not available. Ensure DatabaseModule (or another provider exposing DRIZZLE) is imported before AuthModule.forRoot."
|
|
4400
|
+
);
|
|
4401
|
+
}
|
|
4402
|
+
return new DrizzleOAuthStateStore(db);
|
|
4403
|
+
},
|
|
4404
|
+
inject: [{ token: DRIZZLE, optional: true }]
|
|
4405
|
+
};
|
|
4197
4406
|
}
|
|
4198
4407
|
return { provide: OAUTH_STATE_STORE, ...choice };
|
|
4199
4408
|
}
|
|
4200
4409
|
var AuthModule = class {
|
|
4201
4410
|
static forRoot(options = {}) {
|
|
4411
|
+
const resolved = {
|
|
4412
|
+
encryptionKey: options.encryptionKey ?? "env",
|
|
4413
|
+
oauthStateStore: options.oauthStateStore ?? "memory",
|
|
4414
|
+
enableController: options.enableController ?? false,
|
|
4415
|
+
redirectUriBase: options.redirectUriBase
|
|
4416
|
+
};
|
|
4417
|
+
if (resolved.enableController && !resolved.redirectUriBase) {
|
|
4418
|
+
throw new Error(
|
|
4419
|
+
"AuthModule.forRoot: redirectUriBase is required when enableController: true"
|
|
4420
|
+
);
|
|
4421
|
+
}
|
|
4202
4422
|
const encryptionKeyProvider = resolveEncryptionKeyProvider(
|
|
4203
|
-
|
|
4423
|
+
resolved.encryptionKey
|
|
4204
4424
|
);
|
|
4205
4425
|
const oauthStateStoreProvider = resolveOAuthStateStoreProvider(
|
|
4206
|
-
|
|
4426
|
+
resolved.oauthStateStore
|
|
4207
4427
|
);
|
|
4428
|
+
const optionsProvider = {
|
|
4429
|
+
provide: AUTH_OPTIONS,
|
|
4430
|
+
useValue: resolved
|
|
4431
|
+
};
|
|
4208
4432
|
return {
|
|
4209
4433
|
module: AuthModule,
|
|
4210
4434
|
global: true,
|
|
4211
|
-
providers: [encryptionKeyProvider, oauthStateStoreProvider],
|
|
4212
|
-
|
|
4435
|
+
providers: [encryptionKeyProvider, oauthStateStoreProvider, optionsProvider],
|
|
4436
|
+
controllers: resolved.enableController ? [AuthController] : [],
|
|
4437
|
+
exports: [ENCRYPTION_KEY, OAUTH_STATE_STORE, AUTH_OPTIONS]
|
|
4213
4438
|
};
|
|
4214
4439
|
}
|
|
4215
4440
|
};
|
|
@@ -4217,32 +4442,40 @@ AuthModule = __decorateClass([
|
|
|
4217
4442
|
Module7({})
|
|
4218
4443
|
], AuthModule);
|
|
4219
4444
|
export {
|
|
4445
|
+
AUTH_INTEGRATION_GRANT_SINK,
|
|
4220
4446
|
AUTH_INTEGRATION_READER,
|
|
4221
4447
|
AUTH_INTEGRATION_TOKEN_WRITER,
|
|
4448
|
+
AUTH_OPTIONS,
|
|
4449
|
+
AUTH_USER_CONTEXT,
|
|
4450
|
+
AuthController,
|
|
4222
4451
|
AuthModule,
|
|
4223
4452
|
CACHE,
|
|
4224
4453
|
CacheModule,
|
|
4225
4454
|
DrizzleCacheService,
|
|
4226
4455
|
DrizzleEventBus,
|
|
4456
|
+
DrizzleOAuthStateStore,
|
|
4227
4457
|
ENCRYPTION_KEY,
|
|
4228
4458
|
EVENT_BUS,
|
|
4229
4459
|
EnvEncryptionKey,
|
|
4230
4460
|
EventsModule,
|
|
4231
|
-
InMemoryOAuthStateStore,
|
|
4232
4461
|
IntegrationBrokenError,
|
|
4233
4462
|
LocalStorageBackend,
|
|
4234
4463
|
MemoryCacheService,
|
|
4235
4464
|
MemoryEventBus,
|
|
4465
|
+
MemoryOAuthStateStore,
|
|
4236
4466
|
MemoryStorageBackend,
|
|
4237
4467
|
OAUTH_STATE_STORE,
|
|
4238
4468
|
OAuth2RefreshStrategy,
|
|
4469
|
+
OAuthStateError,
|
|
4239
4470
|
OBSERVABILITY,
|
|
4240
4471
|
OBSERVABILITY_MODULE_OPTIONS,
|
|
4241
4472
|
ObservabilityError,
|
|
4242
4473
|
ObservabilityModule,
|
|
4243
4474
|
STORAGE,
|
|
4475
|
+
STRATEGY_REGISTRY,
|
|
4244
4476
|
SessionExpiredError,
|
|
4245
4477
|
StorageModule,
|
|
4478
|
+
authOAuthState,
|
|
4246
4479
|
collisionModeEnum,
|
|
4247
4480
|
isSessionExpiredError,
|
|
4248
4481
|
jobRunStatusEnum,
|