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/react.mjs
CHANGED
|
@@ -147,7 +147,111 @@ function fromWire(wire) {
|
|
|
147
147
|
// src/validate.ts
|
|
148
148
|
var MIN_PASSWORD = 12;
|
|
149
149
|
var MAX_PASSWORD = 128;
|
|
150
|
+
var FLOOR_PASSWORD = 8;
|
|
150
151
|
var MAX_NAME = 120;
|
|
152
|
+
var CLASSES = ["lowercase", "uppercase", "digit", "symbol"];
|
|
153
|
+
var DEFAULT_PASSWORD_POLICY = Object.freeze({ min: MIN_PASSWORD, max: MAX_PASSWORD, requires: [], min_classes: 0, reject_breached: false });
|
|
154
|
+
var int = (v, fallback) => typeof v === "number" && Number.isFinite(v) ? Math.trunc(v) : fallback;
|
|
155
|
+
function passwordPolicyOf(raw) {
|
|
156
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
157
|
+
const min = Math.min(Math.max(int(r.min ?? r.min_length, MIN_PASSWORD) || MIN_PASSWORD, FLOOR_PASSWORD), MAX_PASSWORD);
|
|
158
|
+
const max = Math.max(Math.min(int(r.max ?? r.max_length, MAX_PASSWORD) || MAX_PASSWORD, MAX_PASSWORD), min);
|
|
159
|
+
const asked = Array.isArray(r.requires) ? r.requires : [];
|
|
160
|
+
return {
|
|
161
|
+
min,
|
|
162
|
+
max,
|
|
163
|
+
requires: CLASSES.filter((c) => asked.includes(c)),
|
|
164
|
+
min_classes: Math.min(Math.max(int(r.min_classes ?? r.minClasses, 0), 0), CLASSES.length),
|
|
165
|
+
reject_breached: (r.reject_breached ?? r.rejectBreached) === true
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function utf8Length(v) {
|
|
169
|
+
let n = 0;
|
|
170
|
+
for (const ch of v) {
|
|
171
|
+
const c = ch.codePointAt(0);
|
|
172
|
+
n += c < 128 ? 1 : c < 2048 ? 2 : c < 65536 ? 3 : 4;
|
|
173
|
+
}
|
|
174
|
+
return n;
|
|
175
|
+
}
|
|
176
|
+
function classesOf(v) {
|
|
177
|
+
const has = /* @__PURE__ */ new Set();
|
|
178
|
+
for (const ch of v) {
|
|
179
|
+
if (/\p{Ll}/u.test(ch)) has.add("lowercase");
|
|
180
|
+
else if (/\p{Lu}/u.test(ch)) has.add("uppercase");
|
|
181
|
+
else if (/\p{Nd}/u.test(ch)) has.add("digit");
|
|
182
|
+
else if (!/\p{L}/u.test(ch)) has.add("symbol");
|
|
183
|
+
}
|
|
184
|
+
return has;
|
|
185
|
+
}
|
|
186
|
+
function passwordProblems(value, policy = DEFAULT_PASSWORD_POLICY) {
|
|
187
|
+
const p = passwordPolicyOf(policy);
|
|
188
|
+
const out = [];
|
|
189
|
+
const length = utf8Length(value);
|
|
190
|
+
if (length < p.min) out.push("too_short");
|
|
191
|
+
if (length > p.max) out.push("too_long");
|
|
192
|
+
const has = classesOf(value);
|
|
193
|
+
for (const c of p.requires) if (!has.has(c)) out.push(`needs_${c}`);
|
|
194
|
+
if (p.min_classes > 0 && CLASSES.filter((c) => has.has(c)).length < p.min_classes) out.push("needs_classes");
|
|
195
|
+
return out;
|
|
196
|
+
}
|
|
197
|
+
var RULES = {
|
|
198
|
+
en: {
|
|
199
|
+
between: "Between {min} and {max} characters.",
|
|
200
|
+
requires: "Include {kinds}.",
|
|
201
|
+
and: "and",
|
|
202
|
+
classes: "Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.",
|
|
203
|
+
breached: "Passwords found in known data breaches are not accepted.",
|
|
204
|
+
kinds: { lowercase: "a lowercase letter", uppercase: "an uppercase letter", digit: "a digit", symbol: "a symbol" },
|
|
205
|
+
reasons: {
|
|
206
|
+
too_short: "Use at least {min} characters.",
|
|
207
|
+
too_long: "Use at most {max} characters.",
|
|
208
|
+
needs_lowercase: "Include a lowercase letter.",
|
|
209
|
+
needs_uppercase: "Include an uppercase letter.",
|
|
210
|
+
needs_digit: "Include a digit.",
|
|
211
|
+
needs_symbol: "Include a symbol.",
|
|
212
|
+
needs_classes: "Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.",
|
|
213
|
+
breached: "This password appears in a known data breach. Choose a different one."
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
es: {
|
|
217
|
+
between: "Entre {min} y {max} caracteres.",
|
|
218
|
+
requires: "Incluye {kinds}.",
|
|
219
|
+
and: "y",
|
|
220
|
+
classes: "Usa al menos {n} de estos tipos: min\xFAsculas, may\xFAsculas, n\xFAmeros, s\xEDmbolos.",
|
|
221
|
+
breached: "No se aceptan contrase\xF1as que aparecen en filtraciones de datos conocidas.",
|
|
222
|
+
kinds: { lowercase: "una min\xFAscula", uppercase: "una may\xFAscula", digit: "un n\xFAmero", symbol: "un s\xEDmbolo" },
|
|
223
|
+
reasons: {
|
|
224
|
+
too_short: "Usa al menos {min} caracteres.",
|
|
225
|
+
too_long: "Usa como m\xE1ximo {max} caracteres.",
|
|
226
|
+
needs_lowercase: "Incluye una min\xFAscula.",
|
|
227
|
+
needs_uppercase: "Incluye una may\xFAscula.",
|
|
228
|
+
needs_digit: "Incluye un n\xFAmero.",
|
|
229
|
+
needs_symbol: "Incluye un s\xEDmbolo.",
|
|
230
|
+
needs_classes: "Usa al menos {n} de estos tipos: min\xFAsculas, may\xFAsculas, n\xFAmeros, s\xEDmbolos.",
|
|
231
|
+
breached: "Esta contrase\xF1a aparece en una filtraci\xF3n de datos conocida. Elige otra."
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
var fill = (s, p) => s.replace("{min}", String(p.min)).replace("{max}", String(p.max)).replace("{n}", String(p.min_classes));
|
|
236
|
+
function describePasswordPolicy(policy = DEFAULT_PASSWORD_POLICY, locale = "en") {
|
|
237
|
+
const p = passwordPolicyOf(policy);
|
|
238
|
+
const t = RULES[locale] ?? RULES.en;
|
|
239
|
+
const parts = [fill(t.between, p)];
|
|
240
|
+
if (p.requires.length > 0) {
|
|
241
|
+
const kinds = p.requires.map((c) => t.kinds[c]);
|
|
242
|
+
const listed = kinds.length === 1 ? kinds[0] : `${kinds.slice(0, -1).join(", ")} ${t.and} ${kinds[kinds.length - 1]}`;
|
|
243
|
+
parts.push(t.requires.replace("{kinds}", listed));
|
|
244
|
+
}
|
|
245
|
+
if (p.min_classes > 0) parts.push(fill(t.classes, p));
|
|
246
|
+
if (p.reject_breached) parts.push(t.breached);
|
|
247
|
+
return parts.join(" ");
|
|
248
|
+
}
|
|
249
|
+
function explainPasswordProblems(reasons, policy = DEFAULT_PASSWORD_POLICY, locale = "en") {
|
|
250
|
+
const p = passwordPolicyOf(policy);
|
|
251
|
+
const t = RULES[locale] ?? RULES.en;
|
|
252
|
+
const said = reasons.filter((r) => r in t.reasons).map((r) => fill(t.reasons[r], p));
|
|
253
|
+
return said.length > 0 ? said.join(" ") : describePasswordPolicy(p, locale);
|
|
254
|
+
}
|
|
151
255
|
var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
152
256
|
function checkEmail(value) {
|
|
153
257
|
const v = typeof value === "string" ? value.trim() : "";
|
|
@@ -160,13 +264,12 @@ function checkPassword(value) {
|
|
|
160
264
|
if (value.length > MAX_PASSWORD) return { field: "password", code: "too_long", message: "That password is too long." };
|
|
161
265
|
return null;
|
|
162
266
|
}
|
|
163
|
-
function checkNewPassword(value) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
return null;
|
|
267
|
+
function checkNewPassword(value, policy) {
|
|
268
|
+
if (typeof value !== "string" || value === "") return { field: "password", code: "required", message: "Enter your password." };
|
|
269
|
+
const p = policy ? passwordPolicyOf(policy) : DEFAULT_PASSWORD_POLICY;
|
|
270
|
+
const reasons = passwordProblems(value, p);
|
|
271
|
+
if (reasons.length === 0) return null;
|
|
272
|
+
return { field: "password", code: reasons[0], message: explainPasswordProblems(reasons, p) };
|
|
170
273
|
}
|
|
171
274
|
function checkName(value) {
|
|
172
275
|
if (value === void 0 || value === null || value === "") return null;
|
|
@@ -229,7 +332,7 @@ function createAuthClient(options = {}) {
|
|
|
229
332
|
const body = await res.json().catch(() => null);
|
|
230
333
|
if (res.ok && body && typeof body.status === "string") return { ok: true, ...body };
|
|
231
334
|
const e = body?.error;
|
|
232
|
-
return { ok: false, error: e && typeof e.code === "string" ? { code: e.code, message: String(e.message ?? ""), ...e.field ? { field: e.field } : {} } : UNAVAILABLE };
|
|
335
|
+
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 };
|
|
233
336
|
} catch {
|
|
234
337
|
return { ok: false, error: UNAVAILABLE };
|
|
235
338
|
}
|
|
@@ -257,12 +360,14 @@ function createAuthClient(options = {}) {
|
|
|
257
360
|
if (o.locale) q.set("locale", o.locale);
|
|
258
361
|
return `${base}/login?${q}`;
|
|
259
362
|
};
|
|
363
|
+
let policy;
|
|
260
364
|
async function methods() {
|
|
261
365
|
try {
|
|
262
366
|
const res = await doFetch(`${base}/methods`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
263
367
|
if (res.ok) {
|
|
264
368
|
const m = await res.json();
|
|
265
|
-
|
|
369
|
+
if (m.password) policy = passwordPolicyOf(m.password);
|
|
370
|
+
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 };
|
|
266
371
|
}
|
|
267
372
|
} catch {
|
|
268
373
|
}
|
|
@@ -406,12 +511,12 @@ function createAuthClient(options = {}) {
|
|
|
406
511
|
email: (f) => post(
|
|
407
512
|
"/sign-up/email",
|
|
408
513
|
{ email: f.email, password: f.password, name: f.name, organization: f.organization, acceptLegal: f.acceptLegal, consents: f.consents },
|
|
409
|
-
firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password), checkOrganization(f.organization)),
|
|
514
|
+
firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password, policy), checkOrganization(f.organization)),
|
|
410
515
|
f.captchaToken
|
|
411
516
|
)
|
|
412
517
|
},
|
|
413
518
|
forgotPassword: (f) => post("/forgot-password", { email: f.email }, checkEmail(f.email), f.captchaToken),
|
|
414
|
-
resetPassword: (f) => post("/reset-password", { token: f.token, password: f.password }, checkNewPassword(f.password)),
|
|
519
|
+
resetPassword: (f) => post("/reset-password", { token: f.token, password: f.password }, checkNewPassword(f.password, policy)),
|
|
415
520
|
verifyEmail: (f) => post("/verify-email", { token: f.token }, null),
|
|
416
521
|
signOut: () => post("/sign-out", {}, null),
|
|
417
522
|
organizations: {
|
|
@@ -445,7 +550,7 @@ function createAuthClient(options = {}) {
|
|
|
445
550
|
},
|
|
446
551
|
acceptLegal: (f = {}) => post("/me/legal/accept", { kinds: f.kinds ?? [] }, null),
|
|
447
552
|
changePassword: (f) => {
|
|
448
|
-
const bad = checkNewPassword(f.newPassword);
|
|
553
|
+
const bad = checkNewPassword(f.newPassword, policy);
|
|
449
554
|
return post("/me/password", { password: f.password, newPassword: f.newPassword }, bad ? { ...bad, field: "newPassword" } : null);
|
|
450
555
|
},
|
|
451
556
|
mfa: {
|
|
@@ -476,7 +581,7 @@ function createAuthClient(options = {}) {
|
|
|
476
581
|
return body && Array.isArray(body.sessions) ? body.sessions : [];
|
|
477
582
|
},
|
|
478
583
|
signOutEverywhere: () => post("/me/sessions/end", {}, null),
|
|
479
|
-
upgrade: (f) => post("/me/upgrade", { email: f.email, password: f.password, name: f.name ?? "" }, firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password))),
|
|
584
|
+
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))),
|
|
480
585
|
upgradeUrl,
|
|
481
586
|
upgradeWith(provider, o) {
|
|
482
587
|
window.location.assign(upgradeUrl(provider, o));
|
|
@@ -998,18 +1103,36 @@ function useForm(props) {
|
|
|
998
1103
|
const Input = props.components?.Input ?? PlainInput;
|
|
999
1104
|
const [error, setError] = useState(null);
|
|
1000
1105
|
const [busy, setBusy] = useState(false);
|
|
1001
|
-
const
|
|
1106
|
+
const [policy, setPolicy] = useState(void 0);
|
|
1107
|
+
const locale = props.locale ?? "en";
|
|
1108
|
+
const say = (e) => {
|
|
1109
|
+
if (props.texts?.errors?.[e.code] === void 0 && isPasswordRule(e)) return explainPasswordProblems(e.reasons ?? [e.code], policy, locale);
|
|
1110
|
+
return t.errors[e.code] ?? e.message;
|
|
1111
|
+
};
|
|
1112
|
+
const passwordRule = describePasswordPolicy(policy, locale);
|
|
1002
1113
|
const done = (to) => {
|
|
1003
1114
|
if (props.onSuccess) props.onSuccess();
|
|
1004
1115
|
else window.location.assign(sitePath(to) ?? sameOrigin(props.returnTo) ?? "/");
|
|
1005
1116
|
};
|
|
1006
1117
|
const root = useRoot(props);
|
|
1007
|
-
return { t, cx, Button, Input, error, setError, busy, setBusy, say, done, root };
|
|
1118
|
+
return { t, cx, Button, Input, error, setError, busy, setBusy, say, done, root, policy, setPolicy, passwordRule };
|
|
1119
|
+
}
|
|
1120
|
+
var PASSWORD_RULES = ["needs_lowercase", "needs_uppercase", "needs_digit", "needs_symbol", "needs_classes", "breached"];
|
|
1121
|
+
function isPasswordRule(e) {
|
|
1122
|
+
if (e.code === "weak_password" || PASSWORD_RULES.includes(e.code)) return true;
|
|
1123
|
+
return (e.code === "too_short" || e.code === "too_long") && (e.field === "password" || e.field === "newPassword");
|
|
1124
|
+
}
|
|
1125
|
+
function usePasswordPolicy(f, methods) {
|
|
1126
|
+
const { setPolicy } = f;
|
|
1127
|
+
useEffect(() => {
|
|
1128
|
+
if (methods?.password) setPolicy(methods.password);
|
|
1129
|
+
}, [methods, setPolicy]);
|
|
1008
1130
|
}
|
|
1009
1131
|
function Field(p) {
|
|
1010
1132
|
const id = useId();
|
|
1011
1133
|
const { f } = p;
|
|
1012
1134
|
const bad = f.error?.field === p.name ? f.error : null;
|
|
1135
|
+
const described = [bad ? `${id}-error` : "", p.hint ? `${id}-hint` : ""].filter(Boolean).join(" ");
|
|
1013
1136
|
return /* @__PURE__ */ jsxs("div", { className: f.cx("field"), children: [
|
|
1014
1137
|
/* @__PURE__ */ jsxs("label", { className: f.cx("label"), htmlFor: id, children: [
|
|
1015
1138
|
p.label,
|
|
@@ -1026,10 +1149,11 @@ function Field(p) {
|
|
|
1026
1149
|
required: p.required,
|
|
1027
1150
|
className: f.cx("input"),
|
|
1028
1151
|
"aria-invalid": bad ? true : void 0,
|
|
1029
|
-
"aria-describedby":
|
|
1152
|
+
"aria-describedby": described || void 0,
|
|
1030
1153
|
onChange: (e) => p.onChange(e.target.value)
|
|
1031
1154
|
}
|
|
1032
1155
|
),
|
|
1156
|
+
p.hint && !bad && /* @__PURE__ */ jsx("span", { id: `${id}-hint`, className: f.cx("hint"), children: p.hint }),
|
|
1033
1157
|
bad && /* @__PURE__ */ jsx("span", { id: `${id}-error`, role: "alert", className: f.cx("fieldError"), children: f.say(bad) })
|
|
1034
1158
|
] });
|
|
1035
1159
|
}
|
|
@@ -1290,6 +1414,7 @@ function SignUp(props) {
|
|
|
1290
1414
|
const [password, setPassword] = useState("");
|
|
1291
1415
|
const [sent, setSent] = useState(false);
|
|
1292
1416
|
const methods = useMethods(auth);
|
|
1417
|
+
usePasswordPolicy(f, methods);
|
|
1293
1418
|
const challenge = useChallenge(methods?.captchaSiteKey, props.locale);
|
|
1294
1419
|
const [acceptLegal, setAcceptLegal] = useState(false);
|
|
1295
1420
|
const [consents, setConsents] = useState({});
|
|
@@ -1324,7 +1449,7 @@ function SignUp(props) {
|
|
|
1324
1449
|
methods?.organization?.ask && /* @__PURE__ */ jsx(Field, { f, name: "organization", type: "text", label: f.t.company, value: organization, autoComplete: "organization", required: methods.organization.required, onChange: setOrganization }),
|
|
1325
1450
|
/* @__PURE__ */ jsx(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
1326
1451
|
/* @__PURE__ */ jsx(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
|
|
1327
|
-
/* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.password, value: password, autoComplete: "new-password", required: true, onChange: setPassword }),
|
|
1452
|
+
/* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.password, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1328
1453
|
legal && legal.documents.length > 0 && /* @__PURE__ */ jsxs("label", { className: f.cx("check"), children: [
|
|
1329
1454
|
/* @__PURE__ */ jsx("input", { type: "checkbox", name: "acceptLegal", checked: acceptLegal, required: true, onChange: (e) => setAcceptLegal(e.target.checked) }),
|
|
1330
1455
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
@@ -1390,6 +1515,7 @@ function ResetPassword(props) {
|
|
|
1390
1515
|
const [token, setToken] = useState(null);
|
|
1391
1516
|
const [password, setPassword] = useState("");
|
|
1392
1517
|
const [changed, setChanged] = useState(false);
|
|
1518
|
+
usePasswordPolicy(f, useMethods(auth));
|
|
1393
1519
|
useMailedToken("token", (t) => {
|
|
1394
1520
|
setToken(t ?? "");
|
|
1395
1521
|
if (!t) f.setError({ code: "invalid_token", message: "This link is not valid, or it has expired." });
|
|
@@ -1419,7 +1545,7 @@ function ResetPassword(props) {
|
|
|
1419
1545
|
}
|
|
1420
1546
|
return /* @__PURE__ */ jsxs("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1421
1547
|
general && /* @__PURE__ */ jsx("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
|
|
1422
|
-
/* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.newPassword, value: password, autoComplete: "new-password", required: true, onChange: setPassword }),
|
|
1548
|
+
/* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.newPassword, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1423
1549
|
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy || token === null, className: f.cx("button"), children: f.t.savePassword })
|
|
1424
1550
|
] });
|
|
1425
1551
|
}
|
|
@@ -1760,6 +1886,7 @@ function PasswordPart({ props }) {
|
|
|
1760
1886
|
const { f, done, setDone, run, general } = useSection(props);
|
|
1761
1887
|
const [password, setPassword] = useState("");
|
|
1762
1888
|
const [newPassword, setNewPassword] = useState("");
|
|
1889
|
+
usePasswordPolicy(f, useMethods(auth));
|
|
1763
1890
|
const submit = async (e) => {
|
|
1764
1891
|
e.preventDefault();
|
|
1765
1892
|
const r = await run(() => auth.account.changePassword({ password, newPassword }));
|
|
@@ -1772,7 +1899,7 @@ function PasswordPart({ props }) {
|
|
|
1772
1899
|
/* @__PURE__ */ jsx("h2", { className: f.cx("heading"), children: f.t.changePassword }),
|
|
1773
1900
|
general && /* @__PURE__ */ jsx("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
|
|
1774
1901
|
/* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
1775
|
-
/* @__PURE__ */ jsx(Field, { f, name: "newPassword", type: "password", label: f.t.newPassword, value: newPassword, autoComplete: "new-password", required: true, onChange: setNewPassword }),
|
|
1902
|
+
/* @__PURE__ */ jsx(Field, { f, name: "newPassword", type: "password", label: f.t.newPassword, value: newPassword, autoComplete: "new-password", required: true, onChange: setNewPassword, hint: f.passwordRule }),
|
|
1776
1903
|
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changePassword }),
|
|
1777
1904
|
done && /* @__PURE__ */ jsx("p", { role: "status", className: f.cx("notice"), children: done })
|
|
1778
1905
|
] });
|