Skip to content

Commit

Permalink
Merge pull request #311 from g-ongenae/feature/cleaning
Browse files Browse the repository at this point in the history
Remove v1 events and references
  • Loading branch information
Charles Coeurderoy authored Jun 28, 2021
2 parents 8ebe81a + cac7048 commit c4601ec
Show file tree
Hide file tree
Showing 21 changed files with 109 additions and 792 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ To configure your application properly, here is a list of key to set:
| `eventList` | No | _array<string>_ | Event List you want to subscribe to |
| `restHooksSecret` | No | _string_ | Resthooks secrets ensuring that all calls are made by Algoan. See [the documentation](https://developers.algoan.com/public/docs/algoan_documentation/resthooks_and_events/resthooks.html#validating-resthook-events) for more information |
| `port` | No | _number_ | Application networking port |
| `banksUserIdPassword` | Yes | _string_ | Password used to encrypt the banks user identifier to authenticate to Bridge. **Ensure that your password is hidden in your production environment** |
| `customerIdPassword` | Yes | _string_ | Password used to encrypt the banks user identifier to authenticate to Bridge. **Ensure that your password is hidden in your production environment** |

_NOTE_: Default values are defined in the [`config/default.json`](./config/default.json) file.

Expand Down
6 changes: 3 additions & 3 deletions config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
"targetUrl": "http://localhost:8080/hooks",
"eventList": [
"service_account_created",
"bankreader_required",
"bankreader_link_required"
"bank_details_required",
"aggregator_link_required"
],
"restHooksSecret": "",
"port": 8080,
"banksUserIdPassword": "",
"customerIdPassword": "",
"activateBridgeRequestInterceptor": true
}
2 changes: 1 addition & 1 deletion config/env/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"synchronizationWaitingTime": 0,
"synchronizationTimeout": 2
},
"banksUserIdPassword": "random_pass"
"customerIdPassword": "random_pass"
}
2 changes: 1 addition & 1 deletion src/aggregator/aggregator.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CacheModule, HttpModule, Inject, Module } from '@nestjs/common';
import { CacheModule, HttpModule, Module } from '@nestjs/common';
import { AlgoanModule } from '../algoan/algoan.module';
import { AggregatorService } from './services/aggregator.service';
import { BridgeClient } from './services/bridge/bridge.client';
Expand Down
90 changes: 47 additions & 43 deletions src/aggregator/services/aggregator.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { BanksUser, BanksUserStatus, RequestBuilder } from '@algoan/rest';
import { CACHE_MANAGER, CacheModule, HttpModule, HttpStatus } from '@nestjs/common';
import { CacheModule, HttpModule, HttpStatus } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { createHmac } from 'crypto';
import { v4 as uuidV4 } from 'uuid';
import { customerMock } from '../../algoan/dto/customer.objects.mock';

