Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin' into 1627-cards-wallet-backend-…
Browse files Browse the repository at this point in the history
…viewchange-pin-code
  • Loading branch information
sanducb committed Oct 1, 2024
2 parents 80454db + bef2be5 commit 8d7ea24
Show file tree
Hide file tree
Showing 9 changed files with 564 additions and 51 deletions.
2 changes: 2 additions & 0 deletions packages/wallet/backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ export class App {
cardController.getCardsByCustomer
)
router.get('/cards/:cardId/details', isAuth, cardController.getCardDetails)
router.put('/cards/:cardId/lock', isAuth, cardController.lock)
router.put('/cards/:cardId/unlock', isAuth, cardController.unlock)
router.get('/cards/:cardId/pin', isAuth, cardController.getPin)
router.post('/cards/:cardId/change-pin', isAuth, cardController.changePin)

Expand Down
41 changes: 40 additions & 1 deletion packages/wallet/backend/src/card/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@ import { toSuccessResponse } from '@shared/backend'
import {
ICardDetailsRequest,
ICardDetailsResponse,
ICardResponse
ICardLockRequest,
ICardResponse,
ICardUnlockRequest
} from './types'
import { validate } from '@/shared/validate'
import {
getCardsByCustomerSchema,
getCardDetailsSchema,
lockCardSchema,
unlockCardSchema,
changePinSchema
} from './validation'

export interface ICardController {
getCardsByCustomer: Controller<ICardDetailsResponse[]>
getCardDetails: Controller<ICardResponse>
lock: Controller<ICardResponse>
unlock: Controller<ICardResponse>
getPin: Controller<ICardResponse>
}

Expand Down Expand Up @@ -61,6 +67,39 @@ export class CardController implements ICardController {
}
}

public lock = async (req: Request, res: Response, next: NextFunction) => {
try {
const { params, query, body } = await validate(lockCardSchema, req)
const { cardId } = params
const { reasonCode } = query
const requestBody: ICardLockRequest = body

const result = await this.cardService.lock(
cardId,
reasonCode,
requestBody
)

res.status(200).json(toSuccessResponse(result))
} catch (error) {
next(error)
}
}

public unlock = async (req: Request, res: Response, next: NextFunction) => {
try {
const { params, body } = await validate(unlockCardSchema, req)
const { cardId } = params
const requestBody: ICardUnlockRequest = body

const result = await this.cardService.unlock(cardId, requestBody)

res.status(200).json(toSuccessResponse(result))
} catch (error) {
next(error)
}
}

public getPin = async (req: Request, res: Response, next: NextFunction) => {
try {
const userId = req.session.user.id
Expand Down
20 changes: 19 additions & 1 deletion packages/wallet/backend/src/card/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { GateHubClient } from '../gatehub/client'
import {
ICardDetailsRequest,
ICardDetailsResponse,
ICardResponse
ICardLockRequest,
ICardResponse,
ICardUnlockRequest
} from './types'
import { LockReasonCode } from '@wallet/shared/src'
import { NotFound } from '@shared/backend'

export class CardService {
Expand Down Expand Up @@ -59,4 +62,19 @@ export class CardService {
throw new NotFound('Card not found or not associated with the user.')
}
}

async lock(
cardId: string,
reasonCode: LockReasonCode,
requestBody: ICardLockRequest
): Promise<ICardResponse> {
return this.gateHubClient.lockCard(cardId, reasonCode, requestBody)
}

async unlock(
cardId: string,
requestBody: ICardUnlockRequest
): Promise<ICardResponse> {
return this.gateHubClient.unlockCard(cardId, requestBody)
}
}
8 changes: 8 additions & 0 deletions packages/wallet/backend/src/card/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,11 @@ export interface ICardProductResponse {
name: string
cost: string
}

export interface ICardLockRequest {
note: string
}

export interface ICardUnlockRequest {
note: string
}
28 changes: 28 additions & 0 deletions packages/wallet/backend/src/card/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,34 @@ export const getCardDetailsSchema = z.object({
})
})

export const lockCardSchema = z.object({
params: z.object({
cardId: z.string()
}),
query: z.object({
reasonCode: z.enum([
'ClientRequestedLock',
'LostCard',
'StolenCard',
'IssuerRequestGeneral',
'IssuerRequestFraud',
'IssuerRequestLegal'
])
}),
body: z.object({
note: z.string()
})
})

export const unlockCardSchema = z.object({
params: z.object({
cardId: z.string()
}),
body: z.object({
note: z.string()
})
})

export const changePinSchema = z.object({
params: z.object({
cardId: z.string()
Expand Down
40 changes: 38 additions & 2 deletions packages/wallet/backend/src/gatehub/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
} from '@/gatehub/consts'
import axios, { AxiosError } from 'axios'
import { Logger } from 'winston'
import { IFRAME_TYPE } from '@wallet/shared/src'
import { IFRAME_TYPE, LockReasonCode } from '@wallet/shared/src'
import { BadRequest } from '@shared/backend'
import {
ICardDetailsResponse,
Expand All @@ -39,7 +39,9 @@ import {
ICreateCustomerRequest,
ICreateCustomerResponse,
ICardProductResponse,
ICardDetailsRequest
ICardDetailsRequest,
ICardLockRequest,
ICardUnlockRequest
} from '@/card/types'

export class GateHubClient {
Expand Down Expand Up @@ -371,6 +373,40 @@ export class GateHubClient {
return cardDetailsResponse
}

async lockCard(
cardId: string,
reasonCode: LockReasonCode,
requestBody: ICardLockRequest
): Promise<ICardResponse> {
let url = `${this.apiUrl}/v1/cards/${cardId}/lock`
url += `?reasonCode=${encodeURIComponent(reasonCode)}`

return this.request<ICardResponse>(
'PUT',
url,
JSON.stringify(requestBody),
{
cardAppId: this.env.GATEHUB_CARD_APP_ID
}
)
}

async unlockCard(
cardId: string,
requestBody: ICardUnlockRequest
): Promise<ICardResponse> {
const url = `${this.apiUrl}/v1/cards/${cardId}/unlock`

return this.request<ICardResponse>(
'PUT',
url,
JSON.stringify(requestBody),
{
cardAppId: this.env.GATEHUB_CARD_APP_ID
}
)
}

async getPin(
requestBody: ICardDetailsRequest
): Promise<ICardDetailsResponse> {
Expand Down
Loading

0 comments on commit 8d7ea24

Please sign in to comment.