Skip to content

Commit 0f3aa94

Browse files
authored
Added multi auth cluster (#952)
* Added new search param for client_id * Added authProvider component * Added apiDomain prop to liveconfig * Added test utils for authProvider component * Added US cluster to demo app * Changed getAuthConfig function to check url param in this order: token > client_id Hooks removed from pure function * Made thumbnail optional in liveconfig fetched and instead passed as props * Made apiDomain and thumbnailDomain optional in configValidator * Changed mock global * Added thumbnail to env and demo app * Fixed wording
1 parent 32bb804 commit 0f3aa94

File tree

22 files changed

+659
-56
lines changed

22 files changed

+659
-56
lines changed

apps/demo-app/.env-cmdrc.json

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,46 +6,91 @@
66
"REACT_APP_ENVIRONMENT": "local",
77
"REACT_APP_LIVE_CONFIG_ID": "demo-app-development",
88
"REACT_APP_USE_LOCAL_CONFIG": "true",
9-
"REACT_APP_AUTH_DOMAIN": "idp.preview.monk.ai",
9+
1010
"REACT_APP_AUTH_AUDIENCE": "https://api.monk.ai/v1/",
11+
"REACT_APP_AUTH_DOMAIN": "idp.preview.monk.ai",
1112
"REACT_APP_AUTH_CLIENT_ID": "O7geYcPM6zEJrHw0WvQVzSIzw4WzrAtH",
13+
"REACT_APP_API_DOMAIN": "api.preview.monk.ai/v1",
14+
"REACT_APP_THUMBNAIL_DOMAIN": "api.preview.monk.ai/image_resize",
15+
16+
"REACT_APP_AUTH_DOMAIN_US": "acv-staging.us.auth0.com",
17+
"REACT_APP_AUTH_CLIENT_ID_US": "0tIBBTLd4uP52jtF2PcXawWYxW12mUfZ",
18+
"REACT_APP_API_DOMAIN_US": "monk-us-core-api.gateway.staging.acvauctions.com/v1",
19+
"REACT_APP_THUMBNAIL_DOMAIN_US": "monk-us-image.gateway.staging.acvauctions.com/image_resize",
20+
1221
"REACT_APP_SENTRY_DSN": "https://74f50bfe6f11de7aefd54acfa5dfed96@o4505669501648896.ingest.us.sentry.io/4506863461662720",
1322
"REACT_APP_SENTRY_DEBUG": "true",
1423
"REACT_APP_INSPECTION_REPORT_URL": "https://demo-capture.preview.monk.ai"
1524
},
1625
"development": {
1726
"REACT_APP_ENVIRONMENT": "development",
1827
"REACT_APP_LIVE_CONFIG_ID": "demo-app-development",
19-
"REACT_APP_AUTH_DOMAIN": "idp.preview.monk.ai",
28+
2029
"REACT_APP_AUTH_AUDIENCE": "https://api.monk.ai/v1/",
30+
"REACT_APP_AUTH_DOMAIN": "idp.preview.monk.ai",
2131
"REACT_APP_AUTH_CLIENT_ID": "O7geYcPM6zEJrHw0WvQVzSIzw4WzrAtH",
32+
"REACT_APP_API_DOMAIN": "api.preview.monk.ai/v1",
33+
"REACT_APP_THUMBNAIL_DOMAIN": "api.preview.monk.ai/image_resize",
34+
35+
"REACT_APP_AUTH_DOMAIN_US": "acv-staging.us.auth0.com",
36+
"REACT_APP_AUTH_CLIENT_ID_US": "0tIBBTLd4uP52jtF2PcXawWYxW12mUfZ",
37+
"REACT_APP_API_DOMAIN_US": "monk-us-core-api.gateway.staging.acvauctions.com/v1",
38+
"REACT_APP_THUMBNAIL_DOMAIN_US": "monk-us-image.gateway.staging.acvauctions.com/image_resize",
39+
2240
"REACT_APP_SENTRY_DSN": "https://74f50bfe6f11de7aefd54acfa5dfed96@o4505669501648896.ingest.us.sentry.io/4506863461662720",
2341
"REACT_APP_INSPECTION_REPORT_URL": "https://demo-capture.preview.monk.ai"
2442
},
2543
"staging": {
2644
"REACT_APP_ENVIRONMENT": "staging",
2745
"REACT_APP_LIVE_CONFIG_ID": "demo-app-staging",
28-
"REACT_APP_AUTH_DOMAIN": "idp.preview.monk.ai",
46+
2947
"REACT_APP_AUTH_AUDIENCE": "https://api.monk.ai/v1/",
48+
"REACT_APP_AUTH_DOMAIN": "idp.preview.monk.ai",
3049
"REACT_APP_AUTH_CLIENT_ID": "O7geYcPM6zEJrHw0WvQVzSIzw4WzrAtH",
50+
"REACT_APP_API_DOMAIN": "api.preview.monk.ai/v1",
51+
"REACT_APP_THUMBNAIL_DOMAIN": "api.preview.monk.ai/image_resize",
52+
53+
"REACT_APP_AUTH_DOMAIN_US": "acv-staging.us.auth0.com",
54+
"REACT_APP_AUTH_CLIENT_ID_US": "0tIBBTLd4uP52jtF2PcXawWYxW12mUfZ",
55+
"REACT_APP_API_DOMAIN_US": "monk-us-core-api.gateway.staging.acvauctions.com/v1",
56+
"REACT_APP_THUMBNAIL_DOMAIN_US": "monk-us-image.gateway.staging.acvauctions.com/image_resize",
57+
3158
"REACT_APP_SENTRY_DSN": "https://74f50bfe6f11de7aefd54acfa5dfed96@o4505669501648896.ingest.us.sentry.io/4506863461662720",
3259
"REACT_APP_INSPECTION_REPORT_URL": "https://demo-capture.preview.monk.ai"
3360
},
3461
"preview": {
3562
"REACT_APP_ENVIRONMENT": "preview",
3663
"REACT_APP_LIVE_CONFIG_ID": "demo-app-preview",
37-
"REACT_APP_AUTH_DOMAIN": "idp.preview.monk.ai",
64+
3865
"REACT_APP_AUTH_AUDIENCE": "https://api.monk.ai/v1/",
66+
"REACT_APP_AUTH_DOMAIN": "idp.preview.monk.ai",
3967
"REACT_APP_AUTH_CLIENT_ID": "O7geYcPM6zEJrHw0WvQVzSIzw4WzrAtH",
68+
"REACT_APP_API_DOMAIN": "api.preview.monk.ai/v1",
69+
"REACT_APP_THUMBNAIL_DOMAIN": "api.preview.monk.ai/image_resize",
70+
71+
"REACT_APP_AUTH_DOMAIN_US": "acv-staging.us.auth0.com",
72+
"REACT_APP_AUTH_CLIENT_ID_US": "0tIBBTLd4uP52jtF2PcXawWYxW12mUfZ",
73+
"REACT_APP_API_DOMAIN_US": "monk-us-core-api.gateway.staging.acvauctions.com/v1",
74+
"REACT_APP_THUMBNAIL_DOMAIN_US": "monk-us-image.gateway.staging.acvauctions.com/image_resize",
75+
4076
"REACT_APP_SENTRY_DSN": "https://74f50bfe6f11de7aefd54acfa5dfed96@o4505669501648896.ingest.us.sentry.io/4506863461662720",
4177
"REACT_APP_INSPECTION_REPORT_URL": "https://demo-capture.preview.monk.ai"
4278
},
4379
"backend-staging-qa": {
4480
"REACT_APP_ENVIRONMENT": "backend-staging-qa",
4581
"REACT_APP_LIVE_CONFIG_ID": "demo-app-backend-staging-qa",
46-
"REACT_APP_AUTH_DOMAIN": "idp.staging.monk.ai",
82+
4783
"REACT_APP_AUTH_AUDIENCE": "https://api.monk.ai/v1/",
84+
"REACT_APP_AUTH_DOMAIN": "idp.staging.monk.ai",
4885
"REACT_APP_AUTH_CLIENT_ID": "DAeZWqeeOfgItYBcQzFeFwSrlvmUdN7L",
86+
"REACT_APP_API_DOMAIN": "api.preview.monk.ai/v1",
87+
"REACT_APP_THUMBNAIL_DOMAIN": "api.staging.dev.monk.ai/image_resize",
88+
89+
"REACT_APP_AUTH_DOMAIN_US": "acv-staging.us.auth0.com",
90+
"REACT_APP_AUTH_CLIENT_ID_US": "0tIBBTLd4uP52jtF2PcXawWYxW12mUfZ",
91+
"REACT_APP_API_DOMAIN_US": "monk-us-core-api.gateway.staging.acvauctions.com/v1",
92+
"REACT_APP_THUMBNAIL_DOMAIN_US": "monk-us-image.gateway.staging.acvauctions.com/image_resize",
93+
4994
"REACT_APP_SENTRY_DSN": "https://74f50bfe6f11de7aefd54acfa5dfed96@o4505669501648896.ingest.us.sentry.io/4506863461662720",
5095
"REACT_APP_INSPECTION_REPORT_URL": "https://demo-capture.staging.monk.ai"
5196
}

