Skip to content

Commit

Permalink
feat(api): add alert endpoints for transfer check (#484)
Browse files Browse the repository at this point in the history
  • Loading branch information
balzdur authored Jun 26, 2024
1 parent dd76f57 commit aa611a5
Show file tree
Hide file tree
Showing 7 changed files with 545 additions and 8 deletions.
100 changes: 100 additions & 0 deletions packages/app-builder/src/models/transfer-alert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {
type CreateTransferAlertDto,
type TransferAlertDto,
type UpdateTransferAlertDto,
} from 'marble-api/generated/transfercheck-api';

export type TransferAlerStatus = 'unread' | 'read' | 'archived';

export type TransferAlertType = 'sender' | 'beneficiary';

export interface TransferAlert {
id: string;
type: TransferAlertType;
transferId: string;
senderPartnerId: string;
beneficiaryPartnerId: string;
createdAt: string;
status: TransferAlerStatus;
message: string;
transferEndToEndId: string;
beneficiaryIban: string;
senderIban: string;
}

export function adaptTransferAlert(
dto: TransferAlertDto,
partnerId: string,
): TransferAlert {
let type: TransferAlertType;
if (dto.sender_partner_id === partnerId) {
type = 'sender';
} else if (dto.beneficiary_partner_id === partnerId) {
type = 'beneficiary';
} else {
throw new Error('Invalid partner id');
}
return {
id: dto.id,
transferId: dto.transfer_id,
type,
senderPartnerId: dto.sender_partner_id,
beneficiaryPartnerId: dto.beneficiary_partner_id,
createdAt: dto.created_at,
status: dto.status,
message: dto.message,
transferEndToEndId: dto.transfer_end_to_end_id,
beneficiaryIban: dto.beneficiary_iban,
senderIban: dto.sender_iban,
};
}

export interface CreateTransferAlert {
transferId: string;
message: string;
transferEndToEndId: string;
beneficiaryIban: string;
senderIban: string;
}

export function adaptCreateTransferAlertDto(
createTransferAlert: CreateTransferAlert,
): CreateTransferAlertDto {
return {
transfer_id: createTransferAlert.transferId,
message: createTransferAlert.message,
transfer_end_to_end_id: createTransferAlert.transferEndToEndId,
beneficiary_iban: createTransferAlert.beneficiaryIban,
sender_iban: createTransferAlert.senderIban,
};
}

export type UpdateTransferAlert =
| {
type: 'sender';
message: string;
transferEndToEndId: string;
beneficiaryIban: string;
senderIban: string;
}
| {
type: 'beneficiary';
status: TransferAlerStatus;
};

export function adaptUpdateTransferAlertDto(
updateTransferAlert: UpdateTransferAlert,
): UpdateTransferAlertDto {
if (updateTransferAlert.type === 'sender') {
return {
message: updateTransferAlert.message,
transfer_end_to_end_id: updateTransferAlert.transferEndToEndId,
beneficiary_iban: updateTransferAlert.beneficiaryIban,
sender_iban: updateTransferAlert.senderIban,
};
} else {
return {
status: updateTransferAlert.status,
};
}
}
6 changes: 4 additions & 2 deletions packages/app-builder/src/models/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
type TransferDto,
} from 'marble-api/generated/transfercheck-api';

export type TransferStatus = 'neutral' | 'suspected_fraud' | 'confirmed_fraud';

