Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pdeexp 1544 implement magic auth recover account provider #832

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions packages/@magic-sdk/provider/src/modules/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
RecencyCheckEventEmit,
RecoveryFactorEventHandlers,
RecoveryFactorEventEmit,
RecoverAccountEventHandlers,
RecoverAccountEventEmit,
} from '@magic-sdk/types';
import { getItem, setItem, removeItem } from '../util/storage';
import { BaseModule } from './base-module';
Expand Down Expand Up @@ -143,11 +145,26 @@ export class UserModule extends BaseModule {
}

public recoverAccount(configuration: RecoverAccountConfiguration) {
const { email, showUI } = configuration;
const requestPayload = createJsonRpcRequestPayload(
this.sdk.testMode ? MagicPayloadMethod.RecoverAccountTestMode : MagicPayloadMethod.RecoverAccount,
[configuration],
[{ email, showUI }],
);
return this.request<boolean | null>(requestPayload);
const handle = this.request<string | boolean | null, RecoverAccountEventHandlers>(requestPayload);

if (!showUI && handle) {
handle.on(RecoverAccountEventEmit.Cancel, () => {
this.createIntermediaryEvent(RecoverAccountEventEmit.Cancel, requestPayload.id as string)();
});
handle.on(RecoverAccountEventEmit.ResendSms, () => {
this.createIntermediaryEvent(RecoverAccountEventEmit.ResendSms, requestPayload.id as string)();
});
handle.on(RecoverAccountEventEmit.VerifyOtp, (otp: string) => {
this.createIntermediaryEvent(RecoverAccountEventEmit.VerifyOtp, requestPayload.id as string)(otp);
});
}

return handle;
}

public revealPrivateKey() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,69 @@ test('Generate JSON RPC request payload with method `magic_auth_recover_account`
const magic = createMagicSDK();
magic.user.request = jest.fn();

await magic.user.recoverAccount({ email: 'test' });
await magic.user.recoverAccount({ email: 'test', showUI: false });

const requestPayload = magic.user.request.mock.calls[0][0];
expect(requestPayload.jsonrpc).toBe('2.0');
expect(requestPayload.method).toBe('magic_auth_recover_account');
expect(requestPayload.params).toEqual([{ email: 'test' }]);
expect(requestPayload.params).toEqual([{ email: 'test', showUI: false }]);
});

test('If `testMode` is enabled, testing-specific RPC method is used', async () => {
const magic = createMagicSDKTestMode();
magic.user.request = jest.fn();

await magic.user.recoverAccount({ email: 'test' });
await magic.user.recoverAccount({ email: 'test', showUI: false });

const requestPayload = magic.user.request.mock.calls[0][0];
expect(requestPayload.jsonrpc).toBe('2.0');
expect(requestPayload.method).toBe('magic_auth_recover_account_testing_mode');
expect(requestPayload.params).toEqual([{ email: 'test' }]);
expect(requestPayload.params).toEqual([{ email: 'test', showUI: false }]);
});

test('method should return a PromiEvent', () => {
const magic = createMagicSDK();
expect(isPromiEvent(magic.user.recoverAccount({ email: 'test' }))).toBeTruthy();
expect(isPromiEvent(magic.user.recoverAccount({ email: 'test', showUI: false }))).toBeTruthy();
});

test('method should create intermediary event on cancel', () => {
const magic = createMagicSDK();
magic.user.overlay.post = jest.fn().mockImplementation(() => new Promise(() => {}));
const createIntermediaryEventFn = jest.fn();
magic.user.createIntermediaryEvent = jest.fn().mockImplementation(() => createIntermediaryEventFn);

const handle = magic.user.recoverAccount({ email: 'test', showUI: false });
handle.emit('cancel');

const cancelEvent = magic.user.createIntermediaryEvent.mock.calls[0][0];

expect(cancelEvent).toBe('cancel');
});

test('method should create intermediary event on ResendSms', () => {
const magic = createMagicSDK();
magic.user.overlay.post = jest.fn().mockImplementation(() => new Promise(() => {}));
const createIntermediaryEventFn = jest.fn();
magic.user.createIntermediaryEvent = jest.fn().mockImplementation(() => createIntermediaryEventFn);

const handle = magic.user.recoverAccount({ email: 'test', showUI: false });
handle.emit('resend-sms-otp');

const resendEvent = magic.user.createIntermediaryEvent.mock.calls[0][0];

expect(resendEvent).toBe('resend-sms-otp');
});

test('method should create intermediary event on VerifyOtp', () => {
const magic = createMagicSDK();
magic.user.overlay.post = jest.fn().mockImplementation(() => new Promise(() => {}));
const createIntermediaryEventFn = jest.fn();
magic.user.createIntermediaryEvent = jest.fn().mockImplementation(() => createIntermediaryEventFn);

const handle = magic.user.recoverAccount({ email: 'test', showUI: false });
handle.emit('verify-otp-code');

const verifyEvent = magic.user.createIntermediaryEvent.mock.calls[0][0];

expect(verifyEvent).toBe('verify-otp-code');
});
12 changes: 10 additions & 2 deletions packages/@magic-sdk/types/src/modules/intermediary-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ import { NftCheckoutIntermediaryEvents } from './nft-types';

import { WalletEventOnReceived } from './wallet-types';
import { UiEventsEmit } from './common-types';
import { RecoveryFactorEventEmit, RecoveryFactorEventOnReceived } from './user-types';
import {
RecoverAccountEventEmit,
RecoverAccountEventOnReceived,
RecoveryFactorEventEmit,
RecoveryFactorEventOnReceived,
} from './user-types';

export type IntermediaryEvents =
// EmailOTP
Expand Down Expand Up @@ -60,4 +65,7 @@ export type IntermediaryEvents =
| `${EnableMFAEventEmit}`
// Disable MFA Events
| `${DisableMFAEventOnReceived}`
| `${DisableMFAEventEmit}`;
| `${DisableMFAEventEmit}`
// Recover Account Events
| `${RecoverAccountEventOnReceived}`
| `${RecoverAccountEventEmit}`;
33 changes: 33 additions & 0 deletions packages/@magic-sdk/types/src/modules/user-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export interface RecoverAccountConfiguration {
* The email to recover
*/
email: string;
showUI: boolean;
}

export interface ShowSettingsConfiguration {
Expand All @@ -113,3 +114,35 @@ export interface ShowSettingsConfiguration {
page: DeepLinkPage;
showUI?: boolean;
}

export enum RecoverAccountEventOnReceived {
SmsOtpSent = 'sms-otp-sent',
LoginThrottled = 'login-throttled',
InvalidSmsOtp = 'invalid-sms-otp',
SmsVerified = 'sms-verified',
}

export enum RecoverAccountEventEmit {
Cancel = 'cancel',
VerifyOtp = 'verify-otp-code',
ResendSms = 'resend-sms-otp',
}

export type RecoverAccountEventHandlers = {
// Event Received
[RecoverAccountEventEmit.Cancel]: () => void;
[RecoverAccountEventEmit.VerifyOtp]: (otp: string) => void;
[RecoverAccountEventEmit.ResendSms]: () => void;

// Event sent
[RecoverAccountEventOnReceived.SmsOtpSent]: ({ phoneNumber }: { phoneNumber: string }) => void;
[RecoverAccountEventOnReceived.LoginThrottled]: (error: string) => {};
[RecoverAccountEventOnReceived.InvalidSmsOtp]: ({
errorMessage,
errorCode,
}: {
errorMessage: string;
errorCode: string;
}) => {};
[RecoverAccountEventOnReceived.SmsVerified]: () => {};
};
Loading
Loading