mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-22 21:50:13 +00:00
Add official Bitwarden resource sync notifications
This commit is contained in:
+74
-1
@@ -11,7 +11,13 @@ import {
|
||||
PasswordHistory,
|
||||
} from '../types';
|
||||
import { StorageService } from '../services/storage';
|
||||
import { notifyUserVaultSync } from '../durable/notifications-hub';
|
||||
import {
|
||||
notifyUserCipherCreate,
|
||||
notifyUserCipherDelete,
|
||||
notifyUserCipherUpdate,
|
||||
notifyUserCiphersSync,
|
||||
notifyUserVaultSync,
|
||||
} from '../durable/notifications-hub';
|
||||
import { jsonResponse, errorResponse } from '../utils/response';
|
||||
import { generateUUID } from '../utils/uuid';
|
||||
import { deleteAllAttachmentsForCipher, deleteAllAttachmentsForCiphers } from './attachments';
|
||||
@@ -51,6 +57,60 @@ function notifyVaultSyncForRequest(
|
||||
notifyUserVaultSync(env, userId, revisionDate, readActingDeviceIdentifier(request));
|
||||
}
|
||||
|
||||
function notifyCipherCreateForRequest(
|
||||
request: Request,
|
||||
env: Env,
|
||||
cipher: Cipher,
|
||||
revisionDate: string
|
||||
): void {
|
||||
notifyUserCipherCreate(env, {
|
||||
userId: cipher.userId,
|
||||
cipherId: cipher.id,
|
||||
revisionDate,
|
||||
organizationId: normalizeOptionalId((cipher as any).organizationId ?? null),
|
||||
collectionIds: Array.isArray((cipher as any).collectionIds)
|
||||
? (cipher as any).collectionIds.map((id: unknown) => String(id || '').trim()).filter(Boolean)
|
||||
: null,
|
||||
contextId: readActingDeviceIdentifier(request),
|
||||
});
|
||||
}
|
||||
|
||||
function notifyCipherUpdateForRequest(
|
||||
request: Request,
|
||||
env: Env,
|
||||
cipher: Cipher,
|
||||
revisionDate: string
|
||||
): void {
|
||||
notifyUserCipherUpdate(env, {
|
||||
userId: cipher.userId,
|
||||
cipherId: cipher.id,
|
||||
revisionDate,
|
||||
organizationId: normalizeOptionalId((cipher as any).organizationId ?? null),
|
||||
collectionIds: Array.isArray((cipher as any).collectionIds)
|
||||
? (cipher as any).collectionIds.map((id: unknown) => String(id || '').trim()).filter(Boolean)
|
||||
: null,
|
||||
contextId: readActingDeviceIdentifier(request),
|
||||
});
|
||||
}
|
||||
|
||||
function notifyCipherDeleteForRequest(
|
||||
request: Request,
|
||||
env: Env,
|
||||
cipher: Cipher,
|
||||
revisionDate: string
|
||||
): void {
|
||||
notifyUserCipherDelete(env, {
|
||||
userId: cipher.userId,
|
||||
cipherId: cipher.id,
|
||||
revisionDate,
|
||||
organizationId: normalizeOptionalId((cipher as any).organizationId ?? null),
|
||||
collectionIds: Array.isArray((cipher as any).collectionIds)
|
||||
? (cipher as any).collectionIds.map((id: unknown) => String(id || '').trim()).filter(Boolean)
|
||||
: null,
|
||||
contextId: readActingDeviceIdentifier(request),
|
||||
});
|
||||
}
|
||||
|
||||
function getAliasedProp(source: any, aliases: string[]): { present: boolean; value: any } {
|
||||
if (!source || typeof source !== 'object') return { present: false, value: undefined };
|
||||
for (const key of aliases) {
|
||||
@@ -815,6 +875,7 @@ export async function handleCreateCipher(request: Request, env: Env, userId: str
|
||||
await storage.saveCipher(cipher);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyCipherCreateForRequest(request, env, cipher, revisionDate);
|
||||
const responseOptions = cipherResponseOptionsForRequest(request);
|
||||
|
||||
return jsonResponse(
|
||||
@@ -925,6 +986,7 @@ export async function handleUpdateCipher(request: Request, env: Env, userId: str
|
||||
await storage.saveCipher(cipher);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyCipherUpdateForRequest(request, env, cipher, revisionDate);
|
||||
const attachments = await storage.getAttachmentsByCipher(cipher.id);
|
||||
const responseOptions = cipherResponseOptionsForRequest(request);
|
||||
|
||||
@@ -949,6 +1011,7 @@ export async function handleDeleteCipher(request: Request, env: Env, userId: str
|
||||
await storage.saveCipher(cipher);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyCipherDeleteForRequest(request, env, cipher, revisionDate);
|
||||
await writeCipherAudit(storage, request, userId, 'cipher.delete.soft', {
|
||||
id: cipher.id,
|
||||
type: cipher.type,
|
||||
@@ -978,6 +1041,7 @@ export async function handleDeleteCipherCompat(request: Request, env: Env, userI
|
||||
await storage.deleteCipher(id, userId);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyCipherDeleteForRequest(request, env, cipher, revisionDate);
|
||||
await writeCipherAudit(storage, request, userId, 'cipher.delete.permanent', {
|
||||
id,
|
||||
type: cipher.type,
|
||||
@@ -1005,6 +1069,7 @@ export async function handlePermanentDeleteCipher(request: Request, env: Env, us
|
||||
await storage.deleteCipher(id, userId);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyCipherDeleteForRequest(request, env, cipher, revisionDate);
|
||||
await writeCipherAudit(storage, request, userId, 'cipher.delete.permanent', {
|
||||
id,
|
||||
type: cipher.type,
|
||||
@@ -1029,6 +1094,7 @@ export async function handleRestoreCipher(request: Request, env: Env, userId: st
|
||||
await storage.saveCipher(cipher);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyCipherUpdateForRequest(request, env, cipher, revisionDate);
|
||||
|
||||
return jsonResponse(
|
||||
cipherToResponse(cipher, [], cipherResponseOptionsForRequest(request))
|
||||
@@ -1068,6 +1134,7 @@ export async function handlePartialUpdateCipher(request: Request, env: Env, user
|
||||
await storage.saveCipher(cipher);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyCipherUpdateForRequest(request, env, cipher, revisionDate);
|
||||
|
||||
return jsonResponse(
|
||||
cipherToResponse(cipher, [], cipherResponseOptionsForRequest(request))
|
||||
@@ -1144,6 +1211,7 @@ export async function handleArchiveCipher(request: Request, env: Env, userId: st
|
||||
await storage.saveCipher(cipher);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyCipherUpdateForRequest(request, env, cipher, revisionDate);
|
||||
|
||||
const attachments = await storage.getAttachmentsByCipher(cipher.id);
|
||||
return jsonResponse(
|
||||
@@ -1192,6 +1260,7 @@ export async function handleBulkArchiveCiphers(request: Request, env: Env, userI
|
||||
const revisionDate = await storage.bulkArchiveCiphers(ids, userId);
|
||||
if (revisionDate) {
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyUserCiphersSync(env, userId, revisionDate, readActingDeviceIdentifier(request));
|
||||
}
|
||||
|
||||
return buildCipherListResponse(request, storage, userId, ids);
|
||||
@@ -1216,6 +1285,7 @@ export async function handleBulkUnarchiveCiphers(request: Request, env: Env, use
|
||||
const revisionDate = await storage.bulkUnarchiveCiphers(ids, userId);
|
||||
if (revisionDate) {
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyUserCiphersSync(env, userId, revisionDate, readActingDeviceIdentifier(request));
|
||||
}
|
||||
|
||||
return buildCipherListResponse(request, storage, userId, ids);
|
||||
@@ -1239,6 +1309,7 @@ export async function handleBulkDeleteCiphers(request: Request, env: Env, userId
|
||||
const revisionDate = await storage.bulkSoftDeleteCiphers(body.ids, userId);
|
||||
if (revisionDate) {
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyUserCiphersSync(env, userId, revisionDate, readActingDeviceIdentifier(request));
|
||||
await writeCipherAudit(storage, request, userId, 'cipher.delete.soft.bulk', {
|
||||
count: body.ids.length,
|
||||
});
|
||||
@@ -1265,6 +1336,7 @@ export async function handleBulkRestoreCiphers(request: Request, env: Env, userI
|
||||
const revisionDate = await storage.bulkRestoreCiphers(body.ids, userId);
|
||||
if (revisionDate) {
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyUserCiphersSync(env, userId, revisionDate, readActingDeviceIdentifier(request));
|
||||
}
|
||||
|
||||
return new Response(null, { status: 204 });
|
||||
@@ -1301,6 +1373,7 @@ export async function handleBulkPermanentDeleteCiphers(request: Request, env: En
|
||||
const revisionDate = await storage.bulkDeleteCiphers(ownedIds, userId);
|
||||
if (revisionDate) {
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyUserCiphersSync(env, userId, revisionDate, readActingDeviceIdentifier(request));
|
||||
await writeCipherAudit(storage, request, userId, 'cipher.delete.permanent.bulk', {
|
||||
count: ownedIds.length,
|
||||
requestedCount: ids.length,
|
||||
|
||||
+24
-1
@@ -1,5 +1,10 @@
|
||||
import { Env, Folder, FolderResponse } from '../types';
|
||||
import { notifyUserVaultSync } from '../durable/notifications-hub';
|
||||
import {
|
||||
notifyUserFolderCreate,
|
||||
notifyUserFolderDelete,
|
||||
notifyUserFolderUpdate,
|
||||
notifyUserVaultSync,
|
||||
} from '../durable/notifications-hub';
|
||||
import { StorageService } from '../services/storage';
|
||||
import { jsonResponse, errorResponse } from '../utils/response';
|
||||
import { readActingDeviceIdentifier } from '../utils/device';
|
||||
@@ -111,6 +116,12 @@ export async function handleCreateFolder(request: Request, env: Env, userId: str
|
||||
await storage.saveFolder(folder);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyUserFolderCreate(env, {
|
||||
userId,
|
||||
folderId: folder.id,
|
||||
revisionDate,
|
||||
contextId: readActingDeviceIdentifier(request),
|
||||
});
|
||||
|
||||
return jsonResponse(folderToResponse(folder), 200);
|
||||
}
|
||||
@@ -139,6 +150,12 @@ export async function handleUpdateFolder(request: Request, env: Env, userId: str
|
||||
await storage.saveFolder(folder);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyUserFolderUpdate(env, {
|
||||
userId,
|
||||
folderId: folder.id,
|
||||
revisionDate,
|
||||
contextId: readActingDeviceIdentifier(request),
|
||||
});
|
||||
|
||||
return jsonResponse(folderToResponse(folder));
|
||||
}
|
||||
@@ -156,6 +173,12 @@ export async function handleDeleteFolder(request: Request, env: Env, userId: str
|
||||
await storage.deleteFolder(id, userId);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifyUserFolderDelete(env, {
|
||||
userId,
|
||||
folderId: id,
|
||||
revisionDate,
|
||||
contextId: readActingDeviceIdentifier(request),
|
||||
});
|
||||
await writeFolderAudit(storage, request, userId, 'folder.delete', {
|
||||
id,
|
||||
});
|
||||
|
||||
@@ -16,6 +16,9 @@ import {
|
||||
formatSize,
|
||||
getAliasedProp,
|
||||
normalizeEmails,
|
||||
notifySendCreateForRequest,
|
||||
notifySendDeleteForRequest,
|
||||
notifySendUpdateForRequest,
|
||||
notifyVaultSyncForRequest,
|
||||
parseDate,
|
||||
parseFileLength,
|
||||
@@ -249,6 +252,7 @@ export async function handleCreateSend(request: Request, env: Env, userId: strin
|
||||
await storage.saveSend(send);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifySendCreateForRequest(request, env, send.id, userId, revisionDate);
|
||||
|
||||
return jsonResponse(sendToResponse(send));
|
||||
}
|
||||
@@ -372,6 +376,7 @@ export async function handleCreateFileSendV2(request: Request, env: Env, userId:
|
||||
await storage.saveSend(send);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifySendCreateForRequest(request, env, send.id, userId, revisionDate);
|
||||
const jwtSecret = getSafeJwtSecret(env);
|
||||
if (!jwtSecret) {
|
||||
return errorResponse('Server configuration error', 500);
|
||||
@@ -619,6 +624,7 @@ export async function handleUpdateSend(request: Request, env: Env, userId: strin
|
||||
await storage.saveSend(send);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifySendUpdateForRequest(request, env, send.id, userId, revisionDate);
|
||||
|
||||
return jsonResponse(sendToResponse(send));
|
||||
}
|
||||
@@ -641,6 +647,7 @@ export async function handleDeleteSend(request: Request, env: Env, userId: strin
|
||||
await storage.deleteSend(sendId, userId);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifySendDeleteForRequest(request, env, sendId, userId, revisionDate);
|
||||
await writeSendAudit(storage, request, userId, 'send.delete', {
|
||||
id: sendId,
|
||||
type: send.type,
|
||||
@@ -697,6 +704,7 @@ export async function handleRemoveSendPassword(request: Request, env: Env, userI
|
||||
await storage.saveSend(send);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifySendUpdateForRequest(request, env, send.id, userId, revisionDate);
|
||||
await writeSendAudit(storage, request, userId, 'send.password.remove', {
|
||||
id: send.id,
|
||||
type: send.type,
|
||||
@@ -718,6 +726,7 @@ export async function handleRemoveSendAuth(request: Request, env: Env, userId: s
|
||||
await storage.saveSend(send);
|
||||
const revisionDate = await storage.updateRevisionDate(userId);
|
||||
notifyVaultSyncForRequest(request, env, userId, revisionDate);
|
||||
notifySendUpdateForRequest(request, env, send.id, userId, revisionDate);
|
||||
await writeSendAudit(storage, request, userId, 'send.auth.remove', {
|
||||
id: send.id,
|
||||
type: send.type,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { Env, Send, SendAuthType, SendResponse, SendType, DEFAULT_DEV_SECRET } from '../types';
|
||||
import { notifyUserVaultSync } from '../durable/notifications-hub';
|
||||
import {
|
||||
notifyUserSendCreate,
|
||||
notifyUserSendDelete,
|
||||
notifyUserSendUpdate,
|
||||
notifyUserVaultSync,
|
||||
} from '../durable/notifications-hub';
|
||||
import { StorageService } from '../services/storage';
|
||||
import { jsonResponse, errorResponse } from '../utils/response';
|
||||
import { readActingDeviceIdentifier } from '../utils/device';
|
||||
@@ -18,6 +23,51 @@ export function notifyVaultSyncForRequest(
|
||||
notifyUserVaultSync(env, userId, revisionDate, readActingDeviceIdentifier(request));
|
||||
}
|
||||
|
||||
export function notifySendCreateForRequest(
|
||||
request: Request,
|
||||
env: Env,
|
||||
sendId: string,
|
||||
userId: string,
|
||||
revisionDate: string
|
||||
): void {
|
||||
notifyUserSendCreate(env, {
|
||||
userId,
|
||||
sendId,
|
||||
revisionDate,
|
||||
contextId: readActingDeviceIdentifier(request),
|
||||
});
|
||||
}
|
||||
|
||||
export function notifySendUpdateForRequest(
|
||||
request: Request,
|
||||
env: Env,
|
||||
sendId: string,
|
||||
userId: string,
|
||||
revisionDate: string
|
||||
): void {
|
||||
notifyUserSendUpdate(env, {
|
||||
userId,
|
||||
sendId,
|
||||
revisionDate,
|
||||
contextId: readActingDeviceIdentifier(request),
|
||||
});
|
||||
}
|
||||
|
||||
export function notifySendDeleteForRequest(
|
||||
request: Request,
|
||||
env: Env,
|
||||
sendId: string,
|
||||
userId: string,
|
||||
revisionDate: string
|
||||
): void {
|
||||
notifyUserSendDelete(env, {
|
||||
userId,
|
||||
sendId,
|
||||
revisionDate,
|
||||
contextId: readActingDeviceIdentifier(request),
|
||||
});
|
||||
}
|
||||
|
||||
export function getAliasedProp(source: unknown, aliases: string[]): { present: boolean; value: unknown } {
|
||||
if (!source || typeof source !== 'object') return { present: false, value: undefined };
|
||||
for (const key of aliases) {
|
||||
|
||||
Reference in New Issue
Block a user