Skip to content

Commit

Permalink
feat: update atlas login screen flow COMPASS-7755 (#5606)
Browse files Browse the repository at this point in the history
* feat: update the atlas login screen flow COMPASS-7755

* test: remove TOS test cases
  • Loading branch information
alenakhineika committed Mar 22, 2024
1 parent 28f4da7 commit d79e1fc
Show file tree
Hide file tree
Showing 30 changed files with 54 additions and 898 deletions.
3 changes: 0 additions & 3 deletions packages/atlas-service/src/atlas-auth-service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { EventEmitter } from 'events';
import type { AtlasUserConfig } from './user-config-store';
import type { AtlasUserInfo } from './util';

export type ArgsWithSignal<T = Record<string, unknown>> = T & {
Expand All @@ -11,7 +10,6 @@ type AtlasAuthServiceEvents = {
'signed-in': [];
'signed-out': [];
'token-refresh-failed': [];
'user-config-changed': [AtlasUserConfig];
};

type AtlasAuthEventNames = keyof AtlasAuthServiceEvents;
Expand All @@ -30,7 +28,6 @@ export abstract class AtlasAuthService extends EventEmitter {
): Promise<Record<string, string>>;

abstract getUserInfo(opts?: ArgsWithSignal): Promise<AtlasUserInfo>;
abstract updateUserConfig(config: AtlasUserConfig): Promise<void>;

on<T extends AtlasAuthEventNames>(
evt: T,
Expand Down
12 changes: 0 additions & 12 deletions packages/atlas-service/src/compass-atlas-auth-service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,4 @@ describe('CompassAtlasAuthService', function () {
expect(res).to.deep.equal({ id: 1 });
expect(getUserInfoStub.calledOnce).to.be.true;
});

it('calls updateUserConfig on ipc', async function () {
const updateUserConfigStub = sandbox.stub();
const atlasAuthService = getAtlasAuthService({
updateAtlasUserConfig: updateUserConfigStub,
});
await atlasAuthService.updateUserConfig({ enabledAIFeature: false });
expect(updateUserConfigStub.calledOnce).to.be.true;
expect(updateUserConfigStub.firstCall.firstArg).to.deep.equal({
config: { enabledAIFeature: false },
});
});
});
12 changes: 1 addition & 11 deletions packages/atlas-service/src/compass-atlas-auth-service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { AtlasUserConfig } from './user-config-store';
import { ipcRenderer } from 'hadron-ipc';
import type { CompassAuthService as AtlasServiceMain } from './main';
import {
Expand All @@ -12,18 +11,12 @@ import type { ArgsWithSignal, SignInPrompt } from './atlas-auth-service';
export class CompassAtlasAuthService extends AtlasAuthService {
private _ipc = ipcRenderer?.createInvoke<
typeof AtlasServiceMain,
| 'getUserInfo'
| 'isAuthenticated'
| 'signIn'
| 'signOut'
| 'updateAtlasUserConfig'
| 'maybeGetToken'
'getUserInfo' | 'isAuthenticated' | 'signIn' | 'signOut' | 'maybeGetToken'
>('AtlasService', [
'getUserInfo',
'isAuthenticated',
'signIn',
'signOut',
'updateAtlasUserConfig',
'maybeGetToken',
]);

Expand Down Expand Up @@ -62,7 +55,4 @@ export class CompassAtlasAuthService extends AtlasAuthService {
getUserInfo(opts?: ArgsWithSignal) {
return this.ipc.getUserInfo(opts);
}
updateUserConfig(config: AtlasUserConfig) {
return this.ipc.updateAtlasUserConfig({ config });
}
}
18 changes: 16 additions & 2 deletions packages/atlas-service/src/components/ai-signin-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
import { connect } from 'react-redux';
import {
Badge,
Body,
Disclaimer,
Icon,
Link,
MarketingModal,
SpinLoader,
css,
Expand All @@ -15,6 +16,8 @@ import { AISignInImageBanner } from './ai-signin-banner-image';
import type { AtlasSignInState } from '../store/atlas-signin-reducer';
import { closeSignInModal, signIn } from '../store/atlas-signin-reducer';

const GEN_AI_FAQ_LINK = 'https://www.mongodb.com/docs/generative-ai-faq/';

type SignInModalProps = {
isSignInModalVisible?: boolean;
isSignInInProgress?: boolean;
Expand Down Expand Up @@ -43,6 +46,10 @@ const paragraphStyles = css({
marginBottom: spacing[2],
});

const disclaimer = css({
marginTop: spacing[3],
});

const AISignInModal: React.FunctionComponent<SignInModalProps> = ({
isSignInModalVisible = false,
isSignInInProgress = false,
Expand Down Expand Up @@ -97,7 +104,14 @@ const AISignInModal: React.FunctionComponent<SignInModalProps> = ({
MongoDB&apos;s&nbsp; intelligent AI-powered feature, available today
in Compass.
</Body>
<Badge variant="blue">Preview</Badge>
<Disclaimer className={disclaimer}>
This is a feature powered by generative AI, and may give inaccurate
responses. Please see our{' '}
<Link hideExternalIcon={false} href={GEN_AI_FAQ_LINK} target="_blank">
FAQ
</Link>{' '}
for more information.
</Disclaimer>
</div>
</MarketingModal>
);
Expand Down
12 changes: 1 addition & 11 deletions packages/atlas-service/src/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { throwIfNotOk } from './util';
import { EventEmitter } from 'events';
import { createSandboxFromDefaultPreferences } from 'compass-preferences-model';
import type { PreferencesAccess } from 'compass-preferences-model';
import type { AtlasUserConfigStore } from './user-config-store';
import * as util from './util';

function getListenerCount(emitter: EventEmitter) {
Expand Down Expand Up @@ -37,11 +36,6 @@ describe('CompassAuthServiceMain', function () {
}[url];
});

const mockUserConfigStore = {
getUserConfig: sandbox.stub().resolves({}),
updateUserConfig: sandbox.stub().resolves(),
};

const mockOidcPlugin = {
mongoClientOptions: {
authMechanismProperties: {
Expand Down Expand Up @@ -71,7 +65,6 @@ describe('CompassAuthServiceMain', function () {
const fetch = CompassAuthService['fetch'];
const ipcMain = CompassAuthService['ipcMain'];
const createPlugin = CompassAuthService['createMongoDBOIDCPlugin'];
const userStore = CompassAuthService['atlasUserConfigStore'];
const authConfig = CompassAuthService['config'];
let preferences: PreferencesAccess;

Expand All @@ -91,8 +84,6 @@ describe('CompassAuthServiceMain', function () {
};
CompassAuthService['fetch'] = mockFetch as any;
CompassAuthService['createMongoDBOIDCPlugin'] = () => mockOidcPlugin;
CompassAuthService['atlasUserConfigStore'] =
mockUserConfigStore as unknown as AtlasUserConfigStore;

CompassAuthService['config'] = defaultConfig;

Expand All @@ -111,7 +102,6 @@ describe('CompassAuthServiceMain', function () {
// eslint-disable-next-line @typescript-eslint/require-await
afterEach(async function () {
CompassAuthService['fetch'] = fetch;
CompassAuthService['atlasUserConfigStore'] = userStore;
CompassAuthService['ipcMain'] = ipcMain;
CompassAuthService['initPromise'] = null;
CompassAuthService['createMongoDBOIDCPlugin'] = createPlugin;
Expand Down Expand Up @@ -339,7 +329,7 @@ describe('CompassAuthServiceMain', function () {
} as any;
await CompassAuthService.init(preferences);
CompassAuthService['config'] = defaultConfig;
expect(getListenerCount(logger)).to.eq(28);
expect(getListenerCount(logger)).to.eq(27);
// We did all preparations, reset sinon history for easier assertions
sandbox.resetHistory();

Expand Down
37 changes: 2 additions & 35 deletions packages/atlas-service/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import type { AbortSignal as NodeFetchAbortSignal } from 'node-fetch/externals';
import type { RequestInfo, RequestInit, Response } from 'node-fetch';
import nodeFetch from 'node-fetch';
import type { IntrospectInfo, AtlasUserInfo, AtlasServiceConfig } from './util';
import type { AtlasUserConfig } from './user-config-store';
import { throwIfAborted } from '@mongodb-js/compass-utils';
import type { HadronIpcMain } from 'hadron-ipc';
import { ipcMain } from 'hadron-ipc';
Expand All @@ -27,7 +26,6 @@ import {
} from '@mongodb-js/compass-logging';
import type { PreferencesAccess } from 'compass-preferences-model';
import { SecretStore } from './secret-store';
import { AtlasUserConfigStore } from './user-config-store';
import { OidcPluginLogger } from './oidc-plugin-logger';
import { spawn } from 'child_process';
import { getAtlasConfig } from './util';
Expand Down Expand Up @@ -93,8 +91,6 @@ export class CompassAuthService {

private static secretStore = new SecretStore();

private static atlasUserConfigStore = new AtlasUserConfigStore();

private static ipcMain:
| Pick<HadronIpcMain, 'createHandle' | 'handle' | 'broadcast'>
| undefined = ipcMain;
Expand Down Expand Up @@ -173,7 +169,6 @@ export class CompassAuthService {
'isAuthenticated',
'signIn',
'signOut',
'updateAtlasUserConfig',
'maybeGetToken',
]);
}
Expand Down Expand Up @@ -233,12 +228,6 @@ export class CompassAuthService {
this.oidcPluginLogger.on('atlas-service-signed-out', () => {
this.ipcMain?.broadcast('atlas-service-signed-out');
});
this.oidcPluginLogger.on(
'atlas-service-user-config-changed',
(newConfig) => {
this.ipcMain?.broadcast('atlas-service-user-config-changed', newConfig);
}
);
}

static async isAuthenticated({
Expand Down Expand Up @@ -381,34 +370,12 @@ export class CompassAuthService {

const userInfo = (await res.json()) as AtlasUserInfo;

const userConfig = await this.atlasUserConfigStore.getUserConfig(
userInfo.sub
);

return { ...userInfo, ...userConfig };
// TODO: Remove hadcoded `enabledAIFeature: true` when Atlas returns the actual value.
return { ...userInfo, enabledAIFeature: true };
})();
return this.currentUser;
}

static async updateAtlasUserConfig({
config,
}: {
config: Partial<AtlasUserConfig>;
}) {
if (!this.currentUser) {
throw new Error("Can't update user config when not logged in");
}
const newConfig = await this.atlasUserConfigStore.updateUserConfig(
this.currentUser.sub,
config
);
this.currentUser = {
...this.currentUser,
...newConfig,
};
this.oidcPluginLogger.emit('atlas-service-user-config-changed', newConfig);
}

static async introspect({
signal,
tokenType,
Expand Down
14 changes: 1 addition & 13 deletions packages/atlas-service/src/oidc-plugin-logger.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { EventEmitter } from 'events';
import type { MongoDBOIDCPluginOptions } from '@mongodb-js/oidc-plugin';
import type { AtlasUserConfig } from './user-config-store';

type MongoDBOIDCPluginLogger = Required<MongoDBOIDCPluginOptions>['logger'];

Expand Down Expand Up @@ -54,24 +53,13 @@ type OidcPluginLogger = MongoDBOIDCPluginLogger & {
on(evt: 'atlas-service-token-refreshed', fn: () => void): void;
on(evt: 'atlas-service-token-refresh-failed', fn: () => void): void;
on(evt: 'atlas-service-signed-out', fn: () => void): void;
on(
evt: 'atlas-service-user-config-changed',
fn: (newConfig: AtlasUserConfig) => void
): void;

once(evt: 'atlas-service-token-refreshed', fn: () => void): void;
once(evt: 'atlas-service-token-refresh-failed', fn: () => void): void;
once(evt: 'atlas-service-signed-out', fn: () => void): void;
once(
evt: 'atlas-service-user-config-changed',
fn: (newConfig: AtlasUserConfig) => void
): void;
emit(evt: 'atlas-service-token-refreshed'): void;
emit(evt: 'atlas-service-token-refresh-failed'): void;
emit(evt: 'atlas-service-signed-out'): void;
emit(
evt: 'atlas-service-user-config-changed',
newConfig: AtlasUserConfig
): void;
} & Pick<EventEmitter, 'removeAllListeners'>;

export const OidcPluginLogger: { new (): OidcPluginLogger } = EventEmitter;
1 change: 0 additions & 1 deletion packages/atlas-service/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@ export const AtlasAuthPlugin = registerHadronPlugin(
);
export default AtlasAuthPlugin;
export { AtlasServiceError } from './util';
export type { AtlasUserConfig } from './user-config-store';
export type { AtlasUserInfo } from './util';
export { CompassAtlasAuthService } from './compass-atlas-auth-service';
28 changes: 0 additions & 28 deletions packages/atlas-service/src/store/atlas-signin-reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { AnyAction, Reducer } from 'redux';
import type { ThunkAction } from 'redux-thunk';
import { openToast } from '@mongodb-js/compass-components';
import type { AtlasUserInfo } from '../util';
import type { AtlasUserConfig } from '../user-config-store';
import type { AtlasAuthService } from '../provider';
import { throwIfAborted } from '@mongodb-js/compass-utils';

Expand Down Expand Up @@ -51,7 +50,6 @@ export const enum AtlasSignInActions {
Cancel = 'atlas-service/atlas-signin/AtlasSignInCancel',
TokenRefreshFailed = 'atlas-service/atlas-signin/TokenRefreshFailed',
SignedOut = 'atlas-service/atlas-signin/SignedOut',
UserConfigChanged = 'atlas-service/atlas-signin/UserConfigChanged',
}

export type AtlasSignInOpenModalAction = {
Expand Down Expand Up @@ -107,11 +105,6 @@ export type AtlasSignInSignedOutAction = {
type: AtlasSignInActions.SignedOut;
};

export type AtlasSignInUserConfigChangedAction = {
type: AtlasSignInActions.UserConfigChanged;
newConfig: AtlasUserConfig;
};

export type AtlasSignInCancelAction = { type: AtlasSignInActions.Cancel };

const INITIAL_STATE = {
Expand Down Expand Up @@ -297,18 +290,6 @@ const reducer: Reducer<AtlasSignInState> = (
return { ...INITIAL_STATE };
}

if (
isAction<AtlasSignInUserConfigChangedAction>(
action,
AtlasSignInActions.UserConfigChanged
)
) {
if (state.state !== 'success') {
return state;
}
return { ...state, userInfo: { ...state.userInfo, ...action.newConfig } };
}

return state;
};

Expand Down Expand Up @@ -490,13 +471,4 @@ export const signedOut = (): AtlasSignInThunkAction<void> => {
};
};

export const userConfigChanged = (
newConfig: AtlasUserConfig
): AtlasSignInThunkAction<void> => {
return (dispatch, _getState, { atlasAuthService }) => {
dispatch({ type: AtlasSignInActions.UserConfigChanged, newConfig });
atlasAuthService.emit('user-config-changed', newConfig);
};
};

export default reducer;
6 changes: 0 additions & 6 deletions packages/atlas-service/src/store/atlas-signin-store.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import type { AtlasUserConfig } from '../renderer';
import reducer, {
restoreSignInState,
signedOut,
tokenRefreshFailed,
userConfigChanged,
} from './atlas-signin-reducer';
import { type AtlasAuthService } from '../provider';
import { ipcRenderer } from 'hadron-ipc';
Expand All @@ -31,13 +29,10 @@ export function activatePlugin(

const onSignedOut = () => store.dispatch(signedOut);
const onTokenRefreshFailed = () => store.dispatch(tokenRefreshFailed);
const onUserConfigChanged = (_evt: unknown, newConfig: AtlasUserConfig) =>
store.dispatch(userConfigChanged(newConfig));

if (ipcRenderer) {
on(ipcRenderer, 'atlas-service-token-refresh-failed', onSignedOut);
on(ipcRenderer, 'atlas-service-signed-out', onTokenRefreshFailed);
on(ipcRenderer, 'atlas-service-user-config-changed', onUserConfigChanged);
}

addCleanup(() => {
Expand All @@ -47,7 +42,6 @@ export function activatePlugin(
onTokenRefreshFailed
);
ipcRenderer.off('atlas-service-signed-out', onSignedOut);
ipcRenderer.off('atlas-service-user-config-changed', onUserConfigChanged);
}
});

Expand Down
Loading

0 comments on commit d79e1fc

Please sign in to comment.