Fix production deployment issues

This commit is contained in:
2026-03-28 13:57:57 +03:00
Unverified
parent 30ab4d9190
commit 3caadde6ff
14 changed files with 170 additions and 105 deletions
+16 -3
View File
@@ -173,8 +173,21 @@ export async function sendWithFiles(
const transportPublicKey = ub64(transportPublicKeyB64);
// Transport-encrypt message (client-side transport only; server will envelope-encrypt)
const { client_public_key_b64, nonce_b64, ciphertext_b64 } = encryptWithTransportKey(plaintext || "", transportPublicKeyB64);
// One ephemeral keypair for message + all files (must match messaging service decrypt_transport_blob).
const ephemeralKeypair = tweetnacl.box.keyPair();
const messagePlaintextBytes = new TextEncoder().encode(plaintext || "");
const messageNonce = tweetnacl.randomBytes(tweetnacl.box.nonceLength);
const messageCiphertext = tweetnacl.box(
messagePlaintextBytes,
messageNonce,
transportPublicKey,
ephemeralKeypair.secretKey
);
const client_public_key_b64 = btoa(
String.fromCharCode.apply(null, Array.from(ephemeralKeypair.publicKey) as number[])
);
const nonce_b64 = btoa(String.fromCharCode.apply(null, Array.from(messageNonce) as number[]));
const ciphertext_b64 = btoa(String.fromCharCode.apply(null, Array.from(messageCiphertext) as number[]));
const senderPublicKeyB64 = keys.publicKey ? btoa(String.fromCharCode.apply(null, Array.from(keys.publicKey) as number[])) : "";
@@ -197,7 +210,7 @@ export async function sendWithFiles(
new Uint8Array(fileData),
transportNonce,
transportPublicKey,
keys.privateKey
ephemeralKeypair.secretKey
);
const transportEncryptedWithNonce = new Uint8Array(transportNonce.length + transportEncrypted.length);
transportEncryptedWithNonce.set(transportNonce);
+16
View File
@@ -168,6 +168,22 @@ export async function ensureKeysOnLogin(password: string, token: string): Promis
return pair;
}
/**
* When the client already has a keypair (e.g. from localStorage) but the server has no public key row,
* upload the public key. Covers failed uploads during login, DB resets, and legacy accounts.
*/
export async function syncPublicKeyToServerIfMissing(token: string): Promise<void> {
const keys = getCurrentKeys();
if (!keys?.publicKey?.length || !keys?.privateKey?.length) {
return;
}
const serverPk = await fetchPublicKey(token);
if (serverPk) {
return;
}
await uploadPublicKey(keys.publicKey, token);
}
export function restoreKeys() {
currentPublicKey = ub64(localStorage.getItem("publicKey")!);
currentPrivateKey = ub64(localStorage.getItem("privateKey")!);
+5
View File
@@ -94,6 +94,11 @@ export function LoginForm({ onSwitchMode }: LoginFormProps) {
await api.user.auth.ensureKeysOnLogin(password, data.token);
} catch (e) {
console.error("Key setup failed:", e);
try {
await api.user.auth.syncPublicKeyToServerIfMissing(data.token);
} catch (e2) {
console.error("Public key re-sync failed:", e2);
}
}
// Ensure WebSocket is connected and authenticated
+5
View File
@@ -122,6 +122,11 @@ export function RegisterForm({ onSwitchMode }: RegisterFormProps) {
await api.user.auth.ensureKeysOnLogin(password, data.token);
} catch (e) {
console.error("Key setup failed:", e);
try {
await api.user.auth.syncPublicKeyToServerIfMissing(data.token);
} catch (e2) {
console.error("Public key re-sync failed:", e2);
}
}
navigate("/chat");
+5
View File
@@ -79,6 +79,11 @@ export const useUserStore = create<UserStore>((set) => ({
if (fullResponse.ok) {
const user: User = await fullResponse.json();
api.user.auth.restoreKeys();
try {
await api.user.auth.syncPublicKeyToServerIfMissing(token);
} catch (e) {
console.error("Public key sync to server failed:", e);
}
if (user.suspended) {
set({