@nxgt/janus 0.17.2 → 0.18.0
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 +72 -18
- package/dist/auth/config/index.d.ts +1 -1
- package/dist/auth/config/index.d.ts.map +1 -1
- package/dist/auth/config/janus-config.d.ts +31 -0
- package/dist/auth/config/janus-config.d.ts.map +1 -1
- package/dist/auth/config/resolve-config.d.ts.map +1 -1
- package/dist/auth/config/resolve-throttle.d.ts +30 -0
- package/dist/auth/config/resolve-throttle.d.ts.map +1 -0
- package/dist/auth/config/resolved-config.d.ts +5 -0
- package/dist/auth/config/resolved-config.d.ts.map +1 -1
- package/dist/auth/config/warn-throttle-window.d.ts +14 -0
- package/dist/auth/config/warn-throttle-window.d.ts.map +1 -0
- package/dist/auth/counter-key.d.ts +19 -0
- package/dist/auth/counter-key.d.ts.map +1 -0
- package/dist/auth/email-flows/reset-password.d.ts.map +1 -1
- package/dist/auth/email-flows/verify-email.d.ts.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/janus.d.ts.map +1 -1
- package/dist/auth/magic-link.d.ts.map +1 -1
- package/dist/auth/mail-requests.d.ts +51 -0
- package/dist/auth/mail-requests.d.ts.map +1 -0
- package/dist/auth/sign-in-attempts.d.ts +3 -6
- package/dist/auth/sign-in-attempts.d.ts.map +1 -1
- package/dist/auth/sign-in-code.d.ts +3 -2
- package/dist/auth/sign-in-code.d.ts.map +1 -1
- package/dist/auth/step-up/request.d.ts.map +1 -1
- package/dist/auth/types/email-flows.d.ts +16 -6
- package/dist/auth/types/email-flows.d.ts.map +1 -1
- package/dist/auth/types/magic-link.d.ts +4 -2
- package/dist/auth/types/magic-link.d.ts.map +1 -1
- package/dist/auth/types/step-up.d.ts +4 -1
- package/dist/auth/types/step-up.d.ts.map +1 -1
- package/dist/chunks/{index-6fxq0kzf.js → index-4khsm7mw.js} +2 -2
- package/dist/chunks/{index-k136102s.js → index-cntabs9d.js} +2 -2
- package/dist/chunks/{index-ztng6018.js → index-kppkcbn5.js} +10 -3
- package/dist/chunks/{index-ztng6018.js.map → index-kppkcbn5.js.map} +4 -4
- package/dist/chunks/{index-7xe5x3eg.js → index-kvjj5xkp.js} +2 -2
- package/dist/conformance/index.js +3 -3
- package/dist/errors/janus-error/codes.d.ts +10 -0
- package/dist/errors/janus-error/codes.d.ts.map +1 -1
- package/dist/errors/janus-error/index.d.ts +1 -1
- package/dist/errors/janus-error/index.d.ts.map +1 -1
- package/dist/errors/janus-error/options.d.ts +4 -3
- package/dist/errors/janus-error/options.d.ts.map +1 -1
- package/dist/errors/janus-error/refusals.d.ts +8 -0
- package/dist/errors/janus-error/refusals.d.ts.map +1 -1
- package/dist/errors/janus-error/status.d.ts +1 -1
- package/dist/errors/janus-error/status.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +114 -25
- package/dist/index.js.map +15 -12
- package/dist/permissions/index.js +3 -3
- package/docs/README.md +1 -1
- package/docs/guide/email-flows.md +164 -4
- package/docs/guide/errors.md +12 -3
- package/docs/guide/magic-link.md +41 -5
- package/docs/guide/passwords.md +2 -1
- package/docs/guide/sign-in-code.md +46 -7
- package/docs/guide/step-up.md +38 -7
- package/docs/guide/users.md +1 -0
- package/docs/roadmap.md +14 -1
- package/docs/troubleshooting.md +88 -3
- package/package.json +1 -1
- package/dist/auth/config/resolve-sign-in.d.ts +0 -5
- package/dist/auth/config/resolve-sign-in.d.ts.map +0 -1
- /package/dist/chunks/{index-6fxq0kzf.js.map → index-4khsm7mw.js.map} +0 -0
- /package/dist/chunks/{index-k136102s.js.map → index-cntabs9d.js.map} +0 -0
- /package/dist/chunks/{index-7xe5x3eg.js.map → index-kvjj5xkp.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
JanusError2,
|
|
3
3
|
InvalidCursorError2,
|
|
4
4
|
StoreFailure2
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-kppkcbn5.js";
|
|
6
6
|
|
|
7
7
|
// src/pagination/cursor-page.ts
|
|
8
8
|
var DEFAULT_PAGE_SIZE2 = 20;
|
|
@@ -72,4 +72,4 @@ var UNSTORABLE = "holds a NUL character or a lone surrogate, which no store can
|
|
|
72
72
|
export { guardStore, guardRelations, isStorable, UNSTORABLE, DEFAULT_PAGE_SIZE2, MAX_PAGE_SIZE2, pageLimit2, invalidCursor2 };
|
|
73
73
|
|
|
74
74
|
//# debugId=7AD3830DC22148E664756E2164756E21
|
|
75
|
-
//# sourceMappingURL=index-
|
|
75
|
+
//# sourceMappingURL=index-4khsm7mw.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isSubjectSet2,
|
|
3
3
|
formatTuple2
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-kppkcbn5.js";
|
|
5
5
|
|
|
6
6
|
// src/permissions/port/memory.ts
|
|
7
7
|
function createMemoryRelations2() {
|
|
@@ -77,4 +77,4 @@ function copyTuple(tuple) {
|
|
|
77
77
|
export { createMemoryRelations2 };
|
|
78
78
|
|
|
79
79
|
//# debugId=0BA3AA406E650E8464756E2164756E21
|
|
80
|
-
//# sourceMappingURL=index-
|
|
80
|
+
//# sourceMappingURL=index-cntabs9d.js.map
|
|
@@ -80,6 +80,11 @@ class StepUpRequiredError2 extends JanusError2 {
|
|
|
80
80
|
code = "STEP_UP_REQUIRED";
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
class MailThrottledError2 extends JanusError2 {
|
|
84
|
+
name = "MailThrottledError";
|
|
85
|
+
code = "MAIL_THROTTLED";
|
|
86
|
+
}
|
|
87
|
+
|
|
83
88
|
class InvalidCursorError2 extends JanusError2 {
|
|
84
89
|
name = "InvalidCursorError";
|
|
85
90
|
code = "INVALID_CURSOR";
|
|
@@ -122,6 +127,8 @@ function statusOf2(code) {
|
|
|
122
127
|
case "USER_INACTIVE":
|
|
123
128
|
case "STEP_UP_REQUIRED":
|
|
124
129
|
return 403;
|
|
130
|
+
case "MAIL_THROTTLED":
|
|
131
|
+
return 429;
|
|
125
132
|
case "UNSUPPORTED":
|
|
126
133
|
return 501;
|
|
127
134
|
case "PERMISSION_DEPTH":
|
|
@@ -208,7 +215,7 @@ function parseSubject2(text) {
|
|
|
208
215
|
return relation === undefined ? { type, id } : setOf2({ type, id }, relation);
|
|
209
216
|
}
|
|
210
217
|
|
|
211
|
-
export { JanusError2, UserInvalidError2, CredentialError2, UserInactiveError2, TokenError2, SecondFactorError2, StepUpRequiredError2, InvalidCursorError2, UnsupportedError2, PermissionDepthError2, statusOf2, StoreFailure2, StoreConflict2, NotFoundError2, isSubjectSet2, subjectOf2, setOf2, isSetOf2, formatEntity2, formatSubject2, formatTuple2, parseTuple2, parseSubject2 };
|
|
218
|
+
export { JanusError2, UserInvalidError2, CredentialError2, UserInactiveError2, TokenError2, SecondFactorError2, StepUpRequiredError2, MailThrottledError2, InvalidCursorError2, UnsupportedError2, PermissionDepthError2, statusOf2, StoreFailure2, StoreConflict2, NotFoundError2, isSubjectSet2, subjectOf2, setOf2, isSetOf2, formatEntity2, formatSubject2, formatTuple2, parseTuple2, parseSubject2 };
|
|
212
219
|
|
|
213
|
-
//# debugId=
|
|
214
|
-
//# sourceMappingURL=index-
|
|
220
|
+
//# debugId=2BB721119E78839E64756E2164756E21
|
|
221
|
+
//# sourceMappingURL=index-kppkcbn5.js.map
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
"sources": ["../src/errors/janus-error/base.ts", "../src/errors/janus-error/refusals.ts", "../src/errors/janus-error/status.ts", "../src/errors/janus-error/store.ts", "../src/subjects/subject.ts", "../src/subjects/notation.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import type { JanusErrorCode } from './codes';\nimport type { CredentialRefusal, Issue, JanusErrorOptions } from './options';\n\n/**\n * The base of everything this package throws at call time.\n *\n * It extends `Error` and not `TypeError`, and the rule behind that is\n * `nxgt-data`'s: *extend whichever class the refusals it replaces already\n * threw, so no consumer's `catch` stops working*. These replace nothing — the\n * package is new — and `DataError`, `RedisError` and `S3Error` all extend\n * `Error`, so nobody has to order their `catch` blocks.\n *\n * **There is exactly one definition of this class**, and that matters more here\n * than it looks: an adapter in another package throws `StoreFailure` and this\n * package tests it with `instanceof`. Two copies and the product is wrong about\n * what an outage is. `build.ts` shares the module across entry points with\n * `splitting: true`, and `scripts/verify-artifacts.ts` fails the build if any\n * class name appears in two entry bundles of the packed tarball.\n */\nexport class JanusError extends Error {\n\toverride name = 'JanusError';\n\treadonly code: JanusErrorCode = 'STORE_FAILED';\n\treadonly userId: string | undefined;\n\treadonly userType: string | undefined;\n\treadonly login: string | undefined;\n\treadonly reason: CredentialRefusal | undefined;\n\treadonly hashPrefix: string | undefined;\n\treadonly expectedVersion: number | undefined;\n\treadonly actualVersion: number | undefined;\n\treadonly issues: readonly Issue[] | undefined;\n\treadonly minLength: number | undefined;\n\treadonly operation: string | undefined;\n\treadonly slot: 'users' | 'sessions' | 'tokens' | 'relations' | undefined;\n\treadonly permission: string | undefined;\n\treadonly maxDepth: number | undefined;\n\treadonly attemptsLeft: number | undefined;\n\treadonly retryAfter: number | undefined;\n\n\tconstructor(message: string, options?: JanusErrorOptions) {\n\t\tsuper(message, { cause: options?.cause });\n\t\tthis.userId = options?.userId;\n\t\tthis.userType = options?.userType;\n\t\tthis.login = options?.login;\n\t\tthis.reason = options?.reason;\n\t\tthis.hashPrefix = options?.hashPrefix;\n\t\tthis.expectedVersion = options?.expectedVersion;\n\t\tthis.actualVersion = options?.actualVersion;\n\t\tthis.issues = options?.issues;\n\t\tthis.minLength = options?.minLength;\n\t\tthis.operation = options?.operation;\n\t\tthis.slot = options?.slot;\n\t\tthis.permission = options?.permission;\n\t\tthis.maxDepth = options?.maxDepth;\n\t\tthis.attemptsLeft = options?.attemptsLeft;\n\t\tthis.retryAfter = options?.retryAfter;\n\t}\n}\n",
|
|
6
|
-
"import { JanusError } from './base';\nimport type { JanusErrorCode } from './codes';\nimport type { JanusErrorOptions } from './options';\n\n/** The fields failed the user type's schema. */\nexport class UserInvalidError extends JanusError {\n\toverride name = 'UserInvalidError';\n\toverride readonly code = 'USER_INVALID' as const;\n}\n\n/** A password too short, credentials that do not match, or a hash format nobody reads. */\nexport class CredentialError extends JanusError {\n\toverride name = 'CredentialError';\n\toverride readonly code: JanusErrorCode;\n\n\tconstructor(\n\t\tcode: Extract<\n\t\t\tJanusErrorCode,\n\t\t\t'PASSWORD_TOO_SHORT' | 'CREDENTIALS_INVALID' | 'HASH_UNSUPPORTED'\n\t\t>,\n\t\tmessage: string,\n\t\toptions?: JanusErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t}\n}\n\n/** The user is inactive, and the password given was the right one. */\nexport class UserInactiveError extends JanusError {\n\toverride name = 'UserInactiveError';\n\toverride readonly code = 'USER_INACTIVE' as const;\n}\n\n/**\n * A one-time token that is unknown, already spent, lapsed, or sent to an\n * e-mail the user no longer has — or a one-time code that does not match.\n */\nexport class TokenError extends JanusError {\n\toverride name = 'TokenError';\n\toverride readonly code: JanusErrorCode;\n\n\tconstructor(\n\t\tcode: Extract<\n\t\t\tJanusErrorCode,\n\t\t\t| 'TOKEN_UNKNOWN'\n\t\t\t| 'TOKEN_SPENT'\n\t\t\t| 'TOKEN_EXPIRED'\n\t\t\t| 'TOKEN_STALE'\n\t\t\t| 'CODE_INVALID'\n\t\t>,\n\t\tmessage: string,\n\t\toptions?: JanusErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t}\n}\n\n/** A second factor asked to change from a state it is not in. */\nexport class SecondFactorError extends JanusError {\n\toverride name = 'SecondFactorError';\n\toverride readonly code: JanusErrorCode;\n\n\tconstructor(\n\t\tcode: Extract<\n\t\t\tJanusErrorCode,\n\t\t\t'SECOND_FACTOR_NOT_ENROLLED' | 'SECOND_FACTOR_ACTIVE'\n\t\t>,\n\t\tmessage: string,\n\t\toptions?: JanusErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t}\n}\n\n/**\n * The session proved who it is longer ago than the action asks: confirm it\n * with a step-up, then send the request again.\n */\nexport class StepUpRequiredError extends JanusError {\n\toverride name = 'StepUpRequiredError';\n\toverride readonly code = 'STEP_UP_REQUIRED' as const;\n}\n\n/** A cursor this store did not mint, or one for another ordering. */\nexport class InvalidCursorError extends JanusError {\n\toverride name = 'InvalidCursorError';\n\toverride readonly code = 'INVALID_CURSOR' as const;\n}\n\n/** The wired store does not implement the optional capability asked for. */\nexport class UnsupportedError extends JanusError {\n\toverride name = 'UnsupportedError';\n\toverride readonly code = 'UNSUPPORTED' as const;\n}\n\n/** A permission check walked deeper than `maxDepth` without an answer. */\nexport class PermissionDepthError extends JanusError {\n\toverride name = 'PermissionDepthError';\n\toverride readonly code = 'PERMISSION_DEPTH' as const;\n}\n",
|
|
7
|
-
"import type { JanusErrorCode } from './codes';\n\n/**\n * Every HTTP status `statusOf` answers: a union of literals, so a framework\n * whose response takes a narrower type than `number` accepts it as it is.\n */\nexport type JanusErrorStatus
|
|
6
|
+
"import { JanusError } from './base';\nimport type { JanusErrorCode } from './codes';\nimport type { JanusErrorOptions } from './options';\n\n/** The fields failed the user type's schema. */\nexport class UserInvalidError extends JanusError {\n\toverride name = 'UserInvalidError';\n\toverride readonly code = 'USER_INVALID' as const;\n}\n\n/** A password too short, credentials that do not match, or a hash format nobody reads. */\nexport class CredentialError extends JanusError {\n\toverride name = 'CredentialError';\n\toverride readonly code: JanusErrorCode;\n\n\tconstructor(\n\t\tcode: Extract<\n\t\t\tJanusErrorCode,\n\t\t\t'PASSWORD_TOO_SHORT' | 'CREDENTIALS_INVALID' | 'HASH_UNSUPPORTED'\n\t\t>,\n\t\tmessage: string,\n\t\toptions?: JanusErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t}\n}\n\n/** The user is inactive, and the password given was the right one. */\nexport class UserInactiveError extends JanusError {\n\toverride name = 'UserInactiveError';\n\toverride readonly code = 'USER_INACTIVE' as const;\n}\n\n/**\n * A one-time token that is unknown, already spent, lapsed, or sent to an\n * e-mail the user no longer has — or a one-time code that does not match.\n */\nexport class TokenError extends JanusError {\n\toverride name = 'TokenError';\n\toverride readonly code: JanusErrorCode;\n\n\tconstructor(\n\t\tcode: Extract<\n\t\t\tJanusErrorCode,\n\t\t\t| 'TOKEN_UNKNOWN'\n\t\t\t| 'TOKEN_SPENT'\n\t\t\t| 'TOKEN_EXPIRED'\n\t\t\t| 'TOKEN_STALE'\n\t\t\t| 'CODE_INVALID'\n\t\t>,\n\t\tmessage: string,\n\t\toptions?: JanusErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t}\n}\n\n/** A second factor asked to change from a state it is not in. */\nexport class SecondFactorError extends JanusError {\n\toverride name = 'SecondFactorError';\n\toverride readonly code: JanusErrorCode;\n\n\tconstructor(\n\t\tcode: Extract<\n\t\t\tJanusErrorCode,\n\t\t\t'SECOND_FACTOR_NOT_ENROLLED' | 'SECOND_FACTOR_ACTIVE'\n\t\t>,\n\t\tmessage: string,\n\t\toptions?: JanusErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t}\n}\n\n/**\n * The session proved who it is longer ago than the action asks: confirm it\n * with a step-up, then send the request again.\n */\nexport class StepUpRequiredError extends JanusError {\n\toverride name = 'StepUpRequiredError';\n\toverride readonly code = 'STEP_UP_REQUIRED' as const;\n}\n\n/**\n * Too many e-mails asked for one address, or one user, in this window:\n * nothing was issued. Wait `retryAfter` seconds, then ask again.\n */\nexport class MailThrottledError extends JanusError {\n\toverride name = 'MailThrottledError';\n\toverride readonly code = 'MAIL_THROTTLED' as const;\n}\n\n/** A cursor this store did not mint, or one for another ordering. */\nexport class InvalidCursorError extends JanusError {\n\toverride name = 'InvalidCursorError';\n\toverride readonly code = 'INVALID_CURSOR' as const;\n}\n\n/** The wired store does not implement the optional capability asked for. */\nexport class UnsupportedError extends JanusError {\n\toverride name = 'UnsupportedError';\n\toverride readonly code = 'UNSUPPORTED' as const;\n}\n\n/** A permission check walked deeper than `maxDepth` without an answer. */\nexport class PermissionDepthError extends JanusError {\n\toverride name = 'PermissionDepthError';\n\toverride readonly code = 'PERMISSION_DEPTH' as const;\n}\n",
|
|
7
|
+
"import type { JanusErrorCode } from './codes';\n\n/**\n * Every HTTP status `statusOf` answers: a union of literals, so a framework\n * whose response takes a narrower type than `number` accepts it as it is.\n */\nexport type JanusErrorStatus =\n\t| 400\n\t| 401\n\t| 403\n\t| 404\n\t| 409\n\t| 429\n\t| 500\n\t| 501\n\t| 503;\n\n/**\n * The HTTP status each code deserves — the one table the integrations share,\n * so a Hono route and a GraphQL field answer the same code the same way.\n * Exhaustive: a code added to `JanusErrorCode` stops this file compiling\n * instead of answering `undefined`.\n *\n * `STORE_FAILED` is 503 and nothing else — **an outage is not a negative\n * answer**, and a 401 or a 404 would tell every user they do not exist.\n *\n * ```ts\n * if (error instanceof JanusError) return Response.json({ code: error.code }, { status: statusOf(error.code) });\n * ```\n */\nexport function statusOf(code: JanusErrorCode): JanusErrorStatus {\n\tswitch (code) {\n\t\tcase 'STORE_FAILED':\n\t\t\treturn 503;\n\t\tcase 'NOT_FOUND':\n\t\t\treturn 404;\n\t\tcase 'LOGIN_TAKEN':\n\t\tcase 'VERSION_CONFLICT':\n\t\tcase 'SECOND_FACTOR_NOT_ENROLLED':\n\t\tcase 'SECOND_FACTOR_ACTIVE':\n\t\t\treturn 409;\n\t\tcase 'USER_INVALID':\n\t\tcase 'PASSWORD_TOO_SHORT':\n\t\tcase 'HASH_UNSUPPORTED':\n\t\tcase 'INVALID_CURSOR':\n\t\tcase 'TOKEN_UNKNOWN':\n\t\tcase 'TOKEN_SPENT':\n\t\tcase 'TOKEN_EXPIRED':\n\t\tcase 'TOKEN_STALE':\n\t\t\treturn 400;\n\t\tcase 'CREDENTIALS_INVALID':\n\t\tcase 'CODE_INVALID':\n\t\t\treturn 401;\n\t\tcase 'USER_INACTIVE':\n\t\tcase 'STEP_UP_REQUIRED':\n\t\t\treturn 403;\n\t\tcase 'MAIL_THROTTLED':\n\t\t\treturn 429;\n\t\tcase 'UNSUPPORTED':\n\t\t\treturn 501;\n\t\tcase 'PERMISSION_DEPTH':\n\t\t\treturn 500;\n\t}\n}\n",
|
|
8
8
|
"import { JanusError } from './base';\nimport type { JanusErrorCode } from './codes';\nimport type { JanusErrorOptions } from './options';\n\n/**\n * The store could not answer.\n *\n * **This is the class an adapter throws**, and it is exported for that reason:\n * an adapter defines no error class of its own, so `instanceof` holds across\n * the two packages. Any other throw from a store is treated as a failure too —\n * throwing this one is how an adapter says so precisely, and sets `cause`.\n */\nexport class StoreFailure extends JanusError {\n\toverride name = 'StoreFailure';\n\toverride readonly code = 'STORE_FAILED' as const;\n}\n\n/**\n * A uniqueness or a version constraint the store refused.\n *\n * Also thrown by an adapter, and also for the `instanceof` reason. `on` says\n * which constraint, because the two are answered differently: a login\n * collision is the caller's to fix, a version conflict is a retry.\n */\nexport class StoreConflict extends JanusError {\n\toverride name = 'StoreConflict';\n\toverride readonly code: JanusErrorCode;\n\treadonly on: 'login' | 'version';\n\n\tconstructor(\n\t\ton: 'login' | 'version',\n\t\tmessage: string,\n\t\toptions?: JanusErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.on = on;\n\t\tthis.code = on === 'login' ? 'LOGIN_TAKEN' : 'VERSION_CONFLICT';\n\t}\n}\n\n/** There is no such record, and the store said so. */\nexport class NotFoundError extends JanusError {\n\toverride name = 'NotFoundError';\n\toverride readonly code = 'NOT_FOUND' as const;\n}\n",
|
|
9
9
|
"/**\n * The id every decision in this package hangs on: a user's `id`, as `janus()`\n * mints it.\n *\n * In Ory, the equality between a Kratos identity id and Keto's `subject_id` is\n * a comment and a convention, restated in three repositories and enforced\n * nowhere. Here a user **is** a subject — see {@link subjectOf} — and that\n * shared vocabulary is the whole reason users and permissions are one package\n * rather than two: two packages would make this contract implicit, and an\n * implicit contract between independently versioned packages breaks silently.\n *\n * Opaque: compared with `===`, carried in a URL, logged, never parsed.\n */\nexport type SubjectId = string;\n\n/**\n * Something a permission is about or held by — a user, a record, a team — by\n * its type and its id.\n *\n * **Typed, unlike Keto's subjects.** One application has patients and staff,\n * and an object can hold a relation too (a record's team), so an id alone does\n * not say who. `type` is a user type of `janus()` or an object type of the\n * permission model, and the same word as a user's own `type`.\n */\nexport interface Entity {\n\treadonly type: string;\n\treadonly id: string;\n}\n\n/**\n * Everyone who holds `relation` on an entity — `team:t1#member` — which is how\n * a permission is inherited rather than granted.\n *\n * A tuple whose subject is a subject set lets a whole group be given access\n * with one write: granting a record's `viewer` to `team:t1#member` means every\n * member of that team can view it, and no member holds a tuple on the record.\n */\nexport interface SubjectSet extends Entity {\n\treadonly relation: string;\n}\n\n/**\n * Who a tuple is about: one entity, or everyone who holds a relation on one.\n * {@link isSubjectSet} tells them apart.\n */\nexport type Subject = Entity | SubjectSet;\n\n/**\n * A relation tuple: `subject` holds `relation` on `object`.\n *\n * `relation` is Zanzibar's word, and a tuple is Zanzibar's unit. What is not\n * carried over is Keto's `namespace`/`object` pair: here the object is an\n * {@link Entity}, with the `type` and `id` a user already has.\n */\nexport interface RelationTuple {\n\treadonly object: Entity;\n\treadonly relation: string;\n\treadonly subject: Subject;\n}\n\n/**\n * Whether this subject is a set rather than one entity. Narrows.\n *\n * It reads the shape, so pass a user through {@link subjectOf} first: a user\n * whose fields include a string `relation` would otherwise read as a set.\n */\nexport function isSubjectSet(subject: Subject): subject is SubjectSet {\n\treturn typeof (subject as { relation?: unknown }).relation === 'string';\n}\n\n/**\n * The subject a user is: their `type` and `id`, and nothing else.\n *\n * One line, and the entire join between the two sides of the package. It\n * takes the narrowest shape it reads, so the permissions side never has to\n * know what a user is, and it copies those two fields so none of the user's\n * own fields ever reaches a tuple.\n */\nexport function subjectOf(user: {\n\treadonly type: string;\n\treadonly id: SubjectId;\n}): Entity {\n\treturn { type: user.type, id: user.id };\n}\n\n/**\n * The mark `setOf()` puts on a set: a symbol property, so it survives a spread\n * and `Object.assign`, and no value read from a database or from JSON can\n * carry it. Registered with `Symbol.for`, so two copies of this module — two\n * bundles, two entry points — still agree on it.\n */\nconst SET_OF: unique symbol = Symbol.for('@nxgt/janus/setOf');\n\n/**\n * A subject set `setOf()` made: everyone who holds `relation` on `type:id`.\n *\n * Marked, because a user is passed to `can()` and `grant()` as it is, fields\n * flat on it: a user whose fields include `relation` must stay that user, and\n * never read as the set of whoever holds that relation on them. For an object\n * type, `{ type, id, relation }` is a set as written; for a user type — one\n * the model also declares as an object type — only `setOf()` makes one.\n *\n * A spread keeps the mark. `JSON.stringify` and `structuredClone` drop it:\n * through either, a set comes back as a user — call `setOf()` again, or\n * `parseSubject()` on its notation.\n */\nexport type SetOf<\n\tType extends string = string,\n\tRelation extends string = string,\n> = SubjectSet & {\n\treadonly type: Type;\n\treadonly relation: Relation;\n\treadonly [SET_OF]: true;\n};\n\n/**\n * A user or an object, never a set `setOf()` made: where a relation admits\n * `staff` but not `staff#managers`, a set passed there is refused at compile\n * time as it is at run time.\n */\nexport type NotASet = { readonly [SET_OF]?: never };\n\n/**\n * Everyone who holds `relation` on this user or object — `staff:s1#managers`.\n *\n * ```ts\n * await access.grant(record, 'viewers', setOf(ada, 'managers'));\n * ```\n *\n * Copies `type` and `id` only, like {@link subjectOf}: none of a user's own\n * fields reaches a tuple.\n */\nexport function setOf<const Type extends string, const Relation extends string>(\n\tentity: { readonly type: Type; readonly id: SubjectId },\n\trelation: Relation,\n): SetOf<Type, Relation> {\n\tif (\n\t\ttypeof entity !== 'object' ||\n\t\tentity === null ||\n\t\ttypeof entity.type !== 'string' ||\n\t\ttypeof entity.id !== 'string'\n\t) {\n\t\tthrow new TypeError('setOf: pass a user or { type, id }, then a relation');\n\t}\n\tif (typeof relation !== 'string' || relation === '') {\n\t\tthrow new TypeError('setOf: the relation must be a non-empty string');\n\t}\n\treturn Object.freeze({\n\t\ttype: entity.type,\n\t\tid: entity.id,\n\t\trelation,\n\t\t[SET_OF]: true as const,\n\t});\n}\n\n/**\n * Whether `setOf()` made this value, or a spread of one — what `can()` and\n * `grant()` read to tell a set on a user type from a user.\n */\nexport function isSetOf(value: unknown): value is SetOf {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t(value as { readonly [SET_OF]?: unknown })[SET_OF] === true\n\t);\n}\n",
|
|
10
10
|
"import {\n\ttype Entity,\n\tisSubjectSet,\n\ttype RelationTuple,\n\ttype SetOf,\n\ttype Subject,\n\tsetOf,\n} from './subject';\n\n/**\n * Zanzibar's notation, with typed subjects:\n *\n * ```\n * record:r1#viewer@staff:u1\n * record:r1#viewer@team:t1#member\n * ```\n *\n * It exists for **messages, logs and documentation**, not as a wire format:\n * nothing in this package parses a tuple off the network, and a tuple that\n * crosses a boundary crosses it as an object. Keeping the notation is worth it\n * because every piece of Zanzibar writing uses it, so an error message in it is\n * an error message a reader has already learned to read.\n *\n * A type holds no `:`, and no part holds `@`, `#` or a parenthesis, so a\n * subject set needs no parentheses: after the `@`, a `#` can only begin its\n * relation. {@link parseTuple} refuses a string where that would not hold,\n * rather than reading it two ways.\n */\nexport function formatEntity(entity: Entity): string {\n\treturn `${entity.type}:${entity.id}`;\n}\n\n/** One subject: `staff:u1`, or `team:t1#member`. */\nexport function formatSubject(subject: Subject): string {\n\treturn isSubjectSet(subject)\n\t\t? `${formatEntity(subject)}#${subject.relation}`\n\t\t: formatEntity(subject);\n}\n\n/** One relation tuple, in the notation above. */\nexport function formatTuple(tuple: RelationTuple): string {\n\treturn `${formatEntity(tuple.object)}#${tuple.relation}@${formatSubject(tuple.subject)}`;\n}\n\nconst TYPE = '([^:@#()]+)';\nconst ID = '([^@#()]+)';\nconst RELATION = '([^:@#()]+)';\n\nconst TUPLE = new RegExp(`^${TYPE}:${ID}#${RELATION}@(.+)$`);\nconst SUBJECT = new RegExp(`^${TYPE}:${ID}(?:#${RELATION})?$`);\n\n/**\n * Reads a tuple back. Refuses, with a `TypeError`, a string that is not one —\n * a permission question built from a malformed string is a question whose\n * answer means nothing, and no request is behind it: the string came from a\n * developer's own code.\n */\nexport function parseTuple(text: string): RelationTuple {\n\tconst match = TUPLE.exec(text);\n\n\tif (!match) {\n\t\tthrow new TypeError(\n\t\t\t`parseTuple: \"${text}\" is not a relation tuple; expected type:id#relation@subject`,\n\t\t);\n\t}\n\n\tconst [, type, id, relation, subject] = match as unknown as [\n\t\tstring,\n\t\tstring,\n\t\tstring,\n\t\tstring,\n\t\tstring,\n\t];\n\n\treturn { object: { type, id }, relation, subject: parseSubject(subject) };\n}\n\n/**\n * Reads one subject back: `staff:u1`, or `team:t1#member`. A set is answered\n * as `setOf()` makes it, so `can()` and `grant()` read it as the set it names\n * on a user type too.\n */\nexport function parseSubject(text: string): Entity | SetOf {\n\tconst match = SUBJECT.exec(text);\n\n\tif (!match) {\n\t\tthrow new TypeError(\n\t\t\t`parseSubject: \"${text}\" is not a subject; expected type:id, or type:id#relation for a subject set`,\n\t\t);\n\t}\n\n\tconst [, type, id, relation] = match as unknown as [\n\t\tstring,\n\t\tstring,\n\t\tstring,\n\t\tstring | undefined,\n\t];\n\n\treturn relation === undefined ? { type, id } : setOf({ type, id }, relation);\n}\n"
|
|
11
11
|
],
|
|
12
|
-
"mappings": ";AAmBO,MAAM,oBAAmB,MAAM;AAAA,EAC5B,OAAO;AAAA,EACP,OAAuB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,WAAW,CAAC,SAAiB,SAA6B;AAAA,IACzD,MAAM,SAAS,EAAE,OAAO,SAAS,MAAM,CAAC;AAAA,IACxC,KAAK,SAAS,SAAS;AAAA,IACvB,KAAK,WAAW,SAAS;AAAA,IACzB,KAAK,QAAQ,SAAS;AAAA,IACtB,KAAK,SAAS,SAAS;AAAA,IACvB,KAAK,aAAa,SAAS;AAAA,IAC3B,KAAK,kBAAkB,SAAS;AAAA,IAChC,KAAK,gBAAgB,SAAS;AAAA,IAC9B,KAAK,SAAS,SAAS;AAAA,IACvB,KAAK,YAAY,SAAS;AAAA,IAC1B,KAAK,YAAY,SAAS;AAAA,IAC1B,KAAK,OAAO,SAAS;AAAA,IACrB,KAAK,aAAa,SAAS;AAAA,IAC3B,KAAK,WAAW,SAAS;AAAA,IACzB,KAAK,eAAe,SAAS;AAAA,IAC7B,KAAK,aAAa,SAAS;AAAA;AAE7B;;;ACnDO,MAAM,0BAAyB,YAAW;AAAA,EACvC,OAAO;AAAA,EACE,OAAO;AAC1B;AAAA;AAGO,MAAM,yBAAwB,YAAW;AAAA,EACtC,OAAO;AAAA,EACE;AAAA,EAElB,WAAW,CACV,MAIA,SACA,SACC;AAAA,IACD,MAAM,SAAS,OAAO;AAAA,IACtB,KAAK,OAAO;AAAA;AAEd;AAAA;AAGO,MAAM,2BAA0B,YAAW;AAAA,EACxC,OAAO;AAAA,EACE,OAAO;AAC1B;AAAA;AAMO,MAAM,oBAAmB,YAAW;AAAA,EACjC,OAAO;AAAA,EACE;AAAA,EAElB,WAAW,CACV,MAQA,SACA,SACC;AAAA,IACD,MAAM,SAAS,OAAO;AAAA,IACtB,KAAK,OAAO;AAAA;AAEd;AAAA;AAGO,MAAM,2BAA0B,YAAW;AAAA,EACxC,OAAO;AAAA,EACE;AAAA,EAElB,WAAW,CACV,MAIA,SACA,SACC;AAAA,IACD,MAAM,SAAS,OAAO;AAAA,IACtB,KAAK,OAAO;AAAA;AAEd;AAAA;AAMO,MAAM,6BAA4B,YAAW;AAAA,EAC1C,OAAO;AAAA,EACE,OAAO;AAC1B;AAAA;AAGO,MAAM,4BAA2B,YAAW;AAAA,EACzC,OAAO;AAAA,EACE,OAAO;AAC1B;AAAA;AAGO,MAAM,0BAAyB,YAAW;AAAA,EACvC,OAAO;AAAA,EACE,OAAO;AAC1B;AAAA;AAGO,MAAM,8BAA6B,YAAW;AAAA,EAC3C,OAAO;AAAA,EACE,OAAO;AAC1B;;;ACjFO,SAAS,SAAQ,CAAC,MAAwC;AAAA,EAChE,QAAQ;AAAA,SACF;AAAA,MACJ,OAAO;AAAA,SACH;AAAA,MACJ,OAAO;AAAA,SACH;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACJ,OAAO;AAAA,SACH;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACJ,OAAO;AAAA,SACH;AAAA,SACA;AAAA,MACJ,OAAO;AAAA,SACH;AAAA,SACA;AAAA,MACJ,OAAO;AAAA,SACH;AAAA,MACJ,OAAO;AAAA,SACH;AAAA,MACJ,OAAO;AAAA;AAAA;;;
|
|
13
|
-
"debugId": "
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "2BB721119E78839E64756E2164756E21",
|
|
14
14
|
"names": []
|
|
15
15
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
StoreConflict2,
|
|
3
3
|
NotFoundError2
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-kppkcbn5.js";
|
|
5
5
|
|
|
6
6
|
// src/ids/id.ts
|
|
7
7
|
var HEX = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
@@ -307,4 +307,4 @@ function createMemoryStores2() {
|
|
|
307
307
|
export { mintId2, isId2, mintedAt2, createMemoryStores2 };
|
|
308
308
|
|
|
309
309
|
//# debugId=0777A8A648CFB0FA64756E2164756E21
|
|
310
|
-
//# sourceMappingURL=index-
|
|
310
|
+
//# sourceMappingURL=index-kvjj5xkp.js.map
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mintId2,
|
|
3
3
|
createMemoryStores2
|
|
4
|
-
} from "../chunks/index-
|
|
4
|
+
} from "../chunks/index-kvjj5xkp.js";
|
|
5
5
|
import {
|
|
6
6
|
JanusError2,
|
|
7
7
|
StoreFailure2,
|
|
8
8
|
StoreConflict2,
|
|
9
9
|
NotFoundError2,
|
|
10
10
|
formatSubject2
|
|
11
|
-
} from "../chunks/index-
|
|
11
|
+
} from "../chunks/index-kppkcbn5.js";
|
|
12
12
|
import {
|
|
13
13
|
createMemoryRelations2
|
|
14
|
-
} from "../chunks/index-
|
|
14
|
+
} from "../chunks/index-cntabs9d.js";
|
|
15
15
|
|
|
16
16
|
// src/conformance/assert.ts
|
|
17
17
|
function equal(actual, expected, what) {
|
|
@@ -104,6 +104,16 @@ export type JanusErrorCode =
|
|
|
104
104
|
* user's five, and `0` past them, when no code is compared at all.
|
|
105
105
|
*/
|
|
106
106
|
| 'CODE_INVALID'
|
|
107
|
+
/**
|
|
108
|
+
* Too many e-mails asked for one address — or for one user, once signed
|
|
109
|
+
* in — in this window: `magicLink.request`, `signInCode.request`,
|
|
110
|
+
* `resetPassword.request`, `verifyEmail.send`, or `stepUp.request` by
|
|
111
|
+
* e-mail. Nothing was issued, so there is nothing to send. Carries
|
|
112
|
+
* `retryAfter`, the seconds until the next window. An address nobody
|
|
113
|
+
* holds is refused alike, so a response may carry it without telling who
|
|
114
|
+
* has an account.
|
|
115
|
+
*/
|
|
116
|
+
| 'MAIL_THROTTLED'
|
|
107
117
|
/** `activate` before `enroll`: the user has no second factor waiting. */
|
|
108
118
|
| 'SECOND_FACTOR_NOT_ENROLLED'
|
|
109
119
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codes.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,cAAc;AACzB;;;;;;;;;;GAUG;AACD,cAAc;AAChB;;;;;GAKG;GACD,WAAW;AACb;;;;;;;GAOG;GACD,aAAa;AACf;;;;GAIG;GACD,kBAAkB;AACpB;;;GAGG;GACD,cAAc;AAChB;;;GAGG;GACD,oBAAoB;AACtB;;;;;;;GAOG;GACD,qBAAqB;AACvB;;;;GAIG;GACD,kBAAkB;AACpB;;;GAGG;GACD,eAAe;AACjB,kCAAkC;GAChC,eAAe;AACjB;;;GAGG;GACD,aAAa;AACf;;;GAGG;GACD,eAAe;AACjB;;;GAGG;GACD,aAAa;AACf;;;;;;GAMG;GACD,cAAc;AAChB,yEAAyE;GACvE,4BAA4B;AAC9B;;;GAGG;GACD,sBAAsB;AACxB;;;;;GAKG;GACD,kBAAkB;AACpB;4EAC4E;GAC1E,gBAAgB;AAClB;;;;GAIG;GACD,aAAa;AACf;;;;;;GAMG;GACD,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"codes.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,cAAc;AACzB;;;;;;;;;;GAUG;AACD,cAAc;AAChB;;;;;GAKG;GACD,WAAW;AACb;;;;;;;GAOG;GACD,aAAa;AACf;;;;GAIG;GACD,kBAAkB;AACpB;;;GAGG;GACD,cAAc;AAChB;;;GAGG;GACD,oBAAoB;AACtB;;;;;;;GAOG;GACD,qBAAqB;AACvB;;;;GAIG;GACD,kBAAkB;AACpB;;;GAGG;GACD,eAAe;AACjB,kCAAkC;GAChC,eAAe;AACjB;;;GAGG;GACD,aAAa;AACf;;;GAGG;GACD,eAAe;AACjB;;;GAGG;GACD,aAAa;AACf;;;;;;GAMG;GACD,cAAc;AAChB;;;;;;;;GAQG;GACD,gBAAgB;AAClB,yEAAyE;GACvE,4BAA4B;AAC9B;;;GAGG;GACD,sBAAsB;AACxB;;;;;GAKG;GACD,kBAAkB;AACpB;4EAC4E;GAC1E,gBAAgB;AAClB;;;;GAIG;GACD,aAAa;AACf;;;;;;GAMG;GACD,kBAAkB,CAAC"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
export { JanusError } from './base';
|
|
12
12
|
export type { JanusErrorCode } from './codes';
|
|
13
13
|
export type { CredentialRefusal, Issue, JanusErrorOptions } from './options';
|
|
14
|
-
export { CredentialError, InvalidCursorError, PermissionDepthError, SecondFactorError, StepUpRequiredError, TokenError, UnsupportedError, UserInactiveError, UserInvalidError, } from './refusals';
|
|
14
|
+
export { CredentialError, InvalidCursorError, MailThrottledError, PermissionDepthError, SecondFactorError, StepUpRequiredError, TokenError, UnsupportedError, UserInactiveError, UserInvalidError, } from './refusals';
|
|
15
15
|
export { type JanusErrorStatus, statusOf } from './status';
|
|
16
16
|
export { NotFoundError, StoreConflict, StoreFailure } from './store';
|
|
17
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -48,9 +48,10 @@ export interface JanusErrorOptions {
|
|
|
48
48
|
*/
|
|
49
49
|
readonly attemptsLeft?: number;
|
|
50
50
|
/**
|
|
51
|
-
* Seconds until a throttled
|
|
52
|
-
*
|
|
53
|
-
* header takes it as
|
|
51
|
+
* Seconds until a throttled request may be made again — a sign-in past
|
|
52
|
+
* its passwords, or a request past its e-mails: the end of the window,
|
|
53
|
+
* rounded up. A client may read it; the `Retry-After` header takes it as
|
|
54
|
+
* it is.
|
|
54
55
|
*/
|
|
55
56
|
readonly retryAfter?: number;
|
|
56
57
|
readonly cause?: unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/options.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,WAAW,KAAK;IACrB,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAC1B,cAAc,GACd,YAAY,GACZ,eAAe,GACf,WAAW,CAAC;AAEf;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IACpC,oEAAoE;IACpE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC9D,uEAAuE;IACvE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/options.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,WAAW,KAAK;IACrB,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAC1B,cAAc,GACd,YAAY,GACZ,eAAe,GACf,WAAW,CAAC;AAEf;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IACpC,oEAAoE;IACpE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC9D,uEAAuE;IACvE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CACzB"}
|
|
@@ -40,6 +40,14 @@ export declare class StepUpRequiredError extends JanusError {
|
|
|
40
40
|
name: string;
|
|
41
41
|
readonly code: "STEP_UP_REQUIRED";
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Too many e-mails asked for one address, or one user, in this window:
|
|
45
|
+
* nothing was issued. Wait `retryAfter` seconds, then ask again.
|
|
46
|
+
*/
|
|
47
|
+
export declare class MailThrottledError extends JanusError {
|
|
48
|
+
name: string;
|
|
49
|
+
readonly code: "MAIL_THROTTLED";
|
|
50
|
+
}
|
|
43
51
|
/** A cursor this store did not mint, or one for another ordering. */
|
|
44
52
|
export declare class InvalidCursorError extends JanusError {
|
|
45
53
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refusals.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/refusals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD,gDAAgD;AAChD,qBAAa,gBAAiB,SAAQ,UAAU;IACtC,IAAI,SAAsB;IACnC,SAAkB,IAAI,EAAG,cAAc,CAAU;CACjD;AAED,0FAA0F;AAC1F,qBAAa,eAAgB,SAAQ,UAAU;IACrC,IAAI,SAAqB;IAClC,SAAkB,IAAI,EAAE,cAAc,CAAC;gBAGtC,IAAI,EAAE,OAAO,CACZ,cAAc,EACd,oBAAoB,GAAG,qBAAqB,GAAG,kBAAkB,CACjE,EACD,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,iBAAiB;CAK5B;AAED,sEAAsE;AACtE,qBAAa,iBAAkB,SAAQ,UAAU;IACvC,IAAI,SAAuB;IACpC,SAAkB,IAAI,EAAG,eAAe,CAAU;CAClD;AAED;;;GAGG;AACH,qBAAa,UAAW,SAAQ,UAAU;IAChC,IAAI,SAAgB;IAC7B,SAAkB,IAAI,EAAE,cAAc,CAAC;gBAGtC,IAAI,EAAE,OAAO,CACZ,cAAc,EACZ,eAAe,GACf,aAAa,GACb,eAAe,GACf,aAAa,GACb,cAAc,CAChB,EACD,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,iBAAiB;CAK5B;AAED,iEAAiE;AACjE,qBAAa,iBAAkB,SAAQ,UAAU;IACvC,IAAI,SAAuB;IACpC,SAAkB,IAAI,EAAE,cAAc,CAAC;gBAGtC,IAAI,EAAE,OAAO,CACZ,cAAc,EACd,4BAA4B,GAAG,sBAAsB,CACrD,EACD,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,iBAAiB;CAK5B;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IACzC,IAAI,SAAyB;IACtC,SAAkB,IAAI,EAAG,kBAAkB,CAAU;CACrD;AAED,qEAAqE;AACrE,qBAAa,kBAAmB,SAAQ,UAAU;IACxC,IAAI,SAAwB;IACrC,SAAkB,IAAI,EAAG,gBAAgB,CAAU;CACnD;AAED,4EAA4E;AAC5E,qBAAa,gBAAiB,SAAQ,UAAU;IACtC,IAAI,SAAsB;IACnC,SAAkB,IAAI,EAAG,aAAa,CAAU;CAChD;AAED,0EAA0E;AAC1E,qBAAa,oBAAqB,SAAQ,UAAU;IAC1C,IAAI,SAA0B;IACvC,SAAkB,IAAI,EAAG,kBAAkB,CAAU;CACrD"}
|
|
1
|
+
{"version":3,"file":"refusals.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/refusals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD,gDAAgD;AAChD,qBAAa,gBAAiB,SAAQ,UAAU;IACtC,IAAI,SAAsB;IACnC,SAAkB,IAAI,EAAG,cAAc,CAAU;CACjD;AAED,0FAA0F;AAC1F,qBAAa,eAAgB,SAAQ,UAAU;IACrC,IAAI,SAAqB;IAClC,SAAkB,IAAI,EAAE,cAAc,CAAC;gBAGtC,IAAI,EAAE,OAAO,CACZ,cAAc,EACd,oBAAoB,GAAG,qBAAqB,GAAG,kBAAkB,CACjE,EACD,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,iBAAiB;CAK5B;AAED,sEAAsE;AACtE,qBAAa,iBAAkB,SAAQ,UAAU;IACvC,IAAI,SAAuB;IACpC,SAAkB,IAAI,EAAG,eAAe,CAAU;CAClD;AAED;;;GAGG;AACH,qBAAa,UAAW,SAAQ,UAAU;IAChC,IAAI,SAAgB;IAC7B,SAAkB,IAAI,EAAE,cAAc,CAAC;gBAGtC,IAAI,EAAE,OAAO,CACZ,cAAc,EACZ,eAAe,GACf,aAAa,GACb,eAAe,GACf,aAAa,GACb,cAAc,CAChB,EACD,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,iBAAiB;CAK5B;AAED,iEAAiE;AACjE,qBAAa,iBAAkB,SAAQ,UAAU;IACvC,IAAI,SAAuB;IACpC,SAAkB,IAAI,EAAE,cAAc,CAAC;gBAGtC,IAAI,EAAE,OAAO,CACZ,cAAc,EACd,4BAA4B,GAAG,sBAAsB,CACrD,EACD,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,iBAAiB;CAK5B;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IACzC,IAAI,SAAyB;IACtC,SAAkB,IAAI,EAAG,kBAAkB,CAAU;CACrD;AAED;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,UAAU;IACxC,IAAI,SAAwB;IACrC,SAAkB,IAAI,EAAG,gBAAgB,CAAU;CACnD;AAED,qEAAqE;AACrE,qBAAa,kBAAmB,SAAQ,UAAU;IACxC,IAAI,SAAwB;IACrC,SAAkB,IAAI,EAAG,gBAAgB,CAAU;CACnD;AAED,4EAA4E;AAC5E,qBAAa,gBAAiB,SAAQ,UAAU;IACtC,IAAI,SAAsB;IACnC,SAAkB,IAAI,EAAG,aAAa,CAAU;CAChD;AAED,0EAA0E;AAC1E,qBAAa,oBAAqB,SAAQ,UAAU;IAC1C,IAAI,SAA0B;IACvC,SAAkB,IAAI,EAAG,kBAAkB,CAAU;CACrD"}
|
|
@@ -3,7 +3,7 @@ import type { JanusErrorCode } from './codes';
|
|
|
3
3
|
* Every HTTP status `statusOf` answers: a union of literals, so a framework
|
|
4
4
|
* whose response takes a narrower type than `number` accepts it as it is.
|
|
5
5
|
*/
|
|
6
|
-
export type JanusErrorStatus = 400 | 401 | 403 | 404 | 409 | 500 | 501 | 503;
|
|
6
|
+
export type JanusErrorStatus = 400 | 401 | 403 | 404 | 409 | 429 | 500 | 501 | 503;
|
|
7
7
|
/**
|
|
8
8
|
* The HTTP status each code deserves — the one table the integrations share,
|
|
9
9
|
* so a Hono route and a GraphQL field answer the same code the same way.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;GAGG;AACH,MAAM,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/errors/janus-error/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GACzB,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;AAEP;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,gBAAgB,CAiC/D"}
|
package/dist/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* `@nxgt/janus/conformance` fails an adapter that breaks it.
|
|
22
22
|
*/
|
|
23
23
|
export * from './auth/index';
|
|
24
|
-
export { CredentialError, type CredentialRefusal, InvalidCursorError, type Issue, JanusError, type JanusErrorCode, type JanusErrorOptions, type JanusErrorStatus, NotFoundError, PermissionDepthError, SecondFactorError, StepUpRequiredError, StoreConflict, StoreFailure, statusOf, TokenError, UnsupportedError, UserInactiveError, UserInvalidError, } from './errors/janus-error';
|
|
24
|
+
export { CredentialError, type CredentialRefusal, InvalidCursorError, type Issue, JanusError, type JanusErrorCode, type JanusErrorOptions, type JanusErrorStatus, MailThrottledError, NotFoundError, PermissionDepthError, SecondFactorError, StepUpRequiredError, StoreConflict, StoreFailure, statusOf, TokenError, UnsupportedError, UserInactiveError, UserInvalidError, } from './errors/janus-error';
|
|
25
25
|
export { type Id, isId, mintedAt, mintId, } from './ids/id';
|
|
26
26
|
export { type CursorPage, DEFAULT_PAGE_SIZE, invalidCursor, MAX_PAGE_SIZE, pageLimit, } from './pagination/cursor-page';
|
|
27
27
|
export { formatEntity, formatSubject, formatTuple, parseSubject, parseTuple, } from './subjects/notation';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,cAAc,cAAc,CAAC;AAC7B,OAAO,EACN,eAAe,EACf,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,KAAK,KAAK,EACV,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,KAAK,EAAE,EACP,IAAI,EACJ,QAAQ,EACR,MAAM,GACN,MAAM,UAAU,CAAC;AAClB,OAAO,EACN,KAAK,UAAU,EACf,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,SAAS,GACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,YAAY,EACZ,aAAa,EACb,WAAW,EACX,YAAY,EACZ,UAAU,GACV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,MAAM,EACX,OAAO,EACP,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,KAAK,EACV,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,EACL,SAAS,GACT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,KAAK,QAAQ,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,cAAc,cAAc,CAAC;AAC7B,OAAO,EACN,eAAe,EACf,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,KAAK,KAAK,EACV,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,KAAK,EAAE,EACP,IAAI,EACJ,QAAQ,EACR,MAAM,GACN,MAAM,UAAU,CAAC;AAClB,OAAO,EACN,KAAK,UAAU,EACf,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,SAAS,GACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,YAAY,EACZ,aAAa,EACb,WAAW,EACX,YAAY,EACZ,UAAU,GACV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,MAAM,EACX,OAAO,EACP,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,KAAK,EACV,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,EACL,SAAS,GACT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,KAAK,QAAQ,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
MAX_PAGE_SIZE2,
|
|
8
8
|
pageLimit2,
|
|
9
9
|
invalidCursor2
|
|
10
|
-
} from "./chunks/index-
|
|
10
|
+
} from "./chunks/index-4khsm7mw.js";
|
|
11
11
|
import {
|
|
12
12
|
mintId2,
|
|
13
13
|
isId2,
|
|
14
14
|
mintedAt2,
|
|
15
15
|
createMemoryStores2
|
|
16
|
-
} from "./chunks/index-
|
|
16
|
+
} from "./chunks/index-kvjj5xkp.js";
|
|
17
17
|
import {
|
|
18
18
|
JanusError2,
|
|
19
19
|
UserInvalidError2,
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
TokenError2,
|
|
23
23
|
SecondFactorError2,
|
|
24
24
|
StepUpRequiredError2,
|
|
25
|
+
MailThrottledError2,
|
|
25
26
|
InvalidCursorError2,
|
|
26
27
|
UnsupportedError2,
|
|
27
28
|
PermissionDepthError2,
|
|
@@ -38,7 +39,7 @@ import {
|
|
|
38
39
|
formatTuple2,
|
|
39
40
|
parseTuple2,
|
|
40
41
|
parseSubject2
|
|
41
|
-
} from "./chunks/index-
|
|
42
|
+
} from "./chunks/index-kppkcbn5.js";
|
|
42
43
|
|
|
43
44
|
// src/auth/hashers.ts
|
|
44
45
|
import { randomBytes, scrypt, timingSafeEqual } from "node:crypto";
|
|
@@ -303,25 +304,32 @@ function resolveSecondFactor(config, where) {
|
|
|
303
304
|
};
|
|
304
305
|
}
|
|
305
306
|
|
|
306
|
-
// src/auth/config/resolve-
|
|
307
|
+
// src/auth/config/resolve-throttle.ts
|
|
307
308
|
function resolveSignInThrottle(config, where) {
|
|
309
|
+
return resolveThrottle(config, { option: "signIn", attempts: 10, window: "15m" }, where);
|
|
310
|
+
}
|
|
311
|
+
function resolveMailThrottle(config, where) {
|
|
312
|
+
return resolveThrottle(config, { option: "mail", attempts: 5, window: "10m" }, where);
|
|
313
|
+
}
|
|
314
|
+
function resolveThrottle(config, defaults, where) {
|
|
315
|
+
const { option } = defaults;
|
|
308
316
|
if (config !== undefined && (typeof config !== "object" || config === null)) {
|
|
309
|
-
throw new TypeError(`${where}:
|
|
317
|
+
throw new TypeError(`${where}: ${option} must be an object — { throttle }`);
|
|
310
318
|
}
|
|
311
319
|
const throttle = config?.throttle ?? {};
|
|
312
320
|
if (throttle === false)
|
|
313
321
|
return null;
|
|
314
|
-
const at = `${where}:
|
|
322
|
+
const at = `${where}: ${option}.throttle`;
|
|
315
323
|
if (typeof throttle !== "object" || throttle === null) {
|
|
316
324
|
throw new TypeError(`${at} must be { attempts, window }, or false to count nothing`);
|
|
317
325
|
}
|
|
318
|
-
const attempts = throttle.attempts ??
|
|
326
|
+
const attempts = throttle.attempts ?? defaults.attempts;
|
|
319
327
|
if (!Number.isSafeInteger(attempts) || attempts < 1) {
|
|
320
328
|
throw new TypeError(`${at}.attempts must be a whole number above zero`);
|
|
321
329
|
}
|
|
322
330
|
return {
|
|
323
331
|
attempts,
|
|
324
|
-
windowMs: parseDuration(throttle.window ??
|
|
332
|
+
windowMs: parseDuration(throttle.window ?? defaults.window, `${at}.window`)
|
|
325
333
|
};
|
|
326
334
|
}
|
|
327
335
|
|
|
@@ -372,6 +380,7 @@ function resolveConfig(config, where) {
|
|
|
372
380
|
tokenTtlMs: resolveTokenTtls(config, where),
|
|
373
381
|
cookie: resolveCookie(config.cookie ?? {}, where),
|
|
374
382
|
signInThrottle: resolveSignInThrottle(config.signIn, where),
|
|
383
|
+
mailThrottle: resolveMailThrottle(config.mail, where),
|
|
375
384
|
secondFactor: resolveSecondFactor(config.secondFactor, where),
|
|
376
385
|
devices: resolveDevices(config.devices, where)
|
|
377
386
|
};
|
|
@@ -419,6 +428,46 @@ function resolveTokenTtls(config, where) {
|
|
|
419
428
|
stepUp: parseDuration(config.tokens?.stepUp ?? "10m", `${where}: tokens.stepUp`)
|
|
420
429
|
};
|
|
421
430
|
}
|
|
431
|
+
// src/auth/config/warn-throttle-window.ts
|
|
432
|
+
var FLOWS = [
|
|
433
|
+
"magicLink",
|
|
434
|
+
"signInCode",
|
|
435
|
+
"resetPassword",
|
|
436
|
+
"verifyEmail",
|
|
437
|
+
"stepUp"
|
|
438
|
+
];
|
|
439
|
+
var UNITS2 = [
|
|
440
|
+
["d", 86400000],
|
|
441
|
+
["h", 3600000],
|
|
442
|
+
["m", 60000],
|
|
443
|
+
["s", 1000]
|
|
444
|
+
];
|
|
445
|
+
function show(ms) {
|
|
446
|
+
const unit = UNITS2.find(([, size]) => ms % size === 0);
|
|
447
|
+
return unit === undefined ? `${ms}ms` : `${ms / unit[1]}${unit[0]}`;
|
|
448
|
+
}
|
|
449
|
+
function throttleWindowMessage(resolved, where) {
|
|
450
|
+
const throttle = resolved.mailThrottle;
|
|
451
|
+
if (throttle === null)
|
|
452
|
+
return null;
|
|
453
|
+
const window = show(throttle.windowMs);
|
|
454
|
+
const shorter = FLOWS.filter((flow) => resolved.tokenTtlMs[flow] < throttle.windowMs);
|
|
455
|
+
if (shorter.length === 0)
|
|
456
|
+
return null;
|
|
457
|
+
const shortest = Math.min(...shorter.map((flow) => resolved.tokenTtlMs[flow]));
|
|
458
|
+
const parts = shorter.map((flow) => `tokens.${flow} is ${show(resolved.tokenTtlMs[flow])}, shorter than mail.throttle.window, ${window}`);
|
|
459
|
+
return `${where}: ${parts.join("; ")} — past the limit the last ${shorter.length === 1 ? "token" : "tokens"} sent can expire before the refusal ends. Set mail.throttle.window to ${show(shortest)} or less, or raise ${shorter.map((flow) => `tokens.${flow}`).join(", ")} to ${window} or more.`;
|
|
460
|
+
}
|
|
461
|
+
function warnThrottleWindow(resolved, where) {
|
|
462
|
+
const message = throttleWindowMessage(resolved, where);
|
|
463
|
+
if (message === null)
|
|
464
|
+
return;
|
|
465
|
+
if (typeof process === "undefined" || typeof process.emitWarning !== "function") {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
process.emitWarning(message, { code: "JANUS_THROTTLE_WINDOW" });
|
|
469
|
+
}
|
|
470
|
+
|
|
422
471
|
// src/auth/context/create-context.ts
|
|
423
472
|
function createContext(config, store, relations, capabilities, clock, hasher, verifiers, events = null) {
|
|
424
473
|
let dummy = null;
|
|
@@ -1008,6 +1057,13 @@ function sharedApi(context) {
|
|
|
1008
1057
|
types: [...config.types.keys()]
|
|
1009
1058
|
};
|
|
1010
1059
|
}
|
|
1060
|
+
// src/auth/counter-key.ts
|
|
1061
|
+
function counterKey(context, purpose) {
|
|
1062
|
+
const sealer = context.config.secondFactor?.sealer;
|
|
1063
|
+
return sealer === undefined ? Buffer.from(purpose) : derivedKey(sealer, purpose);
|
|
1064
|
+
}
|
|
1065
|
+
var keyed = (key, parts) => keyedHash(key, parts).toString("base64url");
|
|
1066
|
+
|
|
1011
1067
|
// src/auth/one-time/codes.ts
|
|
1012
1068
|
import { timingSafeEqual as timingSafeEqual3 } from "node:crypto";
|
|
1013
1069
|
|
|
@@ -1173,6 +1229,38 @@ async function insertLink(links, tokenHash) {
|
|
|
1173
1229
|
return inserted;
|
|
1174
1230
|
throw links.counting.vanished();
|
|
1175
1231
|
}
|
|
1232
|
+
// src/auth/mail-requests.ts
|
|
1233
|
+
var PURPOSE2 = "janus/mail/requests/v1";
|
|
1234
|
+
async function countMailByAddress(context, type, flow, email, where) {
|
|
1235
|
+
await countMail(context, type, flow, { address: normalizeEmail(email) }, where);
|
|
1236
|
+
}
|
|
1237
|
+
async function countMailByUser(context, type, flow, userId, where) {
|
|
1238
|
+
await countMail(context, type, flow, { userId }, where);
|
|
1239
|
+
}
|
|
1240
|
+
async function countMail(context, type, flow, counted, where) {
|
|
1241
|
+
const throttle = context.config.mailThrottle;
|
|
1242
|
+
if (throttle === null)
|
|
1243
|
+
return;
|
|
1244
|
+
const key = counterKey(context, PURPOSE2);
|
|
1245
|
+
const subject = "address" in counted ? keyed(key, [flow, "address", counted.address]) : keyed(key, [flow, "user", counted.userId]);
|
|
1246
|
+
const { attempts, endsAt } = await countInWindow(context, {
|
|
1247
|
+
windowMs: throttle.windowMs,
|
|
1248
|
+
spent: "carry",
|
|
1249
|
+
userId: subject,
|
|
1250
|
+
linkHash: (window, link) => hashSecret(keyed(key, [subject, String(window), String(link)])),
|
|
1251
|
+
vanished: () => new StoreFailure2(`${where}: the store dropped the requests it had just counted`, { slot: "tokens", operation: "countAttempt" })
|
|
1252
|
+
});
|
|
1253
|
+
if (attempts <= throttle.attempts)
|
|
1254
|
+
return;
|
|
1255
|
+
const now = context.clock.now().getTime();
|
|
1256
|
+
const byUser = "userId" in counted;
|
|
1257
|
+
throw new MailThrottledError2(`${where}: too many e-mails asked for this ${byUser ? "user" : "address"} — the last one sent still works; use it, or wait for the next window`, {
|
|
1258
|
+
userType: type.name,
|
|
1259
|
+
...byUser ? { userId: counted.userId } : {},
|
|
1260
|
+
retryAfter: Math.max(1, Math.ceil((endsAt - now) / 1000))
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1176
1264
|
// src/auth/password-written.ts
|
|
1177
1265
|
async function endWhatThePasswordOpened(context, userId) {
|
|
1178
1266
|
const now = context.clock.now();
|
|
@@ -1234,6 +1322,7 @@ function resetPasswordFlows(context, type, at) {
|
|
|
1234
1322
|
async request(email) {
|
|
1235
1323
|
const where = at("resetPassword.request");
|
|
1236
1324
|
passwordRule(type, where);
|
|
1325
|
+
await countMailByAddress(context, type, "resetPassword", String(email), where);
|
|
1237
1326
|
const record = await holderOfEmail(context, type, String(email));
|
|
1238
1327
|
if (record === null)
|
|
1239
1328
|
return null;
|
|
@@ -1278,6 +1367,7 @@ function verifyEmailFlows(context, type, at) {
|
|
|
1278
1367
|
async send(user) {
|
|
1279
1368
|
const where = at("verifyEmail.send");
|
|
1280
1369
|
const record = await getRecord(context, idOf(user), type.name, where);
|
|
1370
|
+
await countMailByUser(context, type, "verifyEmail", record.id, where);
|
|
1281
1371
|
return issueEmailToken(context, type, "verifyEmail", record, where);
|
|
1282
1372
|
},
|
|
1283
1373
|
async confirm(secret) {
|
|
@@ -1465,7 +1555,7 @@ async function finishEmailSignIn(context, type, finish, signIn) {
|
|
|
1465
1555
|
function magicLinkFlows(context, type, at, finish) {
|
|
1466
1556
|
return {
|
|
1467
1557
|
async request(email) {
|
|
1468
|
-
return requestLink(context, type, String(email));
|
|
1558
|
+
return requestLink(context, type, String(email), at("magicLink.request"));
|
|
1469
1559
|
},
|
|
1470
1560
|
async confirm(token, options) {
|
|
1471
1561
|
const where = at("magicLink.confirm");
|
|
@@ -1474,7 +1564,8 @@ function magicLinkFlows(context, type, at, finish) {
|
|
|
1474
1564
|
}
|
|
1475
1565
|
};
|
|
1476
1566
|
}
|
|
1477
|
-
async function requestLink(context, type, email) {
|
|
1567
|
+
async function requestLink(context, type, email, where) {
|
|
1568
|
+
await countMailByAddress(context, type, "magicLink", email, where);
|
|
1478
1569
|
const record = await signInHolder(context, type, email);
|
|
1479
1570
|
if (record === null)
|
|
1480
1571
|
return null;
|
|
@@ -1500,18 +1591,12 @@ async function confirmLink(context, type, finish, secret, where, device) {
|
|
|
1500
1591
|
}
|
|
1501
1592
|
|
|
1502
1593
|
// src/auth/sign-in-attempts.ts
|
|
1503
|
-
var
|
|
1504
|
-
var UNSEALED = Buffer.from(PURPOSE2);
|
|
1505
|
-
function counterKey(context) {
|
|
1506
|
-
const sealer = context.config.secondFactor?.sealer;
|
|
1507
|
-
return sealer === undefined ? UNSEALED : derivedKey(sealer, PURPOSE2);
|
|
1508
|
-
}
|
|
1509
|
-
var keyed = (key, parts) => keyedHash(key, parts).toString("base64url");
|
|
1594
|
+
var PURPOSE3 = "janus/sign-in/attempts/v1";
|
|
1510
1595
|
async function countLogin(context, type, login, where) {
|
|
1511
1596
|
const throttle = context.config.signInThrottle;
|
|
1512
1597
|
if (throttle === null)
|
|
1513
1598
|
return null;
|
|
1514
|
-
const key = counterKey(context);
|
|
1599
|
+
const key = counterKey(context, PURPOSE3);
|
|
1515
1600
|
const loginKey = keyed(key, [type.name, login]);
|
|
1516
1601
|
return countInWindow(context, {
|
|
1517
1602
|
windowMs: throttle.windowMs,
|
|
@@ -1634,7 +1719,7 @@ var RECOVERY_CODES = 10;
|
|
|
1634
1719
|
var ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz";
|
|
1635
1720
|
var LENGTH = 10;
|
|
1636
1721
|
var SHAPE = /^[0-9a-hjkmnp-tv-z]{10}$/;
|
|
1637
|
-
var
|
|
1722
|
+
var PURPOSE4 = "janus/second-factor/recovery-codes/v1";
|
|
1638
1723
|
function mintRecoveryCodes() {
|
|
1639
1724
|
return Array.from({ length: RECOVERY_CODES }, () => {
|
|
1640
1725
|
let code = "";
|
|
@@ -1648,7 +1733,7 @@ function readRecoveryCode(typed) {
|
|
|
1648
1733
|
const code = typed.toLowerCase().replace(/[\s-]/g, "").replace(/o/g, "0").replace(/[il]/g, "1");
|
|
1649
1734
|
return SHAPE.test(code) ? code : null;
|
|
1650
1735
|
}
|
|
1651
|
-
var macKey = (sealer, keyId) => derivedKey(sealer,
|
|
1736
|
+
var macKey = (sealer, keyId) => derivedKey(sealer, PURPOSE4, keyId);
|
|
1652
1737
|
var mac = (key, userId, code) => keyedHash(key, [userId, code]);
|
|
1653
1738
|
function hashRecoveryCode(sealer, userId, code) {
|
|
1654
1739
|
const read = readRecoveryCode(code) ?? code;
|
|
@@ -1759,7 +1844,7 @@ function accountOf(type, record, where) {
|
|
|
1759
1844
|
// src/auth/second-factor/app-code-attempts.ts
|
|
1760
1845
|
var APP_CODE_WINDOW_MS = 15 * 60000;
|
|
1761
1846
|
var WINDOW_MINUTES = APP_CODE_WINDOW_MS / 60000;
|
|
1762
|
-
var
|
|
1847
|
+
var PURPOSE5 = "janus/second-factor/regenerate-attempts/v1";
|
|
1763
1848
|
function linkHash(sealer, record, window, link) {
|
|
1764
1849
|
const parts = [
|
|
1765
1850
|
record.id,
|
|
@@ -1767,7 +1852,7 @@ function linkHash(sealer, record, window, link) {
|
|
|
1767
1852
|
String(record.secondFactor?.lastStep ?? ""),
|
|
1768
1853
|
String(link)
|
|
1769
1854
|
];
|
|
1770
|
-
const key = derivedKey(sealer,
|
|
1855
|
+
const key = derivedKey(sealer, PURPOSE5);
|
|
1771
1856
|
return hashSecret(keyedHash(key, parts).toString("base64url"));
|
|
1772
1857
|
}
|
|
1773
1858
|
async function countAppCodeAttempt(context, sealer, record, where) {
|
|
@@ -1883,14 +1968,15 @@ function secondFactorFlows(context, type, at) {
|
|
|
1883
1968
|
function signInCodeFlows(context, type, at, finish) {
|
|
1884
1969
|
return {
|
|
1885
1970
|
async request(email) {
|
|
1886
|
-
return requestCode(context, type, String(email));
|
|
1971
|
+
return requestCode(context, type, String(email), at("signInCode.request"));
|
|
1887
1972
|
},
|
|
1888
1973
|
async confirm(challenge, code, options) {
|
|
1889
1974
|
return confirmCode(context, type, finish, { challenge, code, options }, at);
|
|
1890
1975
|
}
|
|
1891
1976
|
};
|
|
1892
1977
|
}
|
|
1893
|
-
async function requestCode(context, type, email) {
|
|
1978
|
+
async function requestCode(context, type, email, where) {
|
|
1979
|
+
await countMailByAddress(context, type, "signInCode", email, where);
|
|
1894
1980
|
const record = await signInHolder(context, type, email);
|
|
1895
1981
|
if (record === null)
|
|
1896
1982
|
return null;
|
|
@@ -2028,6 +2114,7 @@ async function byEmail(context, type, record, where) {
|
|
|
2028
2114
|
operation: where
|
|
2029
2115
|
});
|
|
2030
2116
|
}
|
|
2117
|
+
await countMailByUser(context, type, "stepUp", record.id, where);
|
|
2031
2118
|
const { secret, code, expiresAt } = await issueCode(context, {
|
|
2032
2119
|
kind: "stepUp",
|
|
2033
2120
|
userId: record.id,
|
|
@@ -2320,6 +2407,7 @@ function typeApi(context, type) {
|
|
|
2320
2407
|
function janus(config) {
|
|
2321
2408
|
const where = "janus";
|
|
2322
2409
|
const resolved = resolveConfig(config, where);
|
|
2410
|
+
warnThrottleWindow(resolved, where);
|
|
2323
2411
|
const capabilities = assertStores(config.store, where);
|
|
2324
2412
|
const hasher = config.hasher ?? null;
|
|
2325
2413
|
const verifiers = [
|
|
@@ -2363,6 +2451,7 @@ export {
|
|
|
2363
2451
|
InvalidCursorError2 as InvalidCursorError,
|
|
2364
2452
|
JanusError2 as JanusError,
|
|
2365
2453
|
MAX_PAGE_SIZE2 as MAX_PAGE_SIZE,
|
|
2454
|
+
MailThrottledError2 as MailThrottledError,
|
|
2366
2455
|
NotFoundError2 as NotFoundError,
|
|
2367
2456
|
PermissionDepthError2 as PermissionDepthError,
|
|
2368
2457
|
SecondFactorError2 as SecondFactorError,
|
|
@@ -2399,5 +2488,5 @@ export {
|
|
|
2399
2488
|
systemClock
|
|
2400
2489
|
};
|
|
2401
2490
|
|
|
2402
|
-
//# debugId=
|
|
2491
|
+
//# debugId=ACD85BEBE6A087E464756E2164756E21
|
|
2403
2492
|
//# sourceMappingURL=index.js.map
|