sporades 0.7.1 โ†’ 0.7.2

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/CHANGES.md CHANGED
@@ -1,22 +1,9 @@
1
1
  # Changes
2
2
 
3
- ## Unreleased - 2026-08-12
3
+ ## Unreleased - 2026-08-13
4
4
 
5
- Changes since v0.7.0.
6
-
7
- ### ๐Ÿš€ Features
8
-
9
- - Adapt Mailgun email events (66d4291).
10
- - Adapt Postmark email events (d30efa2).
11
- - Adapt SMTP2GO email events (8d39237).
12
- - Dispatch verified email provider events (d818b6d).
13
- - Trust required native installers (c0a539c).
5
+ Changes since v0.7.1.
14
6
 
15
7
  ### ๐Ÿ“ Documentation
16
8
 
17
- - Clarify provider callback responses (7fde2ae).
18
- - Document Mailjet SMTP configuration (e710ba2).
19
-
20
- ### ๐Ÿงช Tests
21
-
22
- - Cover Mailgun non-delivery retries (c5e566e).
9
+ - Require current password to change email credentials (bfba651).
@@ -413,7 +413,7 @@ function writeEnvelope(result, failed = false) {
413
413
  }
414
414
 
415
415
  // src/cli/cli-version.ts
416
- var CLI_VERSION = "0.7.1";
416
+ var CLI_VERSION = "0.7.2";
417
417
 
418
418
  // src/cli/schedule-inspection-envelope.ts
419
419
  function sanitizeScheduleInspectionEnvelope(envelope, invalid) {
package/bin/sporades.js CHANGED
@@ -82,8 +82,8 @@ export const auth = {
82
82
  signOut() {
83
83
  return connect().signOut();
84
84
  },
85
- setPassword(email, newPassword) {
86
- return connect().setPassword(email, newPassword);
85
+ setPassword(email, currentPassword, newPassword) {
86
+ return connect().setPassword(email, currentPassword, newPassword);
87
87
  },
88
88
  sendPasswordResetLink(email) {
89
89
  return connect().sendPasswordResetLink(email);
@@ -174,8 +174,8 @@ export function createHooks(primitives) {
174
174
  signOut() {
175
175
  return connect().signOut();
176
176
  },
177
- setPassword(email, newPassword) {
178
- return connect().setPassword(email, newPassword);
177
+ setPassword(email, currentPassword, newPassword) {
178
+ return connect().setPassword(email, currentPassword, newPassword);
179
179
  },
180
180
  };
181
181
  }
@@ -232,7 +232,7 @@ export function createVueComposables(primitives) {
232
232
  state.signUp = (provider, credentials) => connect().signUp(provider, credentials);
233
233
  state.signIn = (provider, credentials) => connect().signIn(provider, credentials);
234
234
  state.signOut = () => connect().signOut();
235
- state.setPassword = (email, newPassword) => connect().setPassword(email, newPassword);
235
+ state.setPassword = (email, currentPassword, newPassword) => connect().setPassword(email, currentPassword, newPassword);
236
236
  return state;
237
237
  }
238
238
 
@@ -284,7 +284,7 @@ export function createSolidPrimitives(primitives) {
284
284
  signUp: (provider, credentials) => connect().signUp(provider, credentials),
285
285
  signIn: (provider, credentials) => connect().signIn(provider, credentials),
286
286
  signOut: () => connect().signOut(),
287
- setPassword: (email, newPassword) => connect().setPassword(email, newPassword),
287
+ setPassword: (email, currentPassword, newPassword) => connect().setPassword(email, currentPassword, newPassword),
288
288
  };
289
289
  }
290
290
 
@@ -382,7 +382,7 @@ export function createLitControllers() {
382
382
  controller.signUp = (provider, credentials) => connect().signUp(provider, credentials);
383
383
  controller.signIn = (provider, credentials) => connect().signIn(provider, credentials);
384
384
  controller.signOut = () => connect().signOut();
385
- controller.setPassword = (email, newPassword) => connect().setPassword(email, newPassword);
385
+ controller.setPassword = (email, currentPassword, newPassword) => connect().setPassword(email, currentPassword, newPassword);
386
386
  return controller;
387
387
  }
388
388
 
@@ -455,7 +455,7 @@ export function createInfernoAdapters() {
455
455
  adapter.signUp = (provider, credentials) => connect().signUp(provider, credentials);
456
456
  adapter.signIn = (provider, credentials) => connect().signIn(provider, credentials);
457
457
  adapter.signOut = () => connect().signOut();
458
- adapter.setPassword = (email, newPassword) => connect().setPassword(email, newPassword);
458
+ adapter.setPassword = (email, currentPassword, newPassword) => connect().setPassword(email, currentPassword, newPassword);
459
459
  return adapter;
460
460
  }
461
461
  return { queryAdapter, mutationAdapter, authAdapter };
@@ -505,7 +505,7 @@ export function createSvelteStores() {
505
505
  signUp: (provider, credentials) => connect().signUp(provider, credentials),
506
506
  signIn: (provider, credentials) => connect().signIn(provider, credentials),
507
507
  signOut: () => connect().signOut(),
508
- setPassword: (email, newPassword) => connect().setPassword(email, newPassword),
508
+ setPassword: (email, currentPassword, newPassword) => connect().setPassword(email, currentPassword, newPassword),
509
509
  };
510
510
  }
511
511
 
@@ -1010,8 +1010,8 @@ function createConnection() {
1010
1010
  return result;
1011
1011
  });
1012
1012
  },
