feat(browse): edit .zddc.zip bundle members in-place (elevated admin)
The .zddc/markdown editors marked every zip member read-only. Add util.isEditableZipMember (member of a .zddc.zip + session elevated) and let those through canSave in both editors — so an elevated admin can open a bundle's policy .zddc (or any member) and save it, which PUTs to the member URL where the new server-side ServeZipWrite handles the in-place rewrite + in-zip history. The server (bundle gate + active-admin) is the real authority; this just drives the editor UX (mount editable, label "config bundle" instead of "read-only (zip)"). Content-archive members stay read-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fcb8fc6cf1
commit
7b59d82cdb
3 changed files with 23 additions and 4 deletions
|
|
@ -315,9 +315,12 @@
|
|||
}
|
||||
|
||||
var isZipMemberNode = util.isZipMemberNode;
|
||||
var isEditableZipMember = util.isEditableZipMember;
|
||||
|
||||
function canSave(node) {
|
||||
if (isZipMemberNode(node)) return false;
|
||||
// A .zddc.zip bundle member is saveable iff editable (elevated admin) —
|
||||
// the server's ServeZipWrite is the gate; other zip members read-only.
|
||||
if (isZipMemberNode(node)) return isEditableZipMember(node);
|
||||
// Server-computed authority gate. The listing's verbs string
|
||||
// tells us whether a PUT to this entry would be allowed —
|
||||
// false here means the file API would 403, so we mount in
|
||||
|
|
@ -486,7 +489,7 @@
|
|||
var sourceEl = document.createElement('span');
|
||||
sourceEl.className = 'md-shell__source';
|
||||
if (isZipMemberNode(node)) {
|
||||
sourceEl.textContent = 'read-only (zip)';
|
||||
sourceEl.textContent = isEditableZipMember(node) ? 'config bundle' : 'read-only (zip)';
|
||||
} else if (node.handle) {
|
||||
sourceEl.textContent = 'local';
|
||||
} else if (node.url) {
|
||||
|
|
|
|||
|
|
@ -53,9 +53,13 @@
|
|||
}
|
||||
|
||||
var isZipMemberNode = util.isZipMemberNode;
|
||||
var isEditableZipMember = util.isEditableZipMember;
|
||||
|
||||
function canSave(node) {
|
||||
if (isZipMemberNode(node)) return false;
|
||||
// A .zddc.zip bundle member is saveable iff editable (elevated admin);
|
||||
// the server's ServeZipWrite is the real gate. Other zip members are
|
||||
// read-only.
|
||||
if (isZipMemberNode(node)) return isEditableZipMember(node);
|
||||
// Virtual .zddc placeholders are designed to be saved — a PUT
|
||||
// materializes the file from the synthetic body and the next
|
||||
// listing serves a real entry. Every other virtual node (per-
|
||||
|
|
@ -444,7 +448,7 @@
|
|||
|
||||
var sourceEl = document.createElement('span');
|
||||
sourceEl.className = 'md-shell__source';
|
||||
if (isZipMemberNode(node)) sourceEl.textContent = 'read-only (zip)';
|
||||
if (isZipMemberNode(node)) sourceEl.textContent = isEditableZipMember(node) ? 'config bundle' : 'read-only (zip)';
|
||||
else if (node.handle) sourceEl.textContent = 'local';
|
||||
else if (node.url) sourceEl.textContent = 'server';
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,17 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
// isEditableZipMember reports whether node is a member of the .zddc.zip
|
||||
// config bundle AND the session is elevated — the one case where the server
|
||||
// accepts a write into a zip (ServeZipWrite, admin-gated). Every other zip
|
||||
// member (content archives, or the bundle when not elevated) stays
|
||||
// read-only. The server is the real gate; this just drives editor UX.
|
||||
function isEditableZipMember(node) {
|
||||
if (!node || !node.url || window.app.state.source !== 'server') return false;
|
||||
if (!/\.zddc\.zip\//i.test(node.url)) return false;
|
||||
return !!(window.zddc && window.zddc.elevation && window.zddc.elevation.isElevated());
|
||||
}
|
||||
|
||||
// Thrown by saveFile when the server rejects a write with 412
|
||||
// Precondition Failed — the file changed under us since we loaded it.
|
||||
// Callers branch on `.status === 412` to open the conflict UI instead
|
||||
|
|
@ -193,6 +204,7 @@
|
|||
fetchAccessEmails: fetchAccessEmails,
|
||||
fmtSize: fmtSize,
|
||||
isZipMemberNode: isZipMemberNode,
|
||||
isEditableZipMember: isEditableZipMember,
|
||||
saveFile: saveFile,
|
||||
saveCopy: saveCopy,
|
||||
ConflictError: ConflictError
|
||||
|
|
|
|||
Loading…
Reference in a new issue