apps/demo-app/src/auth.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { AuthorizationParams } from '@auth0/auth0-react';
2+
import { getEnvOrThrow } from '@monkvision/common';
3+
import { AuthConfig } from '@monkvision/network';
4+
5+
export const AUTHORIZATION_PARAMS: AuthorizationParams = {
6+
redirect_uri: window.location.origin,
7+
audience: getEnvOrThrow('REACT_APP_AUTH_AUDIENCE'),
8+
prompt: 'login',
9+
};
10+
11+
export const authConfigs: AuthConfig[] = [
12+
{
13+
domain: getEnvOrThrow('REACT_APP_AUTH_DOMAIN'),
14+
clientId: getEnvOrThrow('REACT_APP_AUTH_CLIENT_ID'),
15+
apiDomain: getEnvOrThrow('REACT_APP_API_DOMAIN'),
16+
thumbnailDomain: getEnvOrThrow('REACT_APP_THUMBNAIL_DOMAIN'),
17+
authorizationParams: AUTHORIZATION_PARAMS,
18+
},
19+
{
20+
domain: getEnvOrThrow('REACT_APP_AUTH_DOMAIN_US'),
21+
clientId: getEnvOrThrow('REACT_APP_AUTH_CLIENT_ID_US'),
22+
apiDomain: getEnvOrThrow('REACT_APP_API_DOMAIN_US'),
23+
thumbnailDomain: getEnvOrThrow('REACT_APP_THUMBNAIL_DOMAIN_US'),
24+
authorizationParams: AUTHORIZATION_PARAMS,
25+
},
26+
];

