Add extra SMB/NFS settings to edit modal
SMB: force user, force group, guest ok fields + dropdowns for owner/group NFS: no_root_squash and all_squash toggles exposed in edit modal Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
596365b805
commit
0d09882268
2 files changed
+116
-31
No files matched your search
+60
-15
@@ -112,23 +112,31 @@ async function openEditModal(type, share) {
|
||||
const users = ur ? await ur.json() : [];
|
||||
const groups = gr ? await gr.json() : [];
|
||||
|
||||
const ownerOptions = ['root', ...users.map(u => u.name)]
|
||||
.map(n => `<option value="${esc(n)}">`).join('');
|
||||
const groupOptions = groups.map(g => `<option value="${esc(g.name)}">`).join('');
|
||||
const ownerNames = ['root', ...users.map(u => u.name)];
|
||||
const ownerOptions = ownerNames
|
||||
.map(n => `<option value="${esc(n)}"${share.owner === n ? ' selected' : ''}>${esc(n)}</option>`)
|
||||
.join('');
|
||||
const groupOptions = groups
|
||||
.map(g => `<option value="${esc(g.name)}"${share.group === g.name ? ' selected' : ''}>${esc(g.name)}</option>`)
|
||||
.join('');
|
||||
|
||||
const permSection = `
|
||||
<datalist id="ownerList">${ownerOptions}</datalist>
|
||||
<datalist id="groupList">${groupOptions}</datalist>
|
||||
<hr style="border-color:var(--border); margin:1.25rem 0 1rem">
|
||||
<div class="fw-semibold mb-3" style="font-size:.9rem; color:var(--text)">Folder Permissions</div>
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-5">
|
||||
<label class="form-label" style="color:var(--muted); font-size:.85rem">Owner</label>
|
||||
<input type="text" id="editOwner" class="form-control" value="${esc(share.owner || '')}" placeholder="root" list="ownerList">
|
||||
<select id="editOwner" class="form-control">
|
||||
<option value="">— no change —</option>
|
||||
${ownerOptions}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<label class="form-label" style="color:var(--muted); font-size:.85rem">Group</label>
|
||||
<input type="text" id="editGroup" class="form-control" value="${esc(share.group || '')}" placeholder="root" list="groupList">
|
||||
<select id="editGroup" class="form-control">
|
||||
<option value="">— no change —</option>
|
||||
${groupOptions}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<label class="form-label" style="color:var(--muted); font-size:.85rem">Mode</label>
|
||||
@@ -155,10 +163,34 @@ async function openEditModal(type, share) {
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" style="color:var(--muted); font-size:.85rem">Valid Users
|
||||
<span style="font-weight:400"> — use <code>@groupname</code> for a whole group</span>
|
||||
<span style="font-weight:400"> — space or comma separated, use <code>@groupname</code> for a group</span>
|
||||
</label>
|
||||
<input type="text" id="editUsers" class="form-control" value="${esc(share.valid_users || '')}">
|
||||
</div>
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" style="color:var(--muted); font-size:.85rem">Force User
|
||||
<span style="font-weight:400"> — all writes appear as this user</span>
|
||||
</label>
|
||||
<select id="editForceUser" class="form-control">
|
||||
<option value="">— none —</option>
|
||||
${ownerOptions}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" style="color:var(--muted); font-size:.85rem">Force Group
|
||||
<span style="font-weight:400"> — all writes use this group</span>
|
||||
</label>
|
||||
<select id="editForceGroup" class="form-control">
|
||||
<option value="">— none —</option>
|
||||
${groupOptions}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check ms-1 mb-3">
|
||||
<input type="checkbox" id="editGuestOk" class="form-check-input" ${share.guest_ok ? 'checked' : ''}>
|
||||
<label class="form-check-label" for="editGuestOk" style="color:var(--muted)">Guest OK — allow access without a password</label>
|
||||
</div>
|
||||
${permSection}`;
|
||||
} else {
|
||||
const isRo = /\(ro[,)]/.test(share.clients);
|
||||
@@ -172,10 +204,18 @@ async function openEditModal(type, share) {
|
||||
<label class="form-label" style="color:var(--muted); font-size:.85rem">Clients</label>
|
||||
<input type="text" id="editClients" class="form-control" value="${esc(cleanClients)}">
|
||||
</div>
|
||||
<div class="form-check ms-1 mt-2 mb-2">
|
||||
<div class="form-check ms-1 mt-2 mb-1">
|
||||
<input type="checkbox" id="editReadOnly" class="form-check-input" ${isRo ? 'checked' : ''}>
|
||||
<label class="form-check-label" for="editReadOnly" style="color:var(--muted)">Read only</label>
|
||||
</div>
|
||||
<div class="form-check ms-1 mb-1">
|
||||
<input type="checkbox" id="editNoRootSquash" class="form-check-input" ${share.no_root_squash ? 'checked' : ''}>
|
||||
<label class="form-check-label" for="editNoRootSquash" style="color:var(--muted)">no_root_squash — root on client keeps root access on server</label>
|
||||
</div>
|
||||
<div class="form-check ms-1 mb-3">
|
||||
<input type="checkbox" id="editAllSquash" class="form-check-input" ${share.all_squash ? 'checked' : ''}>
|
||||
<label class="form-check-label" for="editAllSquash" style="color:var(--muted)">all_squash — map all clients to anonymous user (anonuid)</label>
|
||||
</div>
|
||||
${permSection}`;
|
||||
}
|
||||
|
||||
@@ -188,19 +228,24 @@ async function submitEdit() {
|
||||
|
||||
let res;
|
||||
if (ctx.type === 'smb') {
|
||||
const name = document.getElementById('editName').value.trim();
|
||||
const path = document.getElementById('editPath').value.trim();
|
||||
const name = document.getElementById('editName').value.trim();
|
||||
const path = document.getElementById('editPath').value.trim();
|
||||
const validUsers = document.getElementById('editUsers').value.trim();
|
||||
const forceUser = document.getElementById('editForceUser').value;
|
||||
const forceGroup = document.getElementById('editForceGroup').value;
|
||||
const guestOk = document.getElementById('editGuestOk').checked;
|
||||
res = await apiFetch(`/api/share/smb/${encodeURIComponent(ctx.original.name)}`, {
|
||||
method: 'PATCH', headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({name, path, validUsers}),
|
||||
body: JSON.stringify({name, path, validUsers, forceUser, forceGroup, guestOk}),
|
||||
});
|
||||
} else {
|
||||
const clients = document.getElementById('editClients').value.trim();
|
||||
const readOnly = document.getElementById('editReadOnly').checked;
|
||||
const clients = document.getElementById('editClients').value.trim();
|
||||
const readOnly = document.getElementById('editReadOnly').checked;
|
||||
const noRootSquash = document.getElementById('editNoRootSquash').checked;
|
||||
const allSquash = document.getElementById('editAllSquash').checked;
|
||||
res = await apiFetch('/api/share/nfs', {
|
||||
method: 'PATCH', headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({path: ctx.original.path, clients, readOnly}),
|
||||
body: JSON.stringify({path: ctx.original.path, clients, readOnly, noRootSquash, allSquash}),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user