@arbidocs/client 0.4.30 → 0.4.32

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/index.cjs CHANGED
@@ -1032,9 +1032,21 @@ async function changePassword(params, deps) {
1032
1032
  params.newPassword,
1033
1033
  deps.deploymentDomain
1034
1034
  );
1035
+ const stored = await getSession();
1036
+ if (!stored) throw new Error("Sign in to change your password");
1037
+ const current = deriveEncryptionKeypairFromSigning({
1038
+ publicKey: stored.signingPrivateKey.slice(32, 64),
1039
+ secretKey: stored.signingPrivateKey
1040
+ });
1041
+ const next = deriveEncryptionKeypairFromSigning({
1042
+ publicKey: credentials.newSigningPrivateKey.slice(32, 64),
1043
+ secretKey: credentials.newSigningPrivateKey
1044
+ });
1045
+ const mailKeys = await rewrapMailKeys(deps.fetchClient, current.secretKey, next.publicKey);
1035
1046
  const response = await deps.fetchClient.POST("/v1/user/change_password", {
1036
1047
  body: {
1037
1048
  ...credentials.request,
1049
+ ...mailKeys,
1038
1050
  rewrapped_workspace_keys: params.rewrappedWorkspaceKeys ?? {}
1039
1051
  }
1040
1052
  });
@@ -1086,6 +1098,43 @@ async function reEncryptDirectMessages(fetchClient, userExtId, oldSecretKey, new
1086
1098
  if (!patched.data) throw new Error("Failed to save re-encrypted messages");
1087
1099
  return updates.length;
1088
1100
  }
1101
+ async function rewrapMailKeys(fetchClient, oldPrivateKey, newPublicKey) {
1102
+ const rewrappedMailKeys = {};
1103
+ let mailCursor = 0;
1104
+ while (mailCursor !== null) {
1105
+ const result = await fetchClient.GET(
1106
+ "/v1/mail/native/keys",
1107
+ {
1108
+ params: { query: { cursor: mailCursor } }
1109
+ }
1110
+ );
1111
+ if (!result.data) throw new Error("Could not load mailbox keys for password change");
1112
+ for (const [id, wrapped] of Object.entries(result.data.keys)) {
1113
+ const key = sealedBoxDecrypt(wrapped, oldPrivateKey);
1114
+ try {
1115
+ rewrappedMailKeys[id] = sealedBoxEncrypt(key, newPublicKey);
1116
+ } finally {
1117
+ key.fill(0);
1118
+ }
1119
+ }
1120
+ mailCursor = result.data.next_cursor ?? null;
1121
+ }
1122
+ const connected = await fetchClient.GET("/v1/mail/native/rotation-credentials");
1123
+ if (!connected.data) throw new Error("Could not load mail connections for password change");
1124
+ const rewrappedMailCredentials = {};
1125
+ for (const [id, wrapped] of Object.entries(connected.data)) {
1126
+ const plain = sealedBoxDecrypt(wrapped, oldPrivateKey);
1127
+ try {
1128
+ rewrappedMailCredentials[id] = sealedBoxEncrypt(plain, newPublicKey);
1129
+ } finally {
1130
+ plain.fill(0);
1131
+ }
1132
+ }
1133
+ return {
1134
+ rewrapped_mail_keys: rewrappedMailKeys,
1135
+ rewrapped_mail_credentials: rewrappedMailCredentials
1136
+ };
1137
+ }
1089
1138
  async function changePasswordWithRekey(params, deps) {
1090
1139
  const session = await getSession();
1091
1140
  if (!session) throw new Error("No active session found");
@@ -1134,8 +1183,13 @@ async function changePasswordWithRekey(params, deps) {
1134
1183
  } catch {
1135
1184
  }
1136
1185
  }
1186
+ const mailKeys = await rewrapMailKeys(deps.fetchClient, current.secretKey, next.publicKey);
1137
1187
  const response = await deps.fetchClient.POST("/v1/user/change_password", {
1138
- body: { ...request, rewrapped_workspace_keys: rewrapped }
1188
+ body: {
1189
+ ...request,
1190
+ rewrapped_workspace_keys: rewrapped,
1191
+ ...mailKeys
1192
+ }
1139
1193
  });
1140
1194
  if (response.error || !response.data)
1141
1195
  throw response.error ?? new Error("Failed to change password");