Skip to content

Commit

Permalink
Revert "fix: add mfa flow to sync/fetch txns personal card (#3316)"
Browse files Browse the repository at this point in the history
This reverts commit 6f2ea44.
  • Loading branch information
sumrender committed Dec 11, 2024
1 parent 350c71b commit 153f80d
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 230 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ export const personalCardQueryParamFiltersData: Partial<GetTasksQueryParamsWithF
queryParams: {
or: [],
btxn_status: 'in.(DEBIT)',
ba_id: 'eq.baccY70V3Mz048',
ba_id: 'eq.baccLesaRlyvLY',
},
});
4 changes: 0 additions & 4 deletions src/app/core/mock-data/personal-cards.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ export const linkedAccountsRes: PersonalCard[] = deepFreeze([
unclassified_count: 2,
update_credentials: false,
updated_at: new Date('2023-03-23T06:31:08.824707'),
yodlee_provider_account_id: '10287109',
},
{
account_number: 'xxxx1069',
Expand All @@ -132,7 +131,6 @@ export const linkedAccountsRes: PersonalCard[] = deepFreeze([
unclassified_count: 0,
update_credentials: false,
updated_at: new Date('2023-01-12T15:57:47.178727'),
yodlee_provider_account_id: '10287109',
},
]);

Expand All @@ -150,7 +148,6 @@ export const linkedAccountRes2: PersonalCard[] = deepFreeze([
last_synced_at: null,
mask: '3201',
account_type: 'SAVINGS',
yodlee_provider_account_id: '10287109',
},
{
id: 'baccCqRv6YdSqZ',
Expand All @@ -165,7 +162,6 @@ export const linkedAccountRes2: PersonalCard[] = deepFreeze([
last_synced_at: null,
mask: '8791',
account_type: 'SAVINGS',
yodlee_provider_account_id: '10287109',
},
]);

Expand Down
1 change: 0 additions & 1 deletion src/app/core/models/personal_card.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ export interface PersonalCard {
unclassified_amount?: number;
unclassified_count?: number;
updated_at: Date;
yodlee_provider_account_id?: string;
}
81 changes: 6 additions & 75 deletions src/app/core/services/personal-cards.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1537,47 +1537,12 @@ describe('PersonalCardsService', () => {
});
});

describe('htmlFormUrl()', () => {
const baseUrl = 'https://repo1.maven.org/maven2';

it('should generate the correct HTML for a normal flow', () => {
const accessToken = '123';
const isMfaFlow = false;

const result = personalCardsService.htmlFormUrl(baseUrl, accessToken, isMfaFlow);
const expectedExtraParams = 'configName=Aggregation&callback=https://www.fylehq.com';
const expectedHtml = `<form id="fastlink-form" name="fastlink-form" action="${baseUrl}" method="POST">
<input name="accessToken" value="Bearer ${accessToken}" hidden="true" />
<input name="extraParams" value="${expectedExtraParams}" hidden="true" />
</form>
<script type="text/javascript">
document.getElementById("fastlink-form").submit();
</script>
`;
const expectedEncodedHtml = 'data:text/html;base64,' + btoa(expectedHtml);

expect(result).toEqual(expectedEncodedHtml);
});

it('should generate the correct HTML for an MFA flow with providerAccountId', () => {
const accessToken = '789';
const isMfaFlow = true;
const providerAccountId = 'test-provider-id';

const result = personalCardsService.htmlFormUrl(baseUrl, accessToken, isMfaFlow, providerAccountId);
const expectedExtraParams = `configName=Aggregation&flow=refresh&providerAccountId=${providerAccountId}&callback=https://www.fylehq.com`;
const expectedHtml = `<form id="fastlink-form" name="fastlink-form" action="${baseUrl}" method="POST">
<input name="accessToken" value="Bearer ${accessToken}" hidden="true" />
<input name="extraParams" value="${expectedExtraParams}" hidden="true" />
</form>
<script type="text/javascript">
document.getElementById("fastlink-form").submit();
</script>
`;
const expectedEncodedHtml = 'data:text/html;base64,' + btoa(expectedHtml);

expect(result).toEqual(expectedEncodedHtml);
});
it('htmlFormUrl(): get html from URL', () => {
const URL = 'https://repo1.maven.org/maven2';

expect(personalCardsService.htmlFormUrl(URL, '123')).toEqual(
'data:text/html;base64,PGZvcm0gaWQ9ImZhc3RsaW5rLWZvcm0iIG5hbWU9ImZhc3RsaW5rLWZvcm0iIGFjdGlvbj0iaHR0cHM6Ly9yZXBvMS5tYXZlbi5vcmcvbWF2ZW4yIiBtZXRob2Q9IlBPU1QiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPSJhY2Nlc3NUb2tlbiIgdmFsdWU9IkJlYXJlciAxMjMiIGhpZGRlbj0idHJ1ZSIgLz4KICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgIG5hbWU9ImV4dHJhUGFyYW1zIiB2YWx1ZT0iY29uZmlnTmFtZT1BZ2dyZWdhdGlvbiZjYWxsYmFjaz1odHRwczovL3d3dy5meWxlaHEuY29tIiBoaWRkZW49InRydWUiIC8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9mb3JtPiAKICAgICAgICAgICAgICAgICAgICAgICAgICA8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImZhc3RsaW5rLWZvcm0iKS5zdWJtaXQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICA8L3NjcmlwdD4KICAgICAgICAgICAgICAgICAgICAgICAgICA='
);
});

describe('getToken()', () => {
Expand All @@ -1603,38 +1568,4 @@ describe('PersonalCardsService', () => {
});
});
});