export interface TransferData {
beneficiaryBic: string;
beneficiaryIban: string;
Expand All @@ -14,7 +16,7 @@ export interface TransferData {
senderBic: string;
senderDevice: string;
senderIp: string;
status: 'neutral' | 'suspected_fraud' | 'confirmed_fraud';
status: TransferStatus;
timezone: string;
partnerTransferId: string;
transferRequestedAt: string;
Expand Down Expand Up @@ -62,5 +64,5 @@ export function adaptTransfer(transferDto: TransferDto): Transfer {
}

export interface TransferUpdateBody {
status: 'neutral' | 'suspected_fraud' | 'confirmed_fraud';
status: TransferStatus;
}
66 changes: 66 additions & 0 deletions packages/app-builder/src/repositories/TransferAlertRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { type TransfercheckApi } from '@app-builder/infra/transfercheck-api';
import {
adaptCreateTransferAlertDto,
adaptTransferAlert,
adaptUpdateTransferAlertDto,
type CreateTransferAlert,
type TransferAlert,
type UpdateTransferAlert,
} from '@app-builder/models/transfer-alert';
import invariant from 'tiny-invariant';

export interface TransferAlertRepository {
listAlerts(): Promise<TransferAlert[]>;
createAlert(args: CreateTransferAlert): Promise<TransferAlert>;
getAlert(args: { alertId: string }): Promise<TransferAlert>;
updateAlert(
alertId: string,
updateTransferAlert: UpdateTransferAlert,
): Promise<TransferAlert>;
}

export function makeGetTransferAlertRepository() {
return (
transfercheckApi: TransfercheckApi,
// TODO: make partnerId required (need to split init.server.ts into multiple files)
partnerId?: string,
): TransferAlertRepository => ({
listAlerts: async () => {
// TODO: make partnerId required (need to split init.server.ts into multiple files)
invariant(partnerId, 'partnerId is required');

const { alerts } = await transfercheckApi.listAlerts();

return alerts.map((alert) => adaptTransferAlert(alert, partnerId));
},
createAlert: async (createTransferAlert) => {
// TODO: make partnerId required (need to split init.server.ts into multiple files)
invariant(partnerId, 'partnerId is required');

const { alert } = await transfercheckApi.createAlert(
adaptCreateTransferAlertDto(createTransferAlert),
);

return adaptTransferAlert(alert, partnerId);
},
getAlert: async ({ alertId }) => {
// TODO: make partnerId required (need to split init.server.ts into multiple files)
invariant(partnerId, 'partnerId is required');

const { alert } = await transfercheckApi.getAlert(alertId);

return adaptTransferAlert(alert, partnerId);
},
updateAlert: async (alertId, updateTransferAlert) => {
// TODO: make partnerId required (need to split init.server.ts into multiple files)
invariant(partnerId, 'partnerId is required');

const { alert } = await transfercheckApi.updateAlert(
alertId,
adaptUpdateTransferAlertDto(updateTransferAlert),
);

return adaptTransferAlert(alert, partnerId);
},
});
}
2 changes: 2 additions & 0 deletions packages/app-builder/src/repositories/init.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
getToastStorageRepository,
type SessionStorageRepositoryOptions,
} from './SessionStorageRepositories';
import { makeGetTransferAlertRepository } from './TransferAlertRepository';
import { makeGetTransferRepository } from './TransferRepository';
import { makeGetUserRepository } from './UserRepository';

Expand Down Expand Up @@ -60,6 +61,7 @@ export function makeServerRepositories({
getAnalyticsRepository: makeGetAnalyticsRepository(),
getTransferRepository: makeGetTransferRepository(),
getPartnerRepository: makeGetPartnerRepository(),
getTransferAlertRepository: makeGetTransferAlertRepository(),
licenseRepository: getLicenseRepository(licenseAPIClient, devEnvironment),
};
}
Expand Down
11 changes: 11 additions & 0 deletions packages/app-builder/src/services/auth/auth.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { type OrganizationRepository } from '@app-builder/repositories/Organizat
import { type PartnerRepository } from '@app-builder/repositories/PartnerRepository';
import { type ScenarioIterationRuleRepository } from '@app-builder/repositories/ScenarioIterationRuleRepository';
import { type ScenarioRepository } from '@app-builder/repositories/ScenarioRepository';
import { type TransferAlertRepository } from '@app-builder/repositories/TransferAlertRepository';
import { type TransferRepository } from '@app-builder/repositories/TransferRepository';
import { type UserRepository } from '@app-builder/repositories/UserRepository';
import { getServerEnv } from '@app-builder/utils/environment';
Expand All @@ -49,6 +50,7 @@ interface AuthenticatedInfo {
analytics: AnalyticsRepository;
transferRepository: TransferRepository;
partnerRepository: PartnerRepository;
transferAlertRepository: TransferAlertRepository;
organization: OrganizationRepository;
scenario: ScenarioRepository;
scenarioIterationRuleRepository: ScenarioIterationRuleRepository;
Expand Down Expand Up @@ -130,6 +132,10 @@ interface MakeAuthenticationServerServiceArgs {
getPartnerRepository: (
transfercheckApi: TransfercheckApi,
) => PartnerRepository;
getTransferAlertRepository: (
transfercheckApi: TransfercheckApi,
partnerId?: string,
) => TransferAlertRepository;
authSessionService: SessionService<AuthData, AuthFlashData>;
csrfService: CSRF;
}
Expand All @@ -150,6 +156,7 @@ export function makeAuthenticationServerService({
getAnalyticsRepository,
getTransferRepository,
getPartnerRepository,
getTransferAlertRepository,
authSessionService,
csrfService,
}: MakeAuthenticationServerServiceArgs) {
Expand Down Expand Up @@ -324,6 +331,10 @@ export function makeAuthenticationServerService({
analytics: getAnalyticsRepository(marbleCoreApiClient),
transferRepository: getTransferRepository(transfercheckAPIClient),
partnerRepository: getPartnerRepository(transfercheckAPIClient),
transferAlertRepository: getTransferAlertRepository(
transfercheckAPIClient,
user.partnerId,
),
user,
inbox: getInboxRepository(marbleCoreApiClient),
};
Expand Down
Loading

0 comments on commit aa611a5

Please sign in to comment.