@memberjunction/server 2.90.0 → 2.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/AuthProviderFactory.d.ts +24 -0
- package/dist/auth/AuthProviderFactory.d.ts.map +1 -0
- package/dist/auth/AuthProviderFactory.js +82 -0
- package/dist/auth/AuthProviderFactory.js.map +1 -0
- package/dist/auth/BaseAuthProvider.d.ts +18 -0
- package/dist/auth/BaseAuthProvider.d.ts.map +1 -0
- package/dist/auth/BaseAuthProvider.js +42 -0
- package/dist/auth/BaseAuthProvider.js.map +1 -0
- package/dist/auth/IAuthProvider.d.ts +13 -0
- package/dist/auth/IAuthProvider.d.ts.map +1 -0
- package/dist/auth/IAuthProvider.js +2 -0
- package/dist/auth/IAuthProvider.js.map +1 -0
- package/dist/auth/__tests__/backward-compatibility.test.d.ts +2 -0
- package/dist/auth/__tests__/backward-compatibility.test.d.ts.map +1 -0
- package/dist/auth/__tests__/backward-compatibility.test.js +135 -0
- package/dist/auth/__tests__/backward-compatibility.test.js.map +1 -0
- package/dist/auth/index.d.ts +22 -7
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +65 -32
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +2 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -0
- package/dist/auth/initializeProviders.js +23 -0
- package/dist/auth/initializeProviders.js.map +1 -0
- package/dist/auth/providers/Auth0Provider.d.ts +9 -0
- package/dist/auth/providers/Auth0Provider.d.ts.map +1 -0
- package/dist/auth/providers/Auth0Provider.js +42 -0
- package/dist/auth/providers/Auth0Provider.js.map +1 -0
- package/dist/auth/providers/CognitoProvider.d.ts +9 -0
- package/dist/auth/providers/CognitoProvider.d.ts.map +1 -0
- package/dist/auth/providers/CognitoProvider.js +46 -0
- package/dist/auth/providers/CognitoProvider.js.map +1 -0
- package/dist/auth/providers/GoogleProvider.d.ts +9 -0
- package/dist/auth/providers/GoogleProvider.d.ts.map +1 -0
- package/dist/auth/providers/GoogleProvider.js +41 -0
- package/dist/auth/providers/GoogleProvider.js.map +1 -0
- package/dist/auth/providers/MSALProvider.d.ts +9 -0
- package/dist/auth/providers/MSALProvider.d.ts.map +1 -0
- package/dist/auth/providers/MSALProvider.js +42 -0
- package/dist/auth/providers/MSALProvider.js.map +1 -0
- package/dist/auth/providers/OktaProvider.d.ts +9 -0
- package/dist/auth/providers/OktaProvider.d.ts.map +1 -0
- package/dist/auth/providers/OktaProvider.js +42 -0
- package/dist/auth/providers/OktaProvider.js.map +1 -0
- package/dist/config.d.ts +97 -21
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -6
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +25 -17
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +6 -0
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +31 -0
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +1 -1
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +5 -4
- package/dist/generic/ResolverBase.js.map +1 -1
- package/package.json +39 -39
- package/src/auth/AuthProviderFactory.ts +152 -0
- package/src/auth/BaseAuthProvider.ts +71 -0
- package/src/auth/IAuthProvider.ts +49 -0
- package/src/auth/__tests__/backward-compatibility.test.ts +183 -0
- package/src/auth/index.ts +104 -36
- package/src/auth/initializeProviders.ts +31 -0
- package/src/auth/providers/Auth0Provider.ts +45 -0
- package/src/auth/providers/CognitoProvider.ts +50 -0
- package/src/auth/providers/GoogleProvider.ts +45 -0
- package/src/auth/providers/MSALProvider.ts +45 -0
- package/src/auth/providers/OktaProvider.ts +46 -0
- package/src/config.ts +14 -10
- package/src/context.ts +40 -17
- package/src/generated/generated.ts +19 -0
- package/src/generic/ResolverBase.ts +9 -4
package/src/config.ts
CHANGED
|
@@ -102,6 +102,18 @@ const sqlLoggingSchema = z.object({
|
|
|
102
102
|
sessionTimeout: z.number().optional().default(3600000), // 1 hour
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
+
const authProviderSchema = z.object({
|
|
106
|
+
name: z.string(),
|
|
107
|
+
type: z.string(),
|
|
108
|
+
issuer: z.string(),
|
|
109
|
+
audience: z.string(),
|
|
110
|
+
jwksUri: z.string(),
|
|
111
|
+
clientId: z.string().optional(),
|
|
112
|
+
clientSecret: z.string().optional(),
|
|
113
|
+
tenantId: z.string().optional(),
|
|
114
|
+
domain: z.string().optional(),
|
|
115
|
+
}).passthrough(); // Allow additional provider-specific fields
|
|
116
|
+
|
|
105
117
|
const configInfoSchema = z.object({
|
|
106
118
|
userHandling: userHandlingInfoSchema,
|
|
107
119
|
databaseSettings: databaseSettingsInfoSchema,
|
|
@@ -109,6 +121,7 @@ const configInfoSchema = z.object({
|
|
|
109
121
|
restApiOptions: restApiOptionsSchema.optional().default({}),
|
|
110
122
|
askSkip: askSkipInfoSchema.optional(),
|
|
111
123
|
sqlLogging: sqlLoggingSchema.optional(),
|
|
124
|
+
authProviders: z.array(authProviderSchema).optional(),
|
|
112
125
|
|
|
113
126
|
apiKey: z.string().optional(),
|
|
114
127
|
baseUrl: z.string().default('http://localhost'),
|
|
@@ -131,17 +144,12 @@ const configInfoSchema = z.object({
|
|
|
131
144
|
___codeGenAPIPort: z.coerce.number().optional().default(3999),
|
|
132
145
|
___codeGenAPISubmissionDelay: z.coerce.number().optional().default(5000),
|
|
133
146
|
graphqlRootPath: z.string().optional().default('/'),
|
|
134
|
-
webClientID: z.string().optional(),
|
|
135
|
-
tenantID: z.string().optional(),
|
|
136
147
|
enableIntrospection: z.coerce.boolean().optional().default(false),
|
|
137
148
|
websiteRunFromPackage: z.coerce.number().optional(),
|
|
138
149
|
userEmailMap: z
|
|
139
150
|
.string()
|
|
140
151
|
.transform((val) => z.record(z.string()).parse(JSON.parse(val)))
|
|
141
152
|
.optional(),
|
|
142
|
-
auth0Domain: z.string().optional(),
|
|
143
|
-
auth0WebClientID: z.string().optional(),
|
|
144
|
-
auth0ClientSecret: z.string().optional(),
|
|
145
153
|
mjCoreSchema: z.string(),
|
|
146
154
|
});
|
|
147
155
|
|
|
@@ -152,6 +160,7 @@ export type RESTApiOptions = z.infer<typeof restApiOptionsSchema>;
|
|
|
152
160
|
export type AskSkipInfo = z.infer<typeof askSkipInfoSchema>;
|
|
153
161
|
export type SqlLoggingOptions = z.infer<typeof sqlLoggingOptionsSchema>;
|
|
154
162
|
export type SqlLoggingInfo = z.infer<typeof sqlLoggingSchema>;
|
|
163
|
+
export type AuthProviderConfig = z.infer<typeof authProviderSchema>;
|
|
155
164
|
export type ConfigInfo = z.infer<typeof configInfoSchema>;
|
|
156
165
|
|
|
157
166
|
export const configInfo: ConfigInfo = loadConfig();
|
|
@@ -169,14 +178,9 @@ export const {
|
|
|
169
178
|
___codeGenAPIPort,
|
|
170
179
|
___codeGenAPISubmissionDelay,
|
|
171
180
|
graphqlRootPath,
|
|
172
|
-
webClientID,
|
|
173
|
-
tenantID,
|
|
174
181
|
enableIntrospection,
|
|
175
182
|
websiteRunFromPackage,
|
|
176
183
|
userEmailMap,
|
|
177
|
-
auth0Domain,
|
|
178
|
-
auth0WebClientID,
|
|
179
|
-
auth0ClientSecret,
|
|
180
184
|
apiKey,
|
|
181
185
|
baseUrl,
|
|
182
186
|
mjCoreSchema: mj_core_schema,
|
package/src/context.ts
CHANGED
|
@@ -5,24 +5,33 @@ import 'reflect-metadata';
|
|
|
5
5
|
import { Subject, firstValueFrom } from 'rxjs';
|
|
6
6
|
import { AuthenticationError, AuthorizationError } from 'type-graphql';
|
|
7
7
|
import sql from 'mssql';
|
|
8
|
-
import { getSigningKeys, getSystemUser,
|
|
8
|
+
import { getSigningKeys, getSystemUser, getValidationOptions, verifyUserRecord, extractUserInfoFromPayload, TokenExpiredError } from './auth/index.js';
|
|
9
9
|
import { authCache } from './cache.js';
|
|
10
10
|
import { userEmailMap, apiKey, mj_core_schema } from './config.js';
|
|
11
11
|
import { DataSourceInfo, UserPayload } from './types.js';
|
|
12
|
-
import { TokenExpiredError } from './auth/index.js';
|
|
13
12
|
import { GetReadOnlyDataSource, GetReadWriteDataSource } from './util.js';
|
|
14
13
|
import { v4 as uuidv4 } from 'uuid';
|
|
15
14
|
import e from 'express';
|
|
16
15
|
import { DatabaseProviderBase } from '@memberjunction/core';
|
|
17
16
|
import { SQLServerDataProvider, SQLServerProviderConfigData } from '@memberjunction/sqlserver-dataprovider';
|
|
17
|
+
import { AuthProviderFactory } from './auth/AuthProviderFactory.js';
|
|
18
18
|
|
|
19
|
-
const verifyAsync = async (issuer: string,
|
|
19
|
+
const verifyAsync = async (issuer: string, token: string): Promise<jwt.JwtPayload> =>
|
|
20
20
|
new Promise((resolve, reject) => {
|
|
21
|
+
const options = getValidationOptions(issuer);
|
|
22
|
+
|
|
23
|
+
if (!options) {
|
|
24
|
+
reject(new Error(`No validation options found for issuer ${issuer}`));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
jwt.verify(token, getSigningKeys(issuer), options, (err, jwt) => {
|
|
22
29
|
if (jwt && typeof jwt !== 'string' && !err) {
|
|
23
30
|
const payload = jwt.payload ?? jwt;
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
// Use provider to extract user info for logging
|
|
33
|
+
const userInfo = extractUserInfoFromPayload(payload);
|
|
34
|
+
console.log(`Valid token: ${userInfo.fullName || 'Unknown'} (${userInfo.email || userInfo.preferredUsername || 'Unknown'})`);
|
|
26
35
|
resolve(payload);
|
|
27
36
|
} else {
|
|
28
37
|
console.warn('Invalid token');
|
|
@@ -81,15 +90,28 @@ export const getUserPayload = async (
|
|
|
81
90
|
throw new AuthenticationError('Missing issuer claim on token');
|
|
82
91
|
}
|
|
83
92
|
|
|
84
|
-
|
|
93
|
+
// Verify issuer is supported
|
|
94
|
+
const factory = AuthProviderFactory.getInstance();
|
|
95
|
+
if (!factory.getByIssuer(issuer)) {
|
|
96
|
+
console.warn(`Unsupported issuer: ${issuer}`);
|
|
97
|
+
throw new AuthenticationError(`Unsupported authentication provider: ${issuer}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
await verifyAsync(issuer, token);
|
|
85
101
|
authCache.set(token, true);
|
|
86
102
|
}
|
|
87
103
|
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
const userRecord = await verifyUserRecord(
|
|
104
|
+
// Use provider to extract user information
|
|
105
|
+
const userInfo = extractUserInfoFromPayload(payload);
|
|
106
|
+
const email = userInfo.email ? ((userEmailMap ?? {})[userInfo.email] ?? userInfo.email) : userInfo.preferredUsername;
|
|
107
|
+
|
|
108
|
+
const userRecord = await verifyUserRecord(
|
|
109
|
+
email,
|
|
110
|
+
userInfo.firstName,
|
|
111
|
+
userInfo.lastName,
|
|
112
|
+
requestDomain,
|
|
113
|
+
readWriteDataSource
|
|
114
|
+
);
|
|
93
115
|
|
|
94
116
|
if (!userRecord) {
|
|
95
117
|
console.error(`User ${email} not found`);
|
|
@@ -99,12 +121,13 @@ export const getUserPayload = async (
|
|
|
99
121
|
throw new AuthorizationError();
|
|
100
122
|
}
|
|
101
123
|
|
|
102
|
-
return { userRecord, email, sessionId };
|
|
103
|
-
} catch (
|
|
104
|
-
console.error(
|
|
105
|
-
if (
|
|
106
|
-
throw
|
|
107
|
-
}
|
|
124
|
+
return { userRecord, email: userRecord.Email, sessionId };
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(error);
|
|
127
|
+
if (error instanceof TokenExpiredError) {
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
throw new AuthenticationError('Unable to authenticate user');
|
|
108
131
|
}
|
|
109
132
|
};
|
|
110
133
|
|
|
@@ -171,4 +194,4 @@ export const contextFunction =
|
|
|
171
194
|
};
|
|
172
195
|
|
|
173
196
|
return contextResult;
|
|
174
|
-
};
|
|
197
|
+
};
|
|
@@ -39135,6 +39135,13 @@ export class ComponentLibrary_ {
|
|
|
39135
39135
|
@MaxLength(10)
|
|
39136
39136
|
_mj__UpdatedAt: Date;
|
|
39137
39137
|
|
|
39138
|
+
@Field({description: `Status of the component library. Active: fully supported; Deprecated: works but shows console warning; Disabled: throws error if used`})
|
|
39139
|
+
@MaxLength(40)
|
|
39140
|
+
Status: string;
|
|
39141
|
+
|
|
39142
|
+
@Field({nullable: true, description: `JSON configuration for library-specific lint rules that are applied during component validation. This field contains structured rules that define how components using this library should be validated, including DOM element requirements, initialization patterns, lifecycle methods, and common error patterns. Example structure: {"initialization": {"constructorName": "Chart", "elementType": "canvas"}, "lifecycle": {"requiredMethods": ["render"], "cleanupMethods": ["destroy"]}}. The linter dynamically applies these rules based on the libraries referenced in a component spec, enabling extensible validation without hardcoding library-specific logic.`})
|
|
39143
|
+
LintRules?: string;
|
|
39144
|
+
|
|
39138
39145
|
@Field(() => [ComponentLibraryLink_])
|
|
39139
39146
|
MJ_ComponentLibraryLinks_LibraryIDArray: ComponentLibraryLink_[]; // Link to MJ_ComponentLibraryLinks
|
|
39140
39147
|
|
|
@@ -39171,6 +39178,12 @@ export class CreateComponentLibraryInput {
|
|
|
39171
39178
|
|
|
39172
39179
|
@Field({ nullable: true })
|
|
39173
39180
|
Description: string | null;
|
|
39181
|
+
|
|
39182
|
+
@Field({ nullable: true })
|
|
39183
|
+
Status?: string;
|
|
39184
|
+
|
|
39185
|
+
@Field({ nullable: true })
|
|
39186
|
+
LintRules: string | null;
|
|
39174
39187
|
}
|
|
39175
39188
|
|
|
39176
39189
|
|
|
@@ -39206,6 +39219,12 @@ export class UpdateComponentLibraryInput {
|
|
|
39206
39219
|
@Field({ nullable: true })
|
|
39207
39220
|
Description?: string | null;
|
|
39208
39221
|
|
|
39222
|
+
@Field({ nullable: true })
|
|
39223
|
+
Status?: string;
|
|
39224
|
+
|
|
39225
|
+
@Field({ nullable: true })
|
|
39226
|
+
LintRules?: string | null;
|
|
39227
|
+
|
|
39209
39228
|
@Field(() => [KeyValuePairInput], { nullable: true })
|
|
39210
39229
|
OldValues___?: KeyValuePairInput[];
|
|
39211
39230
|
}
|
|
@@ -139,7 +139,8 @@ export class ResolverBase {
|
|
|
139
139
|
viewInput.AuditLogDescription,
|
|
140
140
|
viewInput.ResultType,
|
|
141
141
|
userPayload,
|
|
142
|
-
viewInput.MaxRows
|
|
142
|
+
viewInput.MaxRows,
|
|
143
|
+
viewInput.StartRow
|
|
143
144
|
);
|
|
144
145
|
}
|
|
145
146
|
else {
|
|
@@ -173,7 +174,8 @@ export class ResolverBase {
|
|
|
173
174
|
viewInput.AuditLogDescription,
|
|
174
175
|
viewInput.ResultType,
|
|
175
176
|
userPayload,
|
|
176
|
-
viewInput.MaxRows
|
|
177
|
+
viewInput.MaxRows,
|
|
178
|
+
viewInput.StartRow
|
|
177
179
|
);
|
|
178
180
|
} catch (err) {
|
|
179
181
|
console.log(err);
|
|
@@ -210,7 +212,8 @@ export class ResolverBase {
|
|
|
210
212
|
viewInput.AuditLogDescription,
|
|
211
213
|
viewInput.ResultType,
|
|
212
214
|
userPayload,
|
|
213
|
-
viewInput.MaxRows
|
|
215
|
+
viewInput.MaxRows,
|
|
216
|
+
viewInput.StartRow
|
|
214
217
|
);
|
|
215
218
|
} catch (err) {
|
|
216
219
|
console.log(err);
|
|
@@ -370,7 +373,8 @@ export class ResolverBase {
|
|
|
370
373
|
auditLogDescription: string | undefined,
|
|
371
374
|
resultType: string | undefined,
|
|
372
375
|
userPayload: UserPayload | null,
|
|
373
|
-
maxRows: number | undefined
|
|
376
|
+
maxRows: number | undefined,
|
|
377
|
+
startRow: number | undefined
|
|
374
378
|
) {
|
|
375
379
|
try {
|
|
376
380
|
if (!viewInfo || !userPayload) return null;
|
|
@@ -420,6 +424,7 @@ export class ResolverBase {
|
|
|
420
424
|
ExcludeDataFromAllPriorViewRuns: excludeDataFromAllPriorViewRuns,
|
|
421
425
|
IgnoreMaxRows: ignoreMaxRows,
|
|
422
426
|
MaxRows: maxRows,
|
|
427
|
+
StartRow: startRow,
|
|
423
428
|
ForceAuditLog: forceAuditLog,
|
|
424
429
|
AuditLogDescription: auditLogDescription,
|
|
425
430
|
ResultType: rt,
|