05/29 Fixed a shared item isn't auto updated when it's modified by owner
This commit is contained in:
+12
-1
@@ -145,6 +145,7 @@ def update_item(item_id):
|
||||
# Re-encrypt accepted shared copies if the owner provided updated ciphertext.
|
||||
# Each entry: { share_id, enc_data, iv, enc_name?, iv_name? }
|
||||
from app.models.shared_item import SharedItem
|
||||
updated_share_ids = []
|
||||
for upd in (data.get('shared_updates') or []):
|
||||
share = SharedItem.query.filter_by(
|
||||
id=upd.get('share_id'),
|
||||
@@ -157,6 +158,7 @@ def update_item(item_id):
|
||||
if upd.get('enc_name') is not None:
|
||||
share.enc_name = upd['enc_name']
|
||||
share.iv_name = upd.get('iv_name')
|
||||
updated_share_ids.append(share.id)
|
||||
|
||||
try:
|
||||
db.session.flush()
|
||||
@@ -168,6 +170,15 @@ def update_item(item_id):
|
||||
detail=f'Updated {item.item_type} item (id={item.id})',
|
||||
ip_address=client_ip(),
|
||||
)
|
||||
if updated_share_ids:
|
||||
AuditLog.log(
|
||||
user_id=g.current_user_id,
|
||||
action='shared_item.update',
|
||||
resource_type='shared_item',
|
||||
resource_id=item.id,
|
||||
detail=f'Re-encrypted {len(updated_share_ids)} shared copy(ies) for vault item (id={item.id}), share_ids={updated_share_ids}',
|
||||
ip_address=client_ip(),
|
||||
)
|
||||
db.session.commit()
|
||||
except Exception:
|
||||
db.session.rollback()
|
||||
@@ -320,4 +331,4 @@ def audit_bulk_export():
|
||||
ip_address=client_ip(),
|
||||
)
|
||||
db.session.commit()
|
||||
return jsonify({'logged': len(valid_ids)}), 200
|
||||
return jsonify({'logged': len(valid_ids)}), 200
|
||||
+20
-8
@@ -2212,8 +2212,20 @@ const Vault = (() => {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Always fetch fresh share data from the server so the grantee sees
|
||||
// the owner's latest version, not the ciphertext that was baked into
|
||||
// the button's data-* attributes when the tab was last rendered.
|
||||
const shareId = parseInt(btn.dataset.viewShare);
|
||||
const inboxRes = await apiFetch("/api/sharing/inbox");
|
||||
if (!inboxRes) return;
|
||||
const inbox = await inboxRes.json();
|
||||
const freshShare = inbox.find((s) => s.id === shareId);
|
||||
if (!freshShare || !freshShare.owner_public_key) {
|
||||
showToast("Share not found or owner key unavailable.", "error");
|
||||
return;
|
||||
}
|
||||
const ownerPubKey = await SharingCrypto.importPublicKey(
|
||||
btn.dataset.ownerKey,
|
||||
freshShare.owner_public_key,
|
||||
);
|
||||
const sharedKey = await SharingCrypto.deriveSharedKey(
|
||||
SharingSession.getKey(),
|
||||
@@ -2221,21 +2233,21 @@ const Vault = (() => {
|
||||
);
|
||||
const plain = await SharingCrypto.decryptShare(
|
||||
sharedKey,
|
||||
btn.dataset.enc,
|
||||
btn.dataset.iv,
|
||||
freshShare.enc_data,
|
||||
freshShare.iv,
|
||||
);
|
||||
// Decrypt the item name if an encrypted version is available.
|
||||
// Falls back to the non-sensitive label for legacy shares.
|
||||
let displayName = btn.dataset.name;
|
||||
if (btn.dataset.encName && btn.dataset.ivName) {
|
||||
let displayName = freshShare.item_name;
|
||||
if (freshShare.enc_name && freshShare.iv_name) {
|
||||
const decrypted = await SharingCrypto.decryptName(
|
||||
sharedKey,
|
||||
btn.dataset.encName,
|
||||
btn.dataset.ivName,
|
||||
freshShare.enc_name,
|
||||
freshShare.iv_name,
|
||||
);
|
||||
if (decrypted) displayName = decrypted;
|
||||
}
|
||||
showSharedItemDetails(displayName, btn.dataset.type, plain);
|
||||
showSharedItemDetails(displayName, freshShare.item_type, plain);
|
||||
} catch (err) {
|
||||
showToast("Could not decrypt: " + err.message, "error");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user