@nxgt/janus-hono 0.7.3 → 0.7.5
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/README.md +1 -1
- package/docs/guide/routes.md +12 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ bun add @nxgt/janus-hono @nxgt/janus hono
|
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Every peer is required: `@nxgt/janus`, `hono` (4.13.4 or later) and
|
|
40
|
-
`typescript` (6). `@nxgt/janus` is a **peer**, never a dependency: this package
|
|
40
|
+
`typescript` (6 or 7). `@nxgt/janus` is a **peer**, never a dependency: this package
|
|
41
41
|
defines no error class, so the `JanusError` you catch is the one you import.
|
|
42
42
|
Like `@nxgt/janus`, it expects `"moduleResolution": "bundler"`: the
|
|
43
43
|
declarations import without extensions, so `nodenext` is not supported.
|
package/docs/guide/routes.md
CHANGED
|
@@ -618,7 +618,13 @@ app.post('/invitation/accept', csrf({ origin: ORIGIN }), async (c) => {
|
|
|
618
618
|
const invitation = await invitations.spend(hash(token), new Date()); // yours: once, unexpired
|
|
619
619
|
if (invitation === null) return c.json({ code: 'INVITATION_INVALID' }, 404);
|
|
620
620
|
|
|
621
|
-
|
|
621
|
+
// The invitation reached the inbox: prove it first — on an address never proved, this
|
|
622
|
+
// drops a password, a second factor and sessions somebody else set on it.
|
|
623
|
+
const user = await auth.get(invitation.userId);
|
|
624
|
+
if (user.email !== invitation.email) return c.json({ code: 'INVITATION_INVALID' }, 404);
|
|
625
|
+
await auth.verifyEmail.proveFirst(user);
|
|
626
|
+
// Then sign in — last, since proveFirst revokes every session.
|
|
627
|
+
const result = await auth.signInProven(user, { device: deviceOf(c) });
|
|
622
628
|
if (result.status === 'secondFactor') {
|
|
623
629
|
setCookie(c, CHALLENGE, result.challenge, { ...scope, expires: result.expiresAt });
|
|
624
630
|
return c.redirect('/sign-in/second-factor', 303);
|
|
@@ -628,6 +634,11 @@ app.post('/invitation/accept', csrf({ origin: ORIGIN }), async (c) => {
|
|
|
628
634
|
});
|
|
629
635
|
```
|
|
630
636
|
|
|
637
|
+
`verifyEmail.proveFirst` (`@nxgt/janus` 0.22) comes first, and before any
|
|
638
|
+
`setPassword` your form makes: it drops the password and revokes every
|
|
639
|
+
session. The check on `email` keeps it from proving an address the user
|
|
640
|
+
changed since the invitation was sent.
|
|
641
|
+
|
|
631
642
|
Not `magicLink.request` then `confirm` at once: `request` counts against
|
|
632
643
|
the mail throttle per address, so five anonymous requests for the invitee's
|
|
633
644
|
address would answer this route 429. See [`@nxgt/janus`'s
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/janus-hono",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Hono middleware for @nxgt/janus: the signed-in user on every request, the session cookie, routes guarded by a permission, and every error as its status",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,14 +49,14 @@
|
|
|
49
49
|
]
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@nxgt/janus": "^0.
|
|
52
|
+
"@nxgt/janus": "^0.22.1",
|
|
53
53
|
"@types/bun": "^1.4.2",
|
|
54
54
|
"hono": "^4.13.9",
|
|
55
55
|
"zod": "^4.6.5"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@nxgt/janus": "^0.
|
|
58
|
+
"@nxgt/janus": "^0.22.1",
|
|
59
59
|
"hono": "^4.13.4",
|
|
60
|
-
"typescript": "^6.0.3"
|
|
60
|
+
"typescript": "^6.0.3 || ^7.0.0"
|
|
61
61
|
}
|
|
62
62
|
}
|