apps/demo-app/src/components/App.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import { getEnvOrThrow, MonkProvider } from '@monkvision/common';
33
import { useTranslation } from 'react-i18next';
44
import { LiveConfigAppProvider } from '@monkvision/common-ui-web';
55
import { LiveConfig } from '@monkvision/types';
6+
import { getAuthConfig } from '@monkvision/network';
67
import { Page } from '../pages';
78
import * as config from '../local-config.json';
89
import { AppContainer } from './AppContainer';
10+
import { authConfigs } from '../auth';
911

1012
const localConfig =
1113
process.env['REACT_APP_USE_LOCAL_CONFIG'] === 'true'
@@ -20,6 +22,8 @@ export function App() {
2022
<LiveConfigAppProvider
2123
id={getEnvOrThrow('REACT_APP_LIVE_CONFIG_ID')}
2224
localConfig={localConfig}
25+
apiDomain={getAuthConfig(authConfigs)?.apiDomain}
26+
thumbnailDomain={getAuthConfig(authConfigs)?.thumbnailDomain}
2327
onFetchAuthToken={() => navigate(Page.CREATE_INSPECTION)}
2428
onFetchLanguage={(lang) => i18n.changeLanguage(lang)}
2529
lang={i18n.language}

apps/demo-app/src/index.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,20 @@
11
import ReactDOM from 'react-dom';
22
import { MonitoringProvider } from '@monkvision/monitoring';
33
import { AnalyticsProvider } from '@monkvision/analytics';
4-
import { Auth0Provider } from '@auth0/auth0-react';
5-
import { getEnvOrThrow } from '@monkvision/common';
4+
import { AuthProvider } from '@monkvision/network';
65
import { sentryMonitoringAdapter } from './sentry';
76
import { posthogAnalyticsAdapter } from './posthog';
87
import { AppRouter } from './components';
8+
import { authConfigs } from './auth';
99
import './index.css';
1010
import './i18n';
1111

1212
ReactDOM.render(
1313
<MonitoringProvider adapter={sentryMonitoringAdapter}>
1414
<AnalyticsProvider adapter={posthogAnalyticsAdapter}>
15-
<Auth0Provider
16-
domain={getEnvOrThrow('REACT_APP_AUTH_DOMAIN')}
17-
clientId={getEnvOrThrow('REACT_APP_AUTH_CLIENT_ID')}
18-
authorizationParams={{
19-
redirect_uri: window.location.origin,
20-
audience: getEnvOrThrow('REACT_APP_AUTH_AUDIENCE'),
21-
prompt: 'login',
22-
}}
23-
>
15+
<AuthProvider configs={authConfigs}>
2416
<AppRouter />
25-
</Auth0Provider>
17+
</AuthProvider>
2618
</AnalyticsProvider>
2719
</MonitoringProvider>,
2820
document.getElementById('root'),

apps/demo-app/src/local-config.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
"createInspectionOptions": {
1313
"tasks": ["damage_detection", "wheel_analysis"]
1414
},
15-
"apiDomain": "api.preview.monk.ai/v1",
16-
"thumbnailDomain": "api.preview.monk.ai/image_resize",
1715
"enableTutorial": "first_time_only",
1816
"enableSightTutorial": "modern",
1917
"startTasksOnComplete": true,

configs/test-utils/src/__mocks__/@auth0/auth0-react.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const mockAuth0Provider = ({ children, ...props }: any) => {
2+
(global as any).__auth0ProviderLastProps = props;
3+
return <>{children}</>;
4+
};
5+
6+
export = {
7+
/* Actual exports */
8+
/* Mocks */
9+
useAuth0: jest.fn(() => ({
10+
getAccessTokenWithPopup: jest.fn(() => Promise.resolve('')),
11+
logout: jest.fn(),
12+
})),
13+
Auth0Provider: mockAuth0Provider,
14+
};

configs/test-utils/src/__mocks__/@monkvision/common.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const {
3939
email,
4040
getVehicleModel,
4141
getAspectRatio,
42+
MonkSearchParam,
4243
} = jest.requireActual('@monkvision/common');
4344

4445
export = {
@@ -71,6 +72,7 @@ export = {
7172
email,
7273
getVehicleModel,
7374
getAspectRatio,
75+
MonkSearchParam,
7476

7577
/* Mocks */
7678
useMonkTheme: jest.fn(() => createTheme()),
@@ -148,4 +150,5 @@ export = {
148150
requestCompassPermission: jest.fn(() => Promise.resolve()),
149151
})),
150152
useSafeTimeout: jest.fn(() => jest.fn()),
153+
useMonkSearchParams: jest.fn(() => ({ get: jest.fn(() => null) })),
151154
};

configs/test-utils/src/__mocks__/@monkvision/network.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export = {
3131
decodeMonkJwt: jest.fn((str) => str),
3232
isUserAuthorized: jest.fn(() => true),
3333
isTokenExpired: jest.fn(() => false),
34+
isTokenValid: jest.fn(() => true),
35+
getAuthConfig: jest.fn(),
3436
useAuth: jest.fn(() => ({
3537
authToken: null,
3638
login: jest.fn(() => Promise.resolve('')),

documentation/src/utils/schemas.ts

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
MileageUnit,
1010
MonkApiPermission,
1111
PhotoCaptureSightGuidelinesOption,
12+
PhotoCaptureSightTutorialOption,
1213
PhotoCaptureTutorialOption,
1314
SteeringWheelPosition,
1415
TaskName,
@@ -269,44 +270,57 @@ export const CreateInspectionDiscriminatedUnionSchema = z.discriminatedUnion(
269270

270271
const domainsByEnv = {
271272
staging: {
272-
api: 'api.staging.monk.ai/v1',
273-
thumbnail: 'api.staging.monk.ai/image_resize',
273+
api: ['api.staging.monk.ai/v1', 'monk-us-core-api.gateway.dev.acvauctions.com/v1'],
274+
thumbnail: [
275+
'api.staging.monk.ai/image_resize',
276+
'monk-us-image.gateway.dev.acvauctions.com/image_resize',
277+
],
274278
},
275279
preview: {
276-
api: 'api.preview.monk.ai/v1',
277-
thumbnail: 'api.preview.monk.ai/image_resize',
280+
api: ['api.preview.monk.ai/v1', 'monk-us-core-api.gateway.staging.acvauctions.com/v1'],
281+
thumbnail: [
282+
'api.preview.monk.ai/image_resize',
283+
'monk-us-image.gateway.staging.acvauctions.com/image_resize',
284+
],
278285
},
279286
production: {
280-
api: 'api.monk.ai/v1',
281-
thumbnail: 'api.monk.ai/image_resize',
287+
api: ['api.monk.ai/v1', 'monk-us-core-api.gateway.acvauctions.com/v1'],
288+
thumbnail: ['api.monk.ai/image_resize', 'monk-us-image.gateway.acvauctions.com/image_resize'],
282289
},
283290
};
284291

285-
const apiDomains = Object.values(domainsByEnv).map((env) => env.api) as [string, ...string[]];
286-
const thumbnailDomains = Object.values(domainsByEnv).map((env) => env.thumbnail) as [
292+
const apiDomains = [...new Set(Object.values(domainsByEnv).flatMap((env) => env.api))] as [
287293
string,
288294
...string[],
289295
];
296+
const thumbnailDomains = [
297+
...new Set(Object.values(domainsByEnv).flatMap((env) => env.thumbnail)),
298+
] as [string, ...string[]];
290299

291300
export const DomainsSchema = z
292301
.object({
293-
apiDomain: z.enum(apiDomains),
294-
thumbnailDomain: z.enum(thumbnailDomains),
302+
apiDomain: z.enum(apiDomains).optional(),
303+
thumbnailDomain: z.enum(thumbnailDomains).optional(),
295304
})
296305
.refine(
297306
(data) => {
298-
const apiEnv = Object.values(domainsByEnv).find((env) => env.api === data.apiDomain);
299-
const thumbnailEnv = Object.values(domainsByEnv).find(
300-
(env) => env.thumbnail === data.thumbnailDomain,
307+
const { apiDomain, thumbnailDomain } = data;
308+
309+
if (!apiDomain || !thumbnailDomain) {
310+
return true;
311+
}
312+
313+
const apiEnv = Object.values(domainsByEnv).find((env) => env.api.includes(apiDomain));
314+
const thumbnailEnv = Object.values(domainsByEnv).find((env) =>
315+
env.thumbnail.includes(thumbnailDomain),
301316
);
302-
return !!apiEnv && apiEnv === thumbnailEnv;
317+
318+
return Boolean(apiEnv && thumbnailEnv && apiEnv === thumbnailEnv);
303319
},
304-
(data) => ({
305-
message: `The selected thumbnailDomain must correspond to the selected apiDomain. Please use the corresponding thumbnailDomain: ${
306-
thumbnailDomains[apiDomains.indexOf(data.apiDomain)]
307-
}`,
320+
{
321+
message: 'The selected thumbnailDomain must correspond to the selected apiDomain.',
308322
path: ['thumbnailDomain'],
309-
}),
323+
},
310324
);
311325

312326
export const LiveConfigSchema = z
@@ -329,8 +343,8 @@ export const LiveConfigSchema = z
329343
sightGuidelines: z.array(SightGuidelineSchema).optional(),
330344
enableTutorial: z.nativeEnum(PhotoCaptureTutorialOption).optional(),
331345
allowSkipTutorial: z.boolean().optional(),
332-
enableSightTutorial: z.boolean().optional(),
333-
sightTutorial: z.array(SightGuidelineSchema).optional(),
346+
enableSightTutorial: z.nativeEnum(PhotoCaptureSightTutorialOption).optional(),
347+
sightTutorial: z.array(SightTutorialSchema).optional(),
334348
defaultVehicleType: z.nativeEnum(VehicleType),
335349
allowManualLogin: z.boolean(),
336350
allowVehicleTypeSelection: z.boolean(),

0 commit comments

Comments
 (0)