cauthy-auth 0.27.1 → 0.28.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/dist/client.d.mts +12 -3
- package/dist/client.d.ts +12 -3
- package/dist/client.js +130 -15
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +124 -14
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +147 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +142 -17
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +27 -1
- package/dist/react.d.ts +27 -1
- package/dist/react.js +146 -19
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +146 -19
- package/dist/react.mjs.map +1 -1
- package/dist/styles.css +6 -0
- package/dist/svelte.d.mts +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/svelte.js +118 -13
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +118 -13
- package/dist/svelte.mjs.map +1 -1
- package/dist/validate-sEXG82po.d.mts +66 -0
- package/dist/validate-sEXG82po.d.ts +66 -0
- package/dist/vue.d.mts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +118 -13
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +118 -13
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/validate-YbEfIzfl.d.mts +0 -19
- package/dist/validate-YbEfIzfl.d.ts +0 -19
package/dist/vue.mjs
CHANGED
|
@@ -121,7 +121,111 @@ function fromWire(wire) {
|
|
|
121
121
|
// src/validate.ts
|
|
122
122
|
var MIN_PASSWORD = 12;
|
|
123
123
|
var MAX_PASSWORD = 128;
|
|
124
|
+
var FLOOR_PASSWORD = 8;
|
|
124
125
|
var MAX_NAME = 120;
|
|
126
|
+
var CLASSES = ["lowercase", "uppercase", "digit", "symbol"];
|
|
127
|
+
var DEFAULT_PASSWORD_POLICY = Object.freeze({ min: MIN_PASSWORD, max: MAX_PASSWORD, requires: [], min_classes: 0, reject_breached: false });
|
|
128
|
+
var int = (v, fallback) => typeof v === "number" && Number.isFinite(v) ? Math.trunc(v) : fallback;
|
|
129
|
+
function passwordPolicyOf(raw) {
|
|
130
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
131
|
+
const min = Math.min(Math.max(int(r.min ?? r.min_length, MIN_PASSWORD) || MIN_PASSWORD, FLOOR_PASSWORD), MAX_PASSWORD);
|
|
132
|
+
const max = Math.max(Math.min(int(r.max ?? r.max_length, MAX_PASSWORD) || MAX_PASSWORD, MAX_PASSWORD), min);
|
|
133
|
+
const asked = Array.isArray(r.requires) ? r.requires : [];
|
|
134
|
+
return {
|
|
135
|
+
min,
|
|
136
|
+
max,
|
|
137
|
+
requires: CLASSES.filter((c) => asked.includes(c)),
|
|
138
|
+
min_classes: Math.min(Math.max(int(r.min_classes ?? r.minClasses, 0), 0), CLASSES.length),
|
|
139
|
+
reject_breached: (r.reject_breached ?? r.rejectBreached) === true
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function utf8Length(v) {
|
|
143
|
+
let n = 0;
|
|
144
|
+
for (const ch of v) {
|
|
145
|
+
const c = ch.codePointAt(0);
|
|
146
|
+
n += c < 128 ? 1 : c < 2048 ? 2 : c < 65536 ? 3 : 4;
|
|
147
|
+
}
|
|
148
|
+
return n;
|
|
149
|
+
}
|
|
150
|
+
function classesOf(v) {
|
|
151
|
+
const has = /* @__PURE__ */ new Set();
|
|
152
|
+
for (const ch of v) {
|
|
153
|
+
if (/\p{Ll}/u.test(ch)) has.add("lowercase");
|
|
154
|
+
else if (/\p{Lu}/u.test(ch)) has.add("uppercase");
|
|
155
|
+
else if (/\p{Nd}/u.test(ch)) has.add("digit");
|
|
156
|
+
else if (!/\p{L}/u.test(ch)) has.add("symbol");
|
|
157
|
+
}
|
|
158
|
+
return has;
|
|
159
|
+
}
|
|
160
|
+
function passwordProblems(value, policy = DEFAULT_PASSWORD_POLICY) {
|
|
161
|
+
const p = passwordPolicyOf(policy);
|
|
162
|
+
const out = [];
|
|
163
|
+
const length = utf8Length(value);
|
|
164
|
+
if (length < p.min) out.push("too_short");
|
|
165
|
+
if (length > p.max) out.push("too_long");
|
|
166
|
+
const has = classesOf(value);
|
|
167
|
+
for (const c of p.requires) if (!has.has(c)) out.push(`needs_${c}`);
|
|
168
|
+
if (p.min_classes > 0 && CLASSES.filter((c) => has.has(c)).length < p.min_classes) out.push("needs_classes");
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
var RULES = {
|
|
172
|
+
en: {
|
|
173
|
+
between: "Between {min} and {max} characters.",
|
|
174
|
+
requires: "Include {kinds}.",
|
|
175
|
+
and: "and",
|
|
176
|
+
classes: "Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.",
|
|
177
|
+
breached: "Passwords found in known data breaches are not accepted.",
|
|
178
|
+
kinds: { lowercase: "a lowercase letter", uppercase: "an uppercase letter", digit: "a digit", symbol: "a symbol" },
|
|
179
|
+
reasons: {
|
|
180
|
+
too_short: "Use at least {min} characters.",
|
|
181
|
+
too_long: "Use at most {max} characters.",
|
|
182
|
+
needs_lowercase: "Include a lowercase letter.",
|
|
183
|
+
needs_uppercase: "Include an uppercase letter.",
|
|
184
|
+
needs_digit: "Include a digit.",
|
|
185
|
+
needs_symbol: "Include a symbol.",
|
|
186
|
+
needs_classes: "Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.",
|
|
187
|
+
breached: "This password appears in a known data breach. Choose a different one."
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
es: {
|
|
191
|
+
between: "Entre {min} y {max} caracteres.",
|
|
192
|
+
requires: "Incluye {kinds}.",
|
|
193
|
+
and: "y",
|
|
194
|
+
classes: "Usa al menos {n} de estos tipos: min\xFAsculas, may\xFAsculas, n\xFAmeros, s\xEDmbolos.",
|
|
195
|
+
breached: "No se aceptan contrase\xF1as que aparecen en filtraciones de datos conocidas.",
|
|
196
|
+
kinds: { lowercase: "una min\xFAscula", uppercase: "una may\xFAscula", digit: "un n\xFAmero", symbol: "un s\xEDmbolo" },
|
|
197
|
+
reasons: {
|
|
198
|
+
too_short: "Usa al menos {min} caracteres.",
|
|
199
|
+
too_long: "Usa como m\xE1ximo {max} caracteres.",
|
|
200
|
+
needs_lowercase: "Incluye una min\xFAscula.",
|
|
201
|
+
needs_uppercase: "Incluye una may\xFAscula.",
|
|
202
|
+
needs_digit: "Incluye un n\xFAmero.",
|
|
203
|
+
needs_symbol: "Incluye un s\xEDmbolo.",
|
|
204
|
+
needs_classes: "Usa al menos {n} de estos tipos: min\xFAsculas, may\xFAsculas, n\xFAmeros, s\xEDmbolos.",
|
|
205
|
+
breached: "Esta contrase\xF1a aparece en una filtraci\xF3n de datos conocida. Elige otra."
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
var fill = (s, p) => s.replace("{min}", String(p.min)).replace("{max}", String(p.max)).replace("{n}", String(p.min_classes));
|
|
210
|
+
function describePasswordPolicy(policy = DEFAULT_PASSWORD_POLICY, locale = "en") {
|
|
211
|
+
const p = passwordPolicyOf(policy);
|
|
212
|
+
const t = RULES[locale] ?? RULES.en;
|
|
213
|
+
const parts = [fill(t.between, p)];
|
|
214
|
+
if (p.requires.length > 0) {
|
|
215
|
+
const kinds = p.requires.map((c) => t.kinds[c]);
|
|
216
|
+
const listed = kinds.length === 1 ? kinds[0] : `${kinds.slice(0, -1).join(", ")} ${t.and} ${kinds[kinds.length - 1]}`;
|
|
217
|
+
parts.push(t.requires.replace("{kinds}", listed));
|
|
218
|
+
}
|
|
219
|
+
if (p.min_classes > 0) parts.push(fill(t.classes, p));
|
|
220
|
+
if (p.reject_breached) parts.push(t.breached);
|
|
221
|
+
return parts.join(" ");
|
|
222
|
+
}
|
|
223
|
+
function explainPasswordProblems(reasons, policy = DEFAULT_PASSWORD_POLICY, locale = "en") {
|
|
224
|
+
const p = passwordPolicyOf(policy);
|
|
225
|
+
const t = RULES[locale] ?? RULES.en;
|
|
226
|
+
const said = reasons.filter((r) => r in t.reasons).map((r) => fill(t.reasons[r], p));
|
|
227
|
+
return said.length > 0 ? said.join(" ") : describePasswordPolicy(p, locale);
|
|
228
|
+
}
|
|
125
229
|
var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
126
230
|
function checkEmail(value) {
|
|
127
231
|
const v = typeof value === "string" ? value.trim() : "";
|
|
@@ -134,13 +238,12 @@ function checkPassword(value) {
|
|
|
134
238
|
if (value.length > MAX_PASSWORD) return { field: "password", code: "too_long", message: "That password is too long." };
|
|
135
239
|
return null;
|
|
136
240
|
}
|
|
137
|
-
function checkNewPassword(value) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
return null;
|
|
241
|
+
function checkNewPassword(value, policy) {
|
|
242
|
+
if (typeof value !== "string" || value === "") return { field: "password", code: "required", message: "Enter your password." };
|
|
243
|
+
const p = policy ? passwordPolicyOf(policy) : DEFAULT_PASSWORD_POLICY;
|
|
244
|
+
const reasons = passwordProblems(value, p);
|
|
245
|
+
if (reasons.length === 0) return null;
|
|
246
|
+
return { field: "password", code: reasons[0], message: explainPasswordProblems(reasons, p) };
|
|
144
247
|
}
|
|
145
248
|
function checkName(value) {
|
|
146
249
|
if (value === void 0 || value === null || value === "") return null;
|
|
@@ -203,7 +306,7 @@ function createAuthClient(options = {}) {
|
|
|
203
306
|
const body = await res.json().catch(() => null);
|
|
204
307
|
if (res.ok && body && typeof body.status === "string") return { ok: true, ...body };
|
|
205
308
|
const e = body?.error;
|
|
206
|
-
return { ok: false, error: e && typeof e.code === "string" ? { code: e.code, message: String(e.message ?? ""), ...e.field ? { field: e.field } : {} } : UNAVAILABLE };
|
|
309
|
+
return { ok: false, error: e && typeof e.code === "string" ? { code: e.code, message: String(e.message ?? ""), ...e.field ? { field: e.field } : {}, ...Array.isArray(e.reasons) ? { reasons: e.reasons.map(String) } : {} } : UNAVAILABLE };
|
|
207
310
|
} catch {
|
|
208
311
|
return { ok: false, error: UNAVAILABLE };
|
|
209
312
|
}
|
|
@@ -231,12 +334,14 @@ function createAuthClient(options = {}) {
|
|
|
231
334
|
if (o.locale) q.set("locale", o.locale);
|
|
232
335
|
return `${base}/login?${q}`;
|
|
233
336
|
};
|
|
337
|
+
let policy;
|
|
234
338
|
async function methods() {
|
|
235
339
|
try {
|
|
236
340
|
const res = await doFetch(`${base}/methods`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
237
341
|
if (res.ok) {
|
|
238
342
|
const m = await res.json();
|
|
239
|
-
|
|
343
|
+
if (m.password) policy = passwordPolicyOf(m.password);
|
|
344
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, ...policy ? { password: policy } : {}, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true, sso: m.sso === true };
|
|
240
345
|
}
|
|
241
346
|
} catch {
|
|
242
347
|
}
|
|
@@ -380,12 +485,12 @@ function createAuthClient(options = {}) {
|
|
|
380
485
|
email: (f) => post(
|
|
381
486
|
"/sign-up/email",
|
|
382
487
|
{ email: f.email, password: f.password, name: f.name, organization: f.organization, acceptLegal: f.acceptLegal, consents: f.consents },
|
|
383
|
-
firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password), checkOrganization(f.organization)),
|
|
488
|
+
firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password, policy), checkOrganization(f.organization)),
|
|
384
489
|
f.captchaToken
|
|
385
490
|
)
|
|
386
491
|
},
|
|
387
492
|
forgotPassword: (f) => post("/forgot-password", { email: f.email }, checkEmail(f.email), f.captchaToken),
|
|
388
|
-
resetPassword: (f) => post("/reset-password", { token: f.token, password: f.password }, checkNewPassword(f.password)),
|
|
493
|
+
resetPassword: (f) => post("/reset-password", { token: f.token, password: f.password }, checkNewPassword(f.password, policy)),
|
|
389
494
|
verifyEmail: (f) => post("/verify-email", { token: f.token }, null),
|
|
390
495
|
signOut: () => post("/sign-out", {}, null),
|
|
391
496
|
organizations: {
|
|
@@ -419,7 +524,7 @@ function createAuthClient(options = {}) {
|
|
|
419
524
|
},
|
|
420
525
|
acceptLegal: (f = {}) => post("/me/legal/accept", { kinds: f.kinds ?? [] }, null),
|
|
421
526
|
changePassword: (f) => {
|
|
422
|
-
const bad = checkNewPassword(f.newPassword);
|
|
527
|
+
const bad = checkNewPassword(f.newPassword, policy);
|
|
423
528
|
return post("/me/password", { password: f.password, newPassword: f.newPassword }, bad ? { ...bad, field: "newPassword" } : null);
|
|
424
529
|
},
|
|
425
530
|
mfa: {
|
|
@@ -450,7 +555,7 @@ function createAuthClient(options = {}) {
|
|
|
450
555
|
return body && Array.isArray(body.sessions) ? body.sessions : [];
|
|
451
556
|
},
|
|
452
557
|
signOutEverywhere: () => post("/me/sessions/end", {}, null),
|
|
453
|
-
upgrade: (f) => post("/me/upgrade", { email: f.email, password: f.password, name: f.name ?? "" }, firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password))),
|
|
558
|
+
upgrade: (f) => post("/me/upgrade", { email: f.email, password: f.password, name: f.name ?? "" }, firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password, policy))),
|
|
454
559
|
upgradeUrl,
|
|
455
560
|
upgradeWith(provider, o) {
|
|
456
561
|
window.location.assign(upgradeUrl(provider, o));
|