describe('isMfaEnabled()', () => {
it('should return false when using public api', (done) => {
const personalCardId = '12345';
const usePlatformApi = false;

personalCardsService.isMfaEnabled(personalCardId, usePlatformApi).subscribe((res) => {
expect(res).toBeFalse();
expect(spenderPlatformV1ApiService.post).not.toHaveBeenCalled();
done();
});
});

it('should call platform API usePlatformApi is true', (done) => {
const personalCardId = '12345';
const usePlatformApi = true;
const mockApiResponse = {
data: {
is_mfa_enabled: true,
},
};
spenderPlatformV1ApiService.post.and.returnValue(of(mockApiResponse));

personalCardsService.isMfaEnabled(personalCardId, usePlatformApi).subscribe((res) => {
expect(res).toBeTrue();
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith('/personal_cards/mfa', {
data: {
id: personalCardId,
},
});
done();
});
});
});
});
25 changes: 3 additions & 22 deletions src/app/core/services/personal-cards.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { PersonalCard } from '../models/personal_card.model';
import { YodleeAccessToken } from '../models/yoodle-token.model';
Expand Down Expand Up @@ -55,7 +55,6 @@ export class PersonalCardsService {
last_synced_at: card.yodlee_last_synced_at,
mask: card.card_number.slice(-4),
account_type: card.account_type,
yodlee_provider_account_id: card.yodlee_provider_account_id,
};
return personalCard;
});
Expand Down Expand Up @@ -191,28 +190,10 @@ export class PersonalCardsService {
return this.expenseAggregationService.get('/yodlee/personal/access_token') as Observable<YodleeAccessToken>;
}

isMfaEnabled(personalCardId: string, usePlatformApi): Observable<boolean> {
if (!usePlatformApi) {
return of(false); // TODO sumrender: hack, this will be removed with old personalCards removal in next pr;
}
const payload = {
data: {
id: personalCardId,
},
};
return this.spenderPlatformV1ApiService
.post<PlatformApiResponse<{ is_mfa_enabled: boolean }>>('/personal_cards/mfa', payload)
.pipe(map((res) => res.data.is_mfa_enabled));
}

