Skip to content

Commit 3cbd2ad

Browse files
authored
feat: added getWalletInstanceStatus and setWalletInstanceStatus endpoint
Refs: #1171 SIW-1775
1 parent 003412f commit 3cbd2ad

File tree

6 files changed

+336
-77
lines changed

6 files changed

+336
-77
lines changed

api_io_wallet.yaml

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,39 +83,70 @@ paths:
8383
$ref: "#/components/responses/ServiceUnavailable"
8484

8585
/wallet-instances/current/status:
86+
put:
87+
summary: Revoke current Wallet Instance
88+
operationId: setCurrentWalletInstanceStatus
89+
requestBody:
90+
content:
91+
application/json:
92+
schema:
93+
$ref: "#/components/schemas/SetWalletInstanceStatusBody"
94+
responses:
95+
"204":
96+
description: Wallet Instance status successfully set
97+
"400":
98+
$ref: "#/components/responses/BadRequest"
99+
"403":
100+
$ref: "#/components/responses/Forbidden"
101+
"422":
102+
$ref: "#/components/responses/UnprocessableContent"
103+
"500":
104+
$ref: "#/components/responses/Unexpected"
105+
"503":
106+
$ref: "#/components/responses/ServiceUnavailable"
107+
108+
/wallet-instances/{id}/status:
109+
parameters:
110+
- in: path
111+
name: id
112+
required: true
113+
schema:
114+
type: string
86115
get:
87-
summary: Retrieve the current Wallet Instance status
88-
operationId: getCurrentWalletInstanceStatus
116+
summary: Retrieve a Wallet Instance status
117+
operationId: getWalletInstanceStatus
89118
responses:
90119
"200":
91120
description: Wallet Instance status successfully retrieved
92121
content:
93122
application/json:
94123
schema:
95124
$ref: "#/components/schemas/WalletInstanceData"
125+
"400":
126+
$ref: "#/components/responses/BadRequest"
127+
"403":
128+
$ref: "#/components/responses/Forbidden"
96129
"404":
97130
$ref: "#/components/responses/NotFound"
98131
"500":
99132
$ref: "#/components/responses/Unexpected"
100133
"503":
101134
$ref: "#/components/responses/ServiceUnavailable"
102135
put:
103-
summary: Revoke current Wallet Instance
104-
operationId: setCurrentWalletInstanceStatus
136+
summary: Revoke a Wallet Instance
137+
operationId: setWalletInstanceStatus
105138
requestBody:
106139
content:
107140
application/json:
108141
schema:
109-
$ref: "#/components/schemas/SetCurrentWalletInstanceStatusBody"
142+
$ref: "#/components/schemas/SetWalletInstanceStatusBody"
110143
responses:
111144
"204":
112145
description: Wallet Instance status successfully set
113146
"400":
114147
$ref: "#/components/responses/BadRequest"
115148
"403":
116149
$ref: "#/components/responses/Forbidden"
117-
"422":
118-
$ref: "#/components/responses/UnprocessableContent"
119150
"500":
120151
$ref: "#/components/responses/Unexpected"
121152
"503":
@@ -231,7 +262,7 @@ components:
231262
- grant_type
232263
- assertion
233264

234-
SetCurrentWalletInstanceStatusBody:
265+
SetWalletInstanceStatusBody:
235266
type: object
236267
properties:
237268
status:
@@ -249,9 +280,20 @@ components:
249280
type: string
250281
is_revoked:
251282
type: boolean
283+
revocation_reason:
284+
$ref: "#/components/schemas/RevocationReason"
252285
required:
253286
- id
254287
- is_revoked
288+
289+
RevocationReason:
290+
type: string
291+
enum:
292+
[
293+
"CERTIFICATE_REVOKED_BY_ISSUER",
294+
"NEW_WALLET_INSTANCE_CREATED",
295+
"REVOKED_BY_USER",
296+
]
255297