import { AlgoanModule } from '../../algoan/algoan.module';
import { AppModule } from '../../app.module';
Expand All @@ -13,22 +12,6 @@ import { BridgeClient } from './bridge/bridge.client';
describe('AggregatorService', () => {
let service: AggregatorService;
let client: BridgeClient;
let cacheManager: any;
let uuid: string = uuidV4();
const callbackUrl: string = `http://algoan.com/callback/2/${uuid}`;
const mockBanksUser = new BanksUser(
{
id: 'mockBanksUserId',
status: BanksUserStatus.ACCOUNTS_SYNCHRONIZED,
redirectUrl: 'mockRedirectUrl',
redirectUrlCreatedAt: 123456789,
redirectUrlTTL: 100,
callbackUrl,
scores: [],
analysis: { alerts: [], regularCashFlows: [], reliability: 'HIGH' },
},
new RequestBuilder('mockBaseURL', { clientId: 'mockClientId' }),
);

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
Expand All @@ -38,7 +21,6 @@ describe('AggregatorService', () => {

service = module.get<AggregatorService>(AggregatorService);
client = module.get<BridgeClient>(BridgeClient);
cacheManager = module.get<any>(CACHE_MANAGER);
});

it('should be defined', () => {
Expand All @@ -64,24 +46,31 @@ describe('AggregatorService', () => {
redirect_url: 'https://bridge/redirection-url',
});

const redirectUrl = await service.generateRedirectUrl(mockBanksUser.id, mockBanksUser.callbackUrl);
const expectedPassword: string = createHmac('sha256', 'random_pass').update('mockBanksUserId').digest('hex');
const redirectUrl = await service.generateRedirectUrl(
customerMock.id,
customerMock.aggregationDetails.callbackUrl,
);
const expectedPassword: string = createHmac('sha256', 'random_pass').update(customerMock.id).digest('hex');
expect(registerSpy).toHaveBeenCalledWith(
{
email: 'mockBanksUserId@algoan-bridge.com',
email: `${customerMock.id}@algoan-bridge.com`,
password: expectedPassword,
},
undefined,
);
expect(authenticateSpy).toHaveBeenCalledWith(
{
email: 'mockBanksUserId@algoan-bridge.com',
email: `${customerMock.id}@algoan-bridge.com`,
password: expectedPassword,
},
undefined,
);
const extractedUuid: string = uuid.replace(/-/g, 'z');
expect(connectItemSpy).toHaveBeenCalledWith('access-token', extractedUuid, undefined, undefined);
expect(connectItemSpy).toHaveBeenCalledWith(
'access-token',
customerMock.aggregationDetails.callbackUrl,
undefined,
undefined,
);
expect(redirectUrl).toBe('https://bridge/redirection-url');
});
it('should create and setup an account and return the redirect link', async () => {
Expand All @@ -105,28 +94,35 @@ describe('AggregatorService', () => {
redirect_url: 'https://bridge/redirection-url',
});

const redirectUrl = await service.generateRedirectUrl(mockBanksUser.id, mockBanksUser.callbackUrl);
const expectedPassword: string = createHmac('sha256', 'random_pass').update('mockBanksUserId').digest('hex');
const redirectUrl = await service.generateRedirectUrl(
customerMock.id,
customerMock.aggregationDetails.callbackUrl,
);
const expectedPassword: string = createHmac('sha256', 'random_pass').update(customerMock.id).digest('hex');
expect(registerSpy).toHaveBeenCalledWith(
{
email: 'mockBanksUserId@algoan-bridge.com',
email: `${customerMock.id}@algoan-bridge.com`,
password: expectedPassword,
},
undefined,
);
expect(authenticateSpy).toHaveBeenCalledWith(
{
email: 'mockBanksUserId@algoan-bridge.com',
email: `${customerMock.id}@algoan-bridge.com`,
password: expectedPassword,
},
undefined,
);
const extractedUuid: string = uuid.replace(/-/g, 'z');
expect(connectItemSpy).toHaveBeenCalledWith('access-token', extractedUuid, undefined, undefined);
expect(connectItemSpy).toHaveBeenCalledWith(
'access-token',
customerMock.aggregationDetails.callbackUrl,
undefined,
undefined,
);
expect(redirectUrl).toBe('https://bridge/redirection-url');
});

it('should create and setup an account and return the redirect link with a prefill email', async () => {
it('should create and setup an account and return the redirect link with a pre-fill email', async () => {
const email: string = 'test@test.com';
const registerSpy = jest.spyOn(client, 'register').mockResolvedValueOnce({
uuid: '79c8961c-bdf7-11e5-88a3-4f2c2aec0665',
Expand All @@ -148,24 +144,32 @@ describe('AggregatorService', () => {
redirect_url: 'https://bridge/redirection-url',
});

const redirectUrl = await service.generateRedirectUrl(mockBanksUser.id, mockBanksUser.callbackUrl, email);
const expectedPassword: string = createHmac('sha256', 'random_pass').update('mockBanksUserId').digest('hex');
const redirectUrl = await service.generateRedirectUrl(
customerMock.id,
customerMock.aggregationDetails.callbackUrl,
email,
);
const expectedPassword: string = createHmac('sha256', 'random_pass').update(customerMock.id).digest('hex');
expect(registerSpy).toHaveBeenCalledWith(
{
email: 'mockBanksUserId@algoan-bridge.com',
email: `${customerMock.id}@algoan-bridge.com`,
password: expectedPassword,
},
undefined,
);
expect(authenticateSpy).toHaveBeenCalledWith(
{
email: 'mockBanksUserId@algoan-bridge.com',
email: `${customerMock.id}@algoan-bridge.com`,
password: expectedPassword,
},
undefined,
);
const extractedUuid: string = uuid.replace(/-/g, 'z');
expect(connectItemSpy).toHaveBeenCalledWith('access-token', extractedUuid, email, undefined);
expect(connectItemSpy).toHaveBeenCalledWith(
'access-token',
customerMock.aggregationDetails.callbackUrl,
email,
undefined,
);
expect(redirectUrl).toBe('https://bridge/redirection-url');
});

Expand Down Expand Up @@ -196,12 +200,12 @@ describe('AggregatorService', () => {

it('should get the accessToken', async () => {
const spy = jest.spyOn(client, 'authenticate').mockReturnValue(Promise.resolve(mockAuthResponse));
const accessToken = (await service.getAccessToken(mockBanksUser.id)).access_token;
const expectedPassword: string = createHmac('sha256', 'random_pass').update('mockBanksUserId').digest('hex');
const accessToken = (await service.getAccessToken(customerMock.id)).access_token;
const expectedPassword: string = createHmac('sha256', 'random_pass').update(customerMock.id).digest('hex');

expect(spy).toBeCalledWith(
{
email: 'mockBanksUserId@algoan-bridge.com',
email: `${customerMock.id}@algoan-bridge.com`,
password: expectedPassword,
},
undefined,
Expand All @@ -212,7 +216,7 @@ describe('AggregatorService', () => {
it('should get the resource name', async () => {
const spy = jest.spyOn(client, 'getResourceName').mockReturnValue(Promise.resolve('mockResourceName'));
const token = 'token';
const resourceUri = 'mockResoruceUri';
const resourceUri = 'mockResourceUri';
await service.getResourceName(token, resourceUri);

expect(spy).toBeCalledWith(token, resourceUri, undefined);
Expand Down
11 changes: 6 additions & 5 deletions src/aggregator/services/aggregator.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export class AggregatorService {
/**
* Create the Bridge Webview url base on the client and it's callbackUrl
*
* @param banksUser The bank user for which we generate the redirectUrl
* @param id id of the customer to generate a redirectUrl
* @param callbackUrl callback url of the redirect url
*/
public async generateRedirectUrl(
id: string,
Expand Down Expand Up @@ -84,7 +85,7 @@ export class AggregatorService {
/**
* Returns the Bridge Access Token for a User
*
* @param banksUser The bank user for which we generate the redirectUrl
* @param id id of the customer
*/
public async getAccessToken(id: string, clientConfig?: ClientConfig): Promise<AuthenticationResponse> {
return this.bridgeClient.authenticate(AggregatorService.buildCredentials(id), clientConfig);
Expand All @@ -109,7 +110,7 @@ export class AggregatorService {

/**
* Delete a user from Bridge
* @param banksUser
* @param params.id id of the customer
*/
public async deleteUser(
params: { bridgeUserId: string; accessToken: string; id: string },
Expand All @@ -131,10 +132,10 @@ export class AggregatorService {
* Build Bridge account credentials for a BankUser
* https://docs.bridgeapi.io/docs/user-creation
*
* @param banksUser
* @param id id of the customer
*/
private static buildCredentials(id: string): UserAccount {
const password: string = config.banksUserIdPassword;
const password: string = config.customerIdPassword;
let hash: string = createHmac('sha256', password).update(id).digest('hex');
const maxPasswordLength: number = 72;

Expand Down
4 changes: 2 additions & 2 deletions src/aggregator/services/bridge/bridge-v2.utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('Bridge Utils for Algoan v2 (Customer, Analysis)', () => {
.mockReturnValue(Promise.resolve('mockResourceName'));
});

it('should map the bridge account to a banksUser', async () => {
it("should map the bridge account to algoan customer's account", async () => {
const expectedAccounts: Account[] = [
{
balance: 100,
Expand Down Expand Up @@ -62,7 +62,7 @@ describe('Bridge Utils for Algoan v2 (Customer, Analysis)', () => {
expect(mappedAccount).toEqual(expectedAccounts);
});

it('should map the bridge transactions to banksUser', async () => {
it("should map the bridge transactions to algoan customer's transactions", async () => {
const expectedTransaction: AccountTransaction[] = [
{
dates: { debitedAt: '2019-04-06T13:53:12.000Z' },
Expand Down
8 changes: 4 additions & 4 deletions src/aggregator/services/bridge/bridge-v2.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ClientConfig } from './bridge.client';

/**
* mapBridgeAccount transforms a bridge array of accounts into
* an array of Banks User accounts
* an array of algoan v2 accounts
* @param accounts array of accounts from Bridge
* @param accessToken permanent access token for Bridge api
*/
Expand Down Expand Up @@ -103,14 +103,14 @@ const ACCOUNT_TYPE_MAPPING: AccountTypeMapping = {
};

/**
* mapAccountType map the banksUser type from the bridge type
* mapAccountType map the algoan v2 type from the bridge type
* @param accountType bridge type
*/
// eslint-disable-next-line no-null/no-null
const mapAccountType = (accountType: BridgeAccountType): AccountType => ACCOUNT_TYPE_MAPPING[accountType] || null;

/**
* mapUsageType map the banksUser usage from the bridge type
* mapUsageType map the algoan v2 usage from the bridge type
* @param isPro Bridge boolean
*/
const mapUsageType = (isPro: boolean): AccountUsage => (isPro ? AccountUsage.PROFESSIONAL : AccountUsage.PERSONAL);
Expand All @@ -133,7 +133,7 @@ const mapUserInfo = (itemId: number, userInfo: BridgeUserInformation[]): Account

/**
* mapBridgeTransactions transforms a bridge transaction wrapper into
* an array of banks user transactions
* an array of algoan v2 transactions
*
* @param bridgeTransactions TransactionWrapper from Bridge
* @param accessToken permanent access token for Bridge api
Expand Down
Loading

0 comments on commit c4601ec

Please sign in to comment.