Skip to content

Commit

Permalink
Merge pull request #832 from magiclabs/PDEEXP-1544-Implement-magic_au…
Browse files Browse the repository at this point in the history
…th_recover_account_provider

Pdeexp 1544 implement magic auth recover account provider
  • Loading branch information
Ethella authored Nov 6, 2024
2 parents 7e2962a + df10123 commit e7f0321
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 60 deletions.
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

0 comments on commit e7f0321

Please sign in to comment.