256298
ProblemDetail:
257299
type: object

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
"generate:proxy:api-session": "rimraf generated/session && gen-api-models --api-spec api_session.yaml --out-dir generated/session",
6363
"generate:lollipop-definitions": "rimraf generated/lollipop && gen-api-models --api-spec openapi/lollipop_definitions.yaml --out-dir generated/lollipop",
6464
"generate:lollipop-first-sign": "rimraf generated/lollipop-first-consumer && gen-api-models --api-spec openapi/consumed/lollipop_first_consumer.yaml --out-dir generated/lollipop-first-consumer --request-types --response-decoders --client",
65-
"generate:api:io-wallet": "rimraf generated/io-wallet-api && gen-api-models --api-spec https://raw.githubusercontent.com/pagopa/io-wallet/io-wallet-user-func@2.0.0/apps/io-wallet-user-func/openapi.yaml --no-strict --out-dir generated/io-wallet-api --request-types --response-decoders --client",
65+
"generate:api:io-wallet": "rimraf generated/io-wallet-api && gen-api-models --api-spec https://raw.githubusercontent.com/pagopa/io-wallet/io-wallet-user-func@2.0.1/apps/io-wallet-user-func/openapi.yaml --no-strict --out-dir generated/io-wallet-api --request-types --response-decoders --client",
6666
"generate:proxy:io-wallet-models": "rimraf generated/io-wallet && gen-api-models --api-spec api_io_wallet.yaml --out-dir generated/io-wallet",
6767
"postversion": "git push && git push --tags",
6868
"dist:modules": "modclean -r -n default:safe && yarn install --production",

src/app.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,7 @@ function registerIoWalletAPIRoutes(
14671467
)
14681468
);
14691469

1470+
// TODO SIW-1843
14701471
app.put(
14711472
`${basePath}/wallet-instances/current/status`,
14721473
bearerSessionTokenAuth,
@@ -1477,10 +1478,19 @@ function registerIoWalletAPIRoutes(
14771478
);
14781479

14791480
app.get(
1480-
`${basePath}/wallet-instances/current/status`,
1481+
`${basePath}/wallet-instances/:walletInstanceId/status`,
1482+
bearerSessionTokenAuth,
1483+
toExpressHandler(
1484+
ioWalletController.getWalletInstanceStatus,
1485+
ioWalletController
1486+
)
1487+
);
1488+
1489+
app.put(
1490+
`${basePath}/wallet-instances/:walletInstanceId/status`,
14811491
bearerSessionTokenAuth,
14821492
toExpressHandler(
1483-
ioWalletController.getCurrentWalletInstanceStatus,
1493+
ioWalletController.setWalletInstanceStatus,
14841494
ioWalletController
14851495
)
14861496
);

src/controllers/ioWalletController.ts

Lines changed: 81 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
} from "@pagopa/ts-commons/lib/responses";
2222

2323
import { pipe } from "fp-ts/lib/function";
24+
import { sequenceS } from "fp-ts/lib/Apply";
2425
import { Errors } from "io-ts";
2526
import { FiscalCode, NonEmptyString } from "@pagopa/ts-commons/lib/strings";
2627
import { readableReport } from "@pagopa/ts-commons/lib/reporters";
@@ -32,7 +33,7 @@ import { CreateWalletInstanceBody } from "../../generated/io-wallet/CreateWallet
3233
import { CreateWalletAttestationBody } from "../../generated/io-wallet/CreateWalletAttestationBody";
3334
import { WalletAttestationView } from "../../generated/io-wallet/WalletAttestationView";
3435
import { FF_IO_WALLET_TRIAL_ENABLED } from "../config";
35-
import { SetCurrentWalletInstanceStatusBody } from "../../generated/io-wallet/SetCurrentWalletInstanceStatusBody";
36+
import { SetWalletInstanceStatusBody } from "../../generated/io-wallet/SetWalletInstanceStatusBody";
3637
import { WalletInstanceData } from "../../generated/io-wallet/WalletInstanceData";
3738

3839
const toValidationError = (errors: Errors) =>
@@ -125,6 +126,48 @@ export default class IoWalletController {
125126
)()
126127
);
127128

