@7365admin1/core 3.47.1-staging.136 → 3.47.1-staging.137
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/verification-status-transition.md +35 -0
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +19 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/harness.mjs +5 -0
- package/test/e2e/verification-status.e2e.test.mjs +159 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": minor
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Restrict the unauthenticated invitation-status write to the one transition its
|
|
6
|
+
callers actually perform.
|
|
7
|
+
|
|
8
|
+
`PATCH /api/auth/verification/status` (`API-core auth.route.ts:36`) carries no
|
|
9
|
+
middleware, and it cannot be given any: every caller is an invitation-landing
|
|
10
|
+
page opened from an emailed link **before an account exists** —
|
|
11
|
+
`web-app-main` `pages/verify/invitation/[id].vue`,
|
|
12
|
+
`pages/verify/service-provider/[id].vue`,
|
|
13
|
+
`pages/verify/service-provider-invite/[id].vue` and
|
|
14
|
+
`pages/sign-up-invite/service-provider/index.vue`, all through
|
|
15
|
+
`layer-common composables/useLocalAuth.ts:130`. Adding `requireAuth` would break
|
|
16
|
+
invitation acceptance for everybody, including the shipped clients.
|
|
17
|
+
|
|
18
|
+
What is restricted instead is what an anonymous caller may *do*. Each of those
|
|
19
|
+
pages calls `GET /auth/verify/:id` first, and `verify`
|
|
20
|
+
(`verification.service.ts:661-690`) already refuses an invitation that is
|
|
21
|
+
expired, cancelled or complete — so the only transition a real caller ever
|
|
22
|
+
performs is `pending -> complete`. Accepting the other three states let anyone
|
|
23
|
+
who learned an invitation id:
|
|
24
|
+
|
|
25
|
+
- set a used invitation back to `pending` and replay it,
|
|
26
|
+
- revive a `cancelled` or `expired` invitation, or
|
|
27
|
+
- burn somebody else's pending invitation by marking it `complete` before they
|
|
28
|
+
opened the email.
|
|
29
|
+
|
|
30
|
+
The handler now accepts only `complete`, loads the invitation and requires it to
|
|
31
|
+
be `pending`. Completing an already-complete invitation still answers 200 so a
|
|
32
|
+
page that calls this twice is not broken. Cancelling an invitation on purpose
|
|
33
|
+
keeps its own session-protected endpoint,
|
|
34
|
+
`PUT /api/verifications/:id/cancel` (`verification.route.ts:13`), so no
|
|
35
|
+
capability is removed.
|
package/dist/index.js
CHANGED
|
@@ -19440,7 +19440,7 @@ function useVerificationController() {
|
|
|
19440
19440
|
updateStatusById: _updateStatusById,
|
|
19441
19441
|
cancelUserInvitation: _cancelUserInvitation
|
|
19442
19442
|
} = useVerificationService();
|
|
19443
|
-
const { getVerifications: _getVerifications } = useVerificationRepo();
|
|
19443
|
+
const { getVerifications: _getVerifications, getById: _getVerificationById } = useVerificationRepo();
|
|
19444
19444
|
async function createUserInvite(req, res, next) {
|
|
19445
19445
|
const payload = { ...req.body };
|
|
19446
19446
|
const validation = import_joi21.default.object({
|
|
@@ -19825,7 +19825,7 @@ function useVerificationController() {
|
|
|
19825
19825
|
async function updateVerificationStatus(req, res, next) {
|
|
19826
19826
|
const validation = import_joi21.default.object({
|
|
19827
19827
|
id: import_joi21.default.string().hex().required(),
|
|
19828
|
-
status: import_joi21.default.string().valid("
|
|
19828
|
+
status: import_joi21.default.string().valid("complete").required()
|
|
19829
19829
|
});
|
|
19830
19830
|
const { error } = validation.validate(req.body);
|
|
19831
19831
|
if (error) {
|
|
@@ -19835,6 +19835,23 @@ function useVerificationController() {
|
|
|
19835
19835
|
}
|
|
19836
19836
|
try {
|
|
19837
19837
|
const { id, status } = req.body;
|
|
19838
|
+
const verification = await _getVerificationById(id);
|
|
19839
|
+
if (!verification) {
|
|
19840
|
+
next(new import_node_server_utils47.BadRequestError("Verification not found."));
|
|
19841
|
+
return;
|
|
19842
|
+
}
|
|
19843
|
+
if (verification.status === "complete") {
|
|
19844
|
+
res.json({ message: "Successfully updated verification status." });
|
|
19845
|
+
return;
|
|
19846
|
+
}
|
|
19847
|
+
if (verification.status !== "pending") {
|
|
19848
|
+
next(
|
|
19849
|
+
new import_node_server_utils47.BadRequestError(
|
|
19850
|
+
`Verification is ${verification.status} and cannot be completed.`
|
|
19851
|
+
)
|
|
19852
|
+
);
|
|
19853
|
+
return;
|
|
19854
|
+
}
|
|
19838
19855
|
const result = await _updateStatusById(id, status);
|
|
19839
19856
|
res.json({ message: result });
|
|
19840
19857
|
return;
|