Skip to content

Commit

Permalink
feat(wallet/backend): add lock and unlock endpoints for cards (#1656)
Browse files Browse the repository at this point in the history
* Add lock and unlock endpoints

* Address comments

* Update routes

* Update request methods
  • Loading branch information
sanducb authored Oct 1, 2024
1 parent 8024a9f commit bef2be5
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 94 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)

// Return an error for invalid routes
router.use('*', (req: Request, res: CustomResponse) => {
Expand Down
46 changes: 44 additions & 2 deletions packages/wallet/backend/src/card/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,23 @@ import { toSuccessResponse } from '@shared/backend'
import {
ICardDetailsRequest,
ICardDetailsResponse,
ICardResponse
ICardLockRequest,
ICardResponse,
ICardUnlockRequest
} from './types'
import { validate } from '@/shared/validate'
import { getCardsByCustomerSchema, getCardDetailsSchema } from './validation'
import {
getCardsByCustomerSchema,
getCardDetailsSchema,
lockCardSchema,
unlockCardSchema
} from './validation'

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

export class CardController implements ICardController {
Expand Down Expand Up @@ -55,4 +64,37 @@ export class CardController implements ICardController {
next(error)
}
}

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)
}
}
}
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 @@ -33,4 +36,19 @@ export class CardService {

return this.gateHubClient.getCardDetails(requestBody)
}

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 @@ -14,3 +14,31 @@ export const getCardDetailsSchema = z.object({
publicKeyBase64: z.string()
})
})

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()
})
})
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
}
)
}

private async request<T>(
method: HTTP_METHODS,
url: string,
Expand Down
Loading

0 comments on commit bef2be5

Please sign in to comment.