129+
/**
130+
* Update current Wallet Instance status.
131+
*/
132+
public readonly setWalletInstanceStatus = (
133+
req: express.Request
134+
): Promise<
135+
| IResponseErrorInternal
136+
| IResponseSuccessNoContent
137+
| IResponseErrorServiceUnavailable
138+
| IResponseErrorValidation
139+
| IResponseErrorForbiddenNotAuthorized
140+
> =>
141+
withUserFromRequest(req, async (user) =>
142+
pipe(
143+
this.ensureFiscalCodeIsAllowed(user.fiscal_code),
144+
TE.chainW(() =>
145+
pipe(
146+
sequenceS(E.Apply)({
147+
body: pipe(
148+
req.body,
149+
SetWalletInstanceStatusBody.decode,
150+
E.mapLeft(toValidationError)
151+
),
152+
id: pipe(
153+
NonEmptyString.decode(req.params.walletInstanceId),
154+
E.mapLeft(toValidationError)
155+
),
156+
}),
157+
TE.fromEither
158+
)
159+
),
160+
TE.map(({ id, body: { status } }) =>
161+
this.ioWalletService.setWalletInstanceStatus(
162+
id,
163+
status,
164+
user.fiscal_code
165+
)
166+
),
167+
TE.toUnion
168+
)()
169+
);
170+
128171
/**
129172
* Update current Wallet Instance status.
130173
*/
@@ -144,7 +187,7 @@ export default class IoWalletController {
144187
TE.chainW(() =>
145188
pipe(
146189
req.body,
147-
SetCurrentWalletInstanceStatusBody.decode,
190+
SetWalletInstanceStatusBody.decode,
148191
E.mapLeft(toValidationError),
149192
TE.fromEither
150193
)
@@ -162,22 +205,31 @@ export default class IoWalletController {
162205
/**
163206
* Get current Wallet Instance status.
164207
*/
165-
public readonly getCurrentWalletInstanceStatus = (
208+
public readonly getWalletInstanceStatus = (
166209
req: express.Request
167210
): Promise<
168211
| IResponseErrorInternal
169212
| IResponseSuccessJson<WalletInstanceData>
170213
| IResponseErrorNotFound
171-
| IResponseErrorInternal
172214
| IResponseErrorServiceUnavailable
173215
| IResponseErrorValidation
174216
| IResponseErrorForbiddenNotAuthorized
175217
> =>
176218
withUserFromRequest(req, async (user) =>
177219
pipe(
178220
this.ensureFiscalCodeIsAllowed(user.fiscal_code),
179-
TE.map(() =>
180-
this.ioWalletService.getCurrentWalletInstanceStatus(user.fiscal_code)
221+
TE.chainW(() =>
222+
pipe(
223+
NonEmptyString.decode(req.params.walletInstanceId),
224+
E.mapLeft(toValidationError),
225+
TE.fromEither
226+
)
227+
),
228+
TE.map((walletInstanceId) =>
229+
this.ioWalletService.getWalletInstanceStatus(
230+
walletInstanceId,
231+
user.fiscal_code
232+
)
181233
),
182234
TE.toUnion
183235
)()
@@ -186,32 +238,32 @@ export default class IoWalletController {
186238
private readonly ensureUserIsAllowed = (
187239
userId: NonEmptyString
188240
): TE.TaskEither<Error, void> =>
241+
pipe(
242+
TE.tryCatch(
243+
() => this.ioWalletService.getSubscription(userId),
244+
E.toError
245+
),
246+
// if a successful response with state != "ACTIVE" or an error is returned, return left
247+
TE.chain((response) =>
248+
response.kind === "IResponseSuccessJson" &&
249+
response.value.state === "ACTIVE"
250+
? TE.right(undefined)
251+
: TE.left(new Error())
252+
)
253+
);
254+
255+
private readonly ensureFiscalCodeIsAllowed = (fiscalCode: FiscalCode) =>
189256
FF_IO_WALLET_TRIAL_ENABLED
190257
? pipe(
191-
TE.tryCatch(
192-
() => this.ioWalletService.getSubscription(userId),
193-
E.toError
194-
),
195-
// if a successful response with state != "ACTIVE" or an error is returned, return left
196-
TE.chain((response) =>
197-
response.kind === "IResponseSuccessJson" &&
198-
response.value.state === "ACTIVE"
199-
? TE.right(undefined)
200-
: TE.left(new Error())
258+
fiscalCode,
259+
NonEmptyString.decode,
260+
TE.fromEither,
261+
TE.chainW(this.ensureUserIsAllowed),
262+
TE.mapLeft(() =>
263+
getResponseErrorForbiddenNotAuthorized(
264+
"Not authorized to perform this action"
265+
)
201266
)
202267
)
203268
: TE.right(undefined);
204-
205-
private readonly ensureFiscalCodeIsAllowed = (fiscalCode: FiscalCode) =>
206-
pipe(
207-
fiscalCode,
208-
NonEmptyString.decode,
209-
TE.fromEither,
210-
TE.chainW(this.ensureUserIsAllowed),
211-
TE.mapLeft(() =>
212-
getResponseErrorForbiddenNotAuthorized(
213-
"Not authorized to perform this action"
214-
)
215-
)
216-
);
217269
}

0 commit comments

Comments
 (0)