1013
- setPassword(email, newPassword) {
1014
- return request("auth.setPassword", { email, newPassword });
1013
+ setPassword(email, currentPassword, newPassword) {
1014
+ return request("auth.setPassword", { email, currentPassword, newPassword });
1015
1015
  },
1016
1016
  sendPasswordResetLink(email) {
1017
1017
  return request("auth.sendPasswordResetLink", { email });
@@ -7053,6 +7053,7 @@ var EMAIL_SIGN_IN_FAILURE_LIMIT = 5;
7053
7053
  var EMAIL_SIGN_IN_THROTTLE_WINDOW_MS = 15 * 60 * 1e3;
7054
7054
  var EMAIL_SIGN_IN_THROTTLE_MAX_ENTRIES = 256;
7055
7055
  var EMAIL_SIGN_IN_THROTTLE_FIELD = "__emailSignInThrottle";
7056
+ var PASSWORD_CHANGE_THROTTLE_FIELD = "__emailPasswordChangeThrottle";
7056
7057
  var PASSWORD_RESET_THROTTLE_FIELD = "__emailPasswordResetThrottle";
7057
7058
  var PASSWORD_RESET_DEFAULT_PATH = "/reset-password";
7058
7059
  var PASSWORD_RESET_DEFAULT_TTL_MS = 60 * 60 * 1e3;
@@ -8827,7 +8828,7 @@ function mailNotConfiguredError() {
8827
8828
  hint: "Set `mail.smtp` in sporades.json, or use ctx.serverAuth.createEmailPasswordResetLink with your own delivery path."
8828
8829
  };
8829
8830
  }
8830
- async function setOwnEmailPassword(database, session, email, newPassword) {
8831
+ async function setOwnEmailPassword(database, session, email, currentPassword, newPassword) {
8831
8832
  let auth;
8832
8833
  try {
8833
8834
  auth = requireAuth({ ...session, kind: "message" }, { linked: true });
@@ -8839,6 +8840,15 @@ async function setOwnEmailPassword(database, session, email, newPassword) {
8839
8840
  if (!credential || credential.userId !== auth.userId) {
8840
8841
  return { ok: false, error: emailNotOwnedError() };
8841
8842
  }
8843
+ const throttle = currentEmailSignInThrottleState(database, cleanEmail, session, PASSWORD_CHANGE_THROTTLE_FIELD);
8844
+ if (throttle.throttled) {
8845
+ return { ok: false, error: invalidCurrentPasswordError() };
8846
+ }
8847
+ if (typeof currentPassword !== "string" || !verifyEmailPassword(currentPassword, credential.passwordSalt, credential.passwordHash)) {
8848
+ recordFailedEmailSignInAttempt(database, cleanEmail, session, PASSWORD_CHANGE_THROTTLE_FIELD);
8849
+ return { ok: false, error: invalidCurrentPasswordError() };
8850
+ }
8851
+ resetEmailSignInAttempts(database, cleanEmail, session, PASSWORD_CHANGE_THROTTLE_FIELD);
8842
8852
  return await setEmailPassword(database, session, cleanEmail, newPassword);
8843
8853
  }
8844
8854
  function emailNotOwnedError() {
@@ -8848,6 +8858,13 @@ function emailNotOwnedError() {
8848
8858
  hint: "Change the password for the signed-in account, or use a password reset link."
8849
8859
  };
8850
8860
  }
8861
+ function invalidCurrentPasswordError() {
8862
+ return {
8863
+ code: "INVALID_CURRENT_PASSWORD",
8864
+ message: "Current password is incorrect.",
8865
+ hint: "Enter the current password for this email credential, or use a password reset link."
8866
+ };
8867
+ }
8851
8868
  async function setEmailPassword(database, _session, email, newPassword) {
8852
8869
  if (!database.authConfig.providers.email.enabled) {
8853
8870
  return { ok: false, error: emailAuthDisabledError() };
@@ -15161,7 +15178,13 @@ function createWebSocketHub(getDatabase, trustedRefresh = null) {
15161
15178
  return;
15162
15179
  }
15163
15180
  if (message.type === "auth.setPassword") {
15164
- const result = await setOwnEmailPassword(database, client.session, message.email ?? "", message.newPassword ?? "");
15181
+ const result = await setOwnEmailPassword(
15182
+ database,
15183
+ client.session,
15184
+ message.email ?? "",
15185
+ message.currentPassword ?? "",
15186
+ message.newPassword ?? ""
15187
+ );
15165
15188
  sendJson(client, {
15166
15189
  id: message.id ?? null,
15167
15190
  type: result.ok ? "auth.setPassword.result" : "error",
@@ -22142,7 +22165,7 @@ jobs:
22142
22165
  }
22143
22166
 
22144
22167
  // src/cli/cli-version.ts
22145
- var CLI_VERSION = "0.7.1";
22168
+ var CLI_VERSION = "0.7.2";
22146
22169
 
22147
22170
  // src/cli/sporades.ts
22148
22171
  var SUPPORTED_TEMPLATES = new Set(CLIENT_TEMPLATES);
@@ -7,6 +7,7 @@ export declare const EMAIL_SIGN_IN_FAILURE_LIMIT = 5;
7
7
  export declare const EMAIL_SIGN_IN_THROTTLE_WINDOW_MS: number;
8
8
  export declare const EMAIL_SIGN_IN_THROTTLE_MAX_ENTRIES = 256;
9
9
  export declare const EMAIL_SIGN_IN_THROTTLE_FIELD = "__emailSignInThrottle";
10
+ export declare const PASSWORD_CHANGE_THROTTLE_FIELD = "__emailPasswordChangeThrottle";
10
11
  export declare const PASSWORD_RESET_THROTTLE_FIELD = "__emailPasswordResetThrottle";
11
12
  export declare const PASSWORD_RESET_DEFAULT_PATH = "/reset-password";
12
13
  export declare const PASSWORD_RESET_DEFAULT_TTL_MS: number;
@@ -135,7 +136,7 @@ export declare function mailNotConfiguredError(): {
135
136
  message: string;
136
137
  hint: string;
137
138
  };
138
- export declare function setOwnEmailPassword(database: LooseRecord, session: LooseRecord, email: string, newPassword: string): Promise<{
139
+ export declare function setOwnEmailPassword(database: LooseRecord, session: LooseRecord, email: string, currentPassword: string, newPassword: string): Promise<{
139
140
  ok: boolean;
140
141
  error: {
141
142
  message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"auth-runtime.d.ts","sourceRoot":"","sources":["../src/auth-runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-runtime.d.ts","sourceRoot":"","sources":["../src/auth-runtime.ts"],"names":[],"mappings":"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"}
@@ -108,6 +108,7 @@ export const EMAIL_SIGN_IN_FAILURE_LIMIT = 5;
108
108
  export const EMAIL_SIGN_IN_THROTTLE_WINDOW_MS = 15 * 60 * 1000;
109
109
  export const EMAIL_SIGN_IN_THROTTLE_MAX_ENTRIES = 256;
110
110
  export const EMAIL_SIGN_IN_THROTTLE_FIELD = "__emailSignInThrottle";
111
+ export const PASSWORD_CHANGE_THROTTLE_FIELD = "__emailPasswordChangeThrottle";
111
112
  export const PASSWORD_RESET_THROTTLE_FIELD = "__emailPasswordResetThrottle";
112
113
  export const PASSWORD_RESET_DEFAULT_PATH = "/reset-password";
113
114
  export const PASSWORD_RESET_DEFAULT_TTL_MS = 60 * 60 * 1000;
@@ -1968,11 +1969,12 @@ export function mailNotConfiguredError() {
1968
1969
  };
1969
1970
  }
1970
1971
  // Browser-facing password change. `setEmailPassword` is the trusted server-only
1971
- // API and deliberately accepts any registered email, so the ownership gate lives
1972
- // here rather than there: a browser may only change the credential its own
1973
- // Session owns. Non-existent and someone-else's emails share one opaque denial,
1974
- // so this cannot be used to discover which addresses have accounts.
1975
- export async function setOwnEmailPassword(database, session, email, newPassword) {
1972
+ // API and deliberately accepts any registered email, so the ownership and
1973
+ // re-authentication gates live here rather than there: a browser may only
1974
+ // change the credential its own Session owns after proving knowledge of its
1975
+ // current password. Non-existent and someone-else's emails share one opaque
1976
+ // denial, so this cannot be used to discover which addresses have accounts.
1977
+ export async function setOwnEmailPassword(database, session, email, currentPassword, newPassword) {
1976
1978
  let auth;
1977
1979
  try {
1978
1980
  auth = requireAuth({ ...session, kind: "message" }, { linked: true });
@@ -1985,6 +1987,15 @@ export async function setOwnEmailPassword(database, session, email, newPassword)
1985
1987
  if (!credential || credential.userId !== auth.userId) {
1986
1988
  return { ok: false, error: emailNotOwnedError() };
1987
1989
  }
1990
+ const throttle = currentEmailSignInThrottleState(database, cleanEmail, session, PASSWORD_CHANGE_THROTTLE_FIELD);
1991
+ if (throttle.throttled) {
1992
+ return { ok: false, error: invalidCurrentPasswordError() };
1993
+ }
1994
+ if (typeof currentPassword !== "string" || !verifyEmailPassword(currentPassword, credential.passwordSalt, credential.passwordHash)) {
1995
+ recordFailedEmailSignInAttempt(database, cleanEmail, session, PASSWORD_CHANGE_THROTTLE_FIELD);
1996
+ return { ok: false, error: invalidCurrentPasswordError() };
1997
+ }
1998
+ resetEmailSignInAttempts(database, cleanEmail, session, PASSWORD_CHANGE_THROTTLE_FIELD);
1988
1999
  return await setEmailPassword(database, session, cleanEmail, newPassword);
1989
2000
  }
1990
2001
  function emailNotOwnedError() {
@@ -1994,6 +2005,13 @@ function emailNotOwnedError() {
1994
2005
  hint: "Change the password for the signed-in account, or use a password reset link.",
1995
2006
  };
1996
2007
  }
2008
+ function invalidCurrentPasswordError() {
2009
+ return {
2010
+ code: "INVALID_CURRENT_PASSWORD",
2011
+ message: "Current password is incorrect.",
2012
+ hint: "Enter the current password for this email credential, or use a password reset link.",
2013
+ };
2014
+ }
1997
2015
  export async function setEmailPassword(database, _session, email, newPassword) {
1998
2016
  if (!database.authConfig.providers.email.enabled) {
1999
2017
  return { ok: false, error: emailAuthDisabledError() };
@@ -2013,8 +2031,8 @@ export async function setEmailPassword(database, _session, email, newPassword) {
2013
2031
  await database.adapter.updateEmailCredentialPassword(cleanEmail, password.hash, password.salt);
2014
2032
  return { ok: true };
2015
2033
  }
2016
- // Sign-in failures and reset requests share this throttle shape but never share a
2017
- // bucket: requesting a reset must not lock the account out of sign-in.
2034
+ // Sign-in, password-change, and reset requests share this throttle shape but
2035
+ // never share a bucket: one auth action must not lock out another.
2018
2036
  function createEmailSignInThrottleState(database, scope = EMAIL_SIGN_IN_THROTTLE_FIELD) {
2019
2037
  const existing = database[scope];
2020
2038
  if (existing instanceof Map) {