htmlFormUrl(url: string, accessToken: string, isMfaFlow: boolean, providerAccountId = ''): string {
let extraParams = 'configName=Aggregation&callback=https://www.fylehq.com';
if (isMfaFlow) {
extraParams = `configName=Aggregation&flow=refresh&providerAccountId=${providerAccountId}&callback=https://www.fylehq.com`;
}
htmlFormUrl(url: string, accessToken: string): string {
const pageContent = `<form id="fastlink-form" name="fastlink-form" action="${url}" method="POST">
<input name="accessToken" value="Bearer ${accessToken}" hidden="true" />
<input name="extraParams" value="${extraParams}" hidden="true" />
<input name="extraParams" value="configName=Aggregation&callback=https://www.fylehq.com" hidden="true" />
</form>
<script type="text/javascript">
document.getElementById("fastlink-form").submit();
Expand Down
105 changes: 33 additions & 72 deletions src/app/fyle/personal-cards/personal-cards.page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ describe('PersonalCardsPage', () => {
'generateCreditParams',
'generateDateParams',
'getMatchedExpensesSuggestions',
'isMfaEnabled',
]);
const networkServiceSpy = jasmine.createSpyObj('NetworkService', ['connectivityWatcher', 'isOnline']);
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
Expand Down Expand Up @@ -215,7 +214,6 @@ describe('PersonalCardsPage', () => {
launchDarklyService.getVariation.and.returnValue(of(false));
personalCardsService.getPersonalCardsCount.and.returnValue(of(2));
personalCardsService.getPersonalCards.and.returnValue(of(linkedAccountsRes));
personalCardsService.isMfaEnabled.and.returnValue(of(false));
component.loadData$ = new BehaviorSubject({
pageNumber: 1,
});
Expand Down Expand Up @@ -267,7 +265,7 @@ describe('PersonalCardsPage', () => {
expect(loaderService.showLoader).toHaveBeenCalledTimes(1);
expect(loaderService.hideLoader).toHaveBeenCalledTimes(1);
expect(personalCardsService.getToken).toHaveBeenCalledTimes(1);
expect(component.openYoodle).toHaveBeenCalledOnceWith(apiToken.fast_link_url, apiToken.access_token, false);
expect(component.openYoodle).toHaveBeenCalledOnceWith(apiToken.fast_link_url, apiToken.access_token);
}));

describe('postAccounts():', () => {
Expand Down Expand Up @@ -351,10 +349,10 @@ describe('PersonalCardsPage', () => {
});
spyOn(component.loadData$, 'next');

component.onCardChanged(linkedAccountsRes[0]);
component.onCardChanged('eq.baccLesaRlyvLY');

expect(component.loadData$.next).toHaveBeenCalledOnceWith({
queryParams: { btxn_status: 'in.(INITIALIZED)', ba_id: 'eq.baccY70V3Mz048' },
queryParams: { btxn_status: 'in.(INITIALIZED)', ba_id: 'eq.eq.baccLesaRlyvLY' },
pageNumber: 1,
});
expect(component.loadData$.getValue).toHaveBeenCalledTimes(1);
Expand All @@ -366,10 +364,10 @@ describe('PersonalCardsPage', () => {
});
spyOn(component.loadData$, 'next');

component.onCardChanged(linkedAccountsRes[0]);
component.onCardChanged('eq.baccLesaRlyvLY');

expect(component.loadData$.next).toHaveBeenCalledOnceWith({
queryParams: { btxn_status: 'in.(INITIALIZED)', ba_id: 'eq.baccY70V3Mz048' },
queryParams: { btxn_status: 'in.(INITIALIZED)', ba_id: 'eq.eq.baccLesaRlyvLY' },
pageNumber: 1,
});
expect(component.loadData$.getValue).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -481,7 +479,6 @@ describe('PersonalCardsPage', () => {

it('fetchNewTransactions(): should fetch new transactions', () => {
component.selectionMode = true;
component.selectedAccount = linkedAccountsRes[0];
spyOn(component, 'switchSelectionMode');
personalCardsService.syncTransactions.and.returnValue(of(apiPersonalCardTxnsRes));

Expand Down Expand Up @@ -846,7 +843,7 @@ describe('PersonalCardsPage', () => {
it('addNewFiltersToParams(): should new filters to params', () => {
spyOn(component.loadData$, 'getValue').and.returnValue({});
component.selectedTransactionType = 'DEBIT';
component.selectedAccount = linkedAccountsRes[0];
component.selectedAccount = 'baccLesaRlyvLY';

const result = component.addNewFiltersToParams();
expect(result).toEqual(personalCardQueryParamFiltersData);
Expand Down Expand Up @@ -878,70 +875,34 @@ describe('PersonalCardsPage', () => {
expect(personalCardsService.generateFilterPills).toHaveBeenCalledOnceWith({});
}));

describe('openYoodle()', () => {
let inappbrowserSpy: any;

beforeEach(() => {
component.selectedAccount = linkedAccountsRes[0];
inappbrowserSpy = jasmine.createSpyObj('InAppBrowserObject', ['on', 'close']);
});
it('openYoodle(): should open yoodle', fakeAsync(() => {
personalCardsService.htmlFormUrl.and.returnValue('<h1></h1>');
spyOn(window, 'decodeURIComponent').and.returnValue(
JSON.stringify([
{
requestId: 'tx3qHxFNgRcZ',
},
])
);
const inappborwserSpy = jasmine.createSpyObj('InAppBrowserObject', ['on', 'close']);
inappborwserSpy.on.withArgs('loadstop').and.returnValue(of(null));
inappborwserSpy.on.withArgs('loadstart').and.returnValue(
of({
url: 'https://www.fylehq.com',
})
);
inAppBrowserService.create.and.returnValue(inappborwserSpy);
spyOn(component, 'postAccounts');

it('should open Yoodle with normal flow and handle success callback', fakeAsync(() => {
const mockUrl = 'https://mock-url.com';
const mockAccessToken = 'mock_access_token';
const mockHtmlContent = '<h1></h1>';
const mockDecodedData = JSON.stringify([{ requestId: 'tx3qHxFNgRcZ' }]);

personalCardsService.htmlFormUrl.and.returnValue(mockHtmlContent);
spyOn(window, 'decodeURIComponent').and.returnValue(mockDecodedData);
inappbrowserSpy.on.withArgs('loadstop').and.returnValue(of(null));
inappbrowserSpy.on.withArgs('loadstart').and.returnValue(
of({
url: 'https://www.fylehq.com',
})
);
inAppBrowserService.create.and.returnValue(inappbrowserSpy);
spyOn(component, 'postAccounts');

component.openYoodle(mockUrl, mockAccessToken, false);
tick(20000);

expect(personalCardsService.htmlFormUrl).toHaveBeenCalledOnceWith(mockUrl, mockAccessToken, false, '10287109');
expect(inAppBrowserService.create).toHaveBeenCalledOnceWith(mockHtmlContent, '_blank', 'location=no');
expect(inappbrowserSpy.on).toHaveBeenCalledTimes(2);
expect(window.decodeURIComponent).toHaveBeenCalledTimes(1);
expect(component.postAccounts).toHaveBeenCalledOnceWith(['tx3qHxFNgRcZ']);
expect(inappbrowserSpy.close).toHaveBeenCalled();
}));
component.openYoodle(apiToken.fast_link_url, apiToken.access_token);
tick(20000);

it('should handle MFA flow and sync transactions on success', fakeAsync(() => {
const mockUrl = 'https://mock-url.com';
const mockAccessToken = 'mock_access_token';
const mockHtmlContent = '<h1></h1>';
const mockDecodedData = JSON.stringify([{ requestId: 'tx3qHxFNgRcZ' }]);

personalCardsService.htmlFormUrl.and.returnValue(mockHtmlContent);
spyOn(window, 'decodeURIComponent').and.returnValue(mockDecodedData);
inappbrowserSpy.on.withArgs('loadstop').and.returnValue(of(null));
inappbrowserSpy.on.withArgs('loadstart').and.returnValue(
of({
url: 'https://www.fylehq.com',
})
);
inAppBrowserService.create.and.returnValue(inappbrowserSpy);
spyOn(component, 'syncTransactions');

component.openYoodle(mockUrl, mockAccessToken, true);
tick(20000);

expect(personalCardsService.htmlFormUrl).toHaveBeenCalledOnceWith(mockUrl, mockAccessToken, true, '10287109');
expect(inAppBrowserService.create).toHaveBeenCalledOnceWith(mockHtmlContent, '_blank', 'location=no');
expect(inappbrowserSpy.on).toHaveBeenCalledTimes(2);
expect(window.decodeURIComponent).toHaveBeenCalledTimes(1);
expect(component.syncTransactions).toHaveBeenCalledTimes(1);
expect(inappbrowserSpy.close).toHaveBeenCalled();
}));
});
expect(personalCardsService.htmlFormUrl).toHaveBeenCalledOnceWith(apiToken.fast_link_url, apiToken.access_token);
expect(inappborwserSpy.on).toHaveBeenCalledTimes(2);
expect(inAppBrowserService.create).toHaveBeenCalledTimes(1);
expect(window.decodeURIComponent).toHaveBeenCalledTimes(1);
expect(component.postAccounts).toHaveBeenCalledOnceWith(['tx3qHxFNgRcZ']);
}));
});

describe('ngOnInit():', () => {
Expand Down Expand Up @@ -1099,7 +1060,7 @@ describe('PersonalCardsPage', () => {
subject.next(linkedAccountsRes);

component.linkedAccounts$.subscribe(() => {
expect(component.onCardChanged).toHaveBeenCalledWith(linkedAccountsRes[0]);
expect(component.onCardChanged).toHaveBeenCalledWith(linkedAccountsRes[0].id);
done();
});
});
Expand Down
Loading

0 comments on commit 153f80d

Please sign in to comment.