@arbidocs/client 0.4.30 → 0.4.31

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.js CHANGED
@@ -1025,9 +1025,21 @@ async function changePassword(params, deps) {
1025
1025
  params.newPassword,
1026
1026
  deps.deploymentDomain
1027
1027
  );
1028
+ const stored = await getSession();
1029
+ if (!stored) throw new Error("Sign in to change your password");
1030
+ const current = deriveEncryptionKeypairFromSigning({
1031
+ publicKey: stored.signingPrivateKey.slice(32, 64),
1032
+ secretKey: stored.signingPrivateKey
1033
+ });
1034
+ const next = deriveEncryptionKeypairFromSigning({
1035
+ publicKey: credentials.newSigningPrivateKey.slice(32, 64),
1036
+ secretKey: credentials.newSigningPrivateKey
1037
+ });
1038
+ const mailKeys = await rewrapMailKeys(deps.fetchClient, current.secretKey, next.publicKey);
1028
1039
  const response = await deps.fetchClient.POST("/v1/user/change_password", {
1029
1040
  body: {
1030
1041
  ...credentials.request,
1042
+ ...mailKeys,
1031
1043
  rewrapped_workspace_keys: params.rewrappedWorkspaceKeys ?? {}
1032
1044
  }
1033
1045
  });
@@ -1079,6 +1091,43 @@ async function reEncryptDirectMessages(fetchClient, userExtId, oldSecretKey, new
1079
1091
  if (!patched.data) throw new Error("Failed to save re-encrypted messages");
1080
1092
  return updates.length;
1081
1093
  }
1094
+ async function rewrapMailKeys(fetchClient, oldPrivateKey, newPublicKey) {
1095
+ const rewrappedMailKeys = {};
1096
+ let mailCursor = 0;
1097
+ while (mailCursor !== null) {
1098
+ const result = await fetchClient.GET(
1099
+ "/v1/mail/native/keys",
1100
+ {
1101
+ params: { query: { cursor: mailCursor } }
1102
+ }
1103
+ );
1104
+ if (!result.data) throw new Error("Could not load mailbox keys for password change");
1105
+ for (const [id, wrapped] of Object.entries(result.data.keys)) {
1106
+ const key = sealedBoxDecrypt(wrapped, oldPrivateKey);
1107
+ try {
1108
+ rewrappedMailKeys[id] = sealedBoxEncrypt(key, newPublicKey);
1109
+ } finally {
1110
+ key.fill(0);
1111
+ }
1112
+ }
1113
+ mailCursor = result.data.next_cursor ?? null;
1114
+ }
1115
+ const connected = await fetchClient.GET("/v1/mail/native/rotation-credentials");
1116
+ if (!connected.data) throw new Error("Could not load mail connections for password change");
1117
+ const rewrappedMailCredentials = {};
1118
+ for (const [id, wrapped] of Object.entries(connected.data)) {
1119
+ const plain = sealedBoxDecrypt(wrapped, oldPrivateKey);
1120
+ try {
1121
+ rewrappedMailCredentials[id] = sealedBoxEncrypt(plain, newPublicKey);
1122
+ } finally {
1123
+ plain.fill(0);
1124
+ }
1125
+ }
1126
+ return {
1127
+ rewrapped_mail_keys: rewrappedMailKeys,
1128
+ rewrapped_mail_credentials: rewrappedMailCredentials
1129
+ };
1130
+ }
1082
1131
  async function changePasswordWithRekey(params, deps) {
1083
1132
  const session = await getSession();
1084
1133
  if (!session) throw new Error("No active session found");
@@ -1127,8 +1176,13 @@ async function changePasswordWithRekey(params, deps) {
1127
1176
  } catch {
1128
1177
  }
1129
1178
  }
1179
+ const mailKeys = await rewrapMailKeys(deps.fetchClient, current.secretKey, next.publicKey);
1130
1180
  const response = await deps.fetchClient.POST("/v1/user/change_password", {
1131
- body: { ...request, rewrapped_workspace_keys: rewrapped }
1181
+ body: {
1182
+ ...request,
1183
+ rewrapped_workspace_keys: rewrapped,
1184
+ ...mailKeys
1185
+ }
1132
1186
  });
1133
1187
  if (response.error || !response.data)
1134
1188
  throw response.error ?? new Error("Failed to change password");