@arbidocs/client 0.4.4 → 0.4.6
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 +109 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -1
- package/dist/index.d.ts +41 -1
- package/dist/index.js +108 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1006,6 +1006,13 @@ async function performLogin(request, signingPrivateKey, deps) {
|
|
|
1006
1006
|
accessToken: data.access_token,
|
|
1007
1007
|
userExtId: data.user.external_id ?? void 0,
|
|
1008
1008
|
parentExtId: data.user.parent_ext_id ?? null,
|
|
1009
|
+
profile: {
|
|
1010
|
+
givenName: data.user.given_name,
|
|
1011
|
+
familyName: data.user.family_name ?? null,
|
|
1012
|
+
picture: data.user.picture ?? null,
|
|
1013
|
+
email: data.user.email ?? request.email,
|
|
1014
|
+
isSso: data.user.is_sso === true
|
|
1015
|
+
},
|
|
1009
1016
|
signingPrivateKey,
|
|
1010
1017
|
serverSessionKey
|
|
1011
1018
|
};
|
|
@@ -1039,6 +1046,106 @@ async function changePassword(params, deps) {
|
|
|
1039
1046
|
await updateSigningPrivateKey(credentials.newSigningPrivateKey);
|
|
1040
1047
|
return { newSigningPrivateKey: credentials.newSigningPrivateKey };
|
|
1041
1048
|
}
|
|
1049
|
+
function passwordChangeErrorMessage(err) {
|
|
1050
|
+
if (err instanceof Error) return err.message;
|
|
1051
|
+
if (err && typeof err === "object") {
|
|
1052
|
+
const obj = err;
|
|
1053
|
+
if (typeof obj.detail === "string") return obj.detail;
|
|
1054
|
+
if (typeof obj.message === "string") return obj.message;
|
|
1055
|
+
if (Array.isArray(obj.detail)) {
|
|
1056
|
+
const msgs = obj.detail.map(
|
|
1057
|
+
(d) => d && typeof d.msg === "string" ? d.msg : null
|
|
1058
|
+
).filter((m) => m !== null);
|
|
1059
|
+
if (msgs.length) return msgs.join("; ");
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
return "Failed to change password";
|
|
1063
|
+
}
|
|
1064
|
+
async function reEncryptDirectMessages(fetchClient, userExtId, oldSecretKey, newSecretKey) {
|
|
1065
|
+
const { data } = await fetchClient.GET("/v1/notifications/");
|
|
1066
|
+
const messages = (data ?? []).filter((n) => n.type === "user_message" && n.content);
|
|
1067
|
+
const oldSecrets = {};
|
|
1068
|
+
const newSecrets = {};
|
|
1069
|
+
const updates = [];
|
|
1070
|
+
for (const n of messages) {
|
|
1071
|
+
try {
|
|
1072
|
+
const other = n.sender.external_id === userExtId ? n.recipient : n.sender;
|
|
1073
|
+
const id = other.external_id;
|
|
1074
|
+
oldSecrets[id] ??= await computeSharedSecret(other.encryption_public_key, oldSecretKey);
|
|
1075
|
+
newSecrets[id] ??= await computeSharedSecret(other.encryption_public_key, newSecretKey);
|
|
1076
|
+
const plain = await decryptMessageWithSharedSecret(n.content, oldSecrets[id]);
|
|
1077
|
+
updates.push({
|
|
1078
|
+
external_id: n.external_id,
|
|
1079
|
+
content: await encryptMessageWithSharedSecret(plain, newSecrets[id])
|
|
1080
|
+
});
|
|
1081
|
+
} catch {
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
if (updates.length === 0) return 0;
|
|
1085
|
+
const patched = await fetchClient.PATCH("/v1/notifications/", { body: { updates } });
|
|
1086
|
+
if (!patched.data) throw new Error("Failed to save re-encrypted messages");
|
|
1087
|
+
return updates.length;
|
|
1088
|
+
}
|
|
1089
|
+
async function changePasswordWithRekey(params, deps) {
|
|
1090
|
+
const session = await getSession();
|
|
1091
|
+
if (!session) throw new Error("No active session found");
|
|
1092
|
+
const { request, newSigningPrivateKey } = params.currentPassword ? await generatePasswordChangeCredentials(
|
|
1093
|
+
params.email,
|
|
1094
|
+
params.currentPassword,
|
|
1095
|
+
params.newPassword,
|
|
1096
|
+
deps.deploymentDomain
|
|
1097
|
+
) : await generateRecoveryPasswordChangeCredentials(
|
|
1098
|
+
params.email,
|
|
1099
|
+
session.signingPrivateKey,
|
|
1100
|
+
params.newPassword,
|
|
1101
|
+
deps.deploymentDomain
|
|
1102
|
+
);
|
|
1103
|
+
const current = deriveEncryptionKeypairFromSigning({
|
|
1104
|
+
publicKey: session.signingPrivateKey.slice(32, 64),
|
|
1105
|
+
secretKey: session.signingPrivateKey
|
|
1106
|
+
});
|
|
1107
|
+
const next = deriveEncryptionKeypairFromSigning({
|
|
1108
|
+
publicKey: newSigningPrivateKey.slice(32, 64),
|
|
1109
|
+
secretKey: newSigningPrivateKey
|
|
1110
|
+
});
|
|
1111
|
+
const listed = await deps.fetchClient.GET("/v1/user/workspaces");
|
|
1112
|
+
if (!listed.data) throw new Error("Could not list your workspaces");
|
|
1113
|
+
const rewrapped = {};
|
|
1114
|
+
for (const ws of listed.data.filter((w) => w.is_member)) {
|
|
1115
|
+
if (!ws.wrapped_key) continue;
|
|
1116
|
+
try {
|
|
1117
|
+
rewrapped[ws.external_id] = sealedBoxEncrypt(
|
|
1118
|
+
sealedBoxDecrypt(ws.wrapped_key, current.secretKey),
|
|
1119
|
+
next.publicKey
|
|
1120
|
+
);
|
|
1121
|
+
} catch {
|
|
1122
|
+
throw new Error(`Failed to re-wrap workspace key for ${ws.name || ws.external_id}`);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
let messagesReEncrypted = 0;
|
|
1126
|
+
if (params.userExtId) {
|
|
1127
|
+
try {
|
|
1128
|
+
messagesReEncrypted = await reEncryptDirectMessages(
|
|
1129
|
+
deps.fetchClient,
|
|
1130
|
+
params.userExtId,
|
|
1131
|
+
current.secretKey,
|
|
1132
|
+
next.secretKey
|
|
1133
|
+
);
|
|
1134
|
+
} catch {
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
const response = await deps.fetchClient.POST("/v1/user/change_password", {
|
|
1138
|
+
body: { ...request, rewrapped_workspace_keys: rewrapped }
|
|
1139
|
+
});
|
|
1140
|
+
if (response.error || !response.data)
|
|
1141
|
+
throw response.error ?? new Error("Failed to change password");
|
|
1142
|
+
await updateSigningPrivateKey(newSigningPrivateKey);
|
|
1143
|
+
return {
|
|
1144
|
+
newSigningPrivateKey,
|
|
1145
|
+
workspacesUpdated: response.data.workspaces_updated ?? 0,
|
|
1146
|
+
messagesReEncrypted
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1042
1149
|
|
|
1043
1150
|
// src/client.ts
|
|
1044
1151
|
var API_PREFIX = "/v1";
|
|
@@ -1289,6 +1396,7 @@ exports.base64Encode = base64Encode;
|
|
|
1289
1396
|
exports.base64ToBytes = base64ToBytes;
|
|
1290
1397
|
exports.buildWebSocketUrl = buildWebSocketUrl;
|
|
1291
1398
|
exports.bytesToBase64 = bytesToBase64;
|
|
1399
|
+
exports.changePasswordWithRekey = changePasswordWithRekey;
|
|
1292
1400
|
exports.clearAllData = clearAllData;
|
|
1293
1401
|
exports.clearSession = clearSession;
|
|
1294
1402
|
exports.computeSharedSecret = computeSharedSecret;
|
|
@@ -1323,6 +1431,7 @@ exports.initSodium = initSodium;
|
|
|
1323
1431
|
exports.initializeDatabase = initializeDatabase;
|
|
1324
1432
|
exports.isMessageType = isMessageType;
|
|
1325
1433
|
exports.parseServerMessage = parseServerMessage;
|
|
1434
|
+
exports.passwordChangeErrorMessage = passwordChangeErrorMessage;
|
|
1326
1435
|
exports.prewarmKeyPairs = prewarmKeyPairs;
|
|
1327
1436
|
exports.saveSession = saveSession;
|
|
1328
1437
|
exports.sealKeyForSession = sealKeyForSession;
|