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:
marcandClaude Sonnet 4.6 committed 2026-06-20 00:55:40 +02:00
1 parent 596365b805
commit 0d09882268
2 files changed
+116 -31

No files matched your search

+56 -16
View File
@@ -124,7 +124,9 @@ def parse_smb():
if m:
if current is not None and current['name'].lower() not in _SMB_SKIP:
shares.append(current)
current = {'name': m.group(1), 'path': '', 'valid_users': '', 'enabled': True}
current = {'name': m.group(1), 'path': '', 'valid_users': '',
'enabled': True, 'guest_ok': False,
'force_user': '', 'force_group': ''}
elif current is not None and '=' in line:
key, _, val = line.partition('=')
key = key.strip().lower().replace(' ', '_')
@@ -135,6 +137,12 @@ def parse_smb():
current['valid_users'] = val
elif key == 'available':
current['enabled'] = val.lower() not in ('no', 'false', '0')
elif key == 'guest_ok':
current['guest_ok'] = val.lower() in ('yes', 'true', '1')
elif key == 'force_user':
current['force_user'] = val
elif key == 'force_group':
current['force_group'] = val
if current is not None and current['name'].lower() not in _SMB_SKIP:
shares.append(current)
@@ -202,10 +210,19 @@ def _write_exports(entries):
def get_nfs_shares():
return [
{'path': e['path'], 'clients': e['rest'], 'enabled': e['enabled']}
for e in _parse_exports() if e['kind'] == 'export'
]
shares = []
for e in _parse_exports():
if e['kind'] != 'export':
continue
rest = e['rest']
shares.append({
'path': e['path'],
'clients': rest,
'enabled': e['enabled'],
'no_root_squash': 'no_root_squash' in rest,
'all_squash': 'all_squash' in rest,
})
return shares
def add_nfs_share(path, clients, ro=False):
@@ -298,29 +315,44 @@ def delete_smb(name):
@require_auth
def edit_smb(name):
data = request.json or {}
new_name = data.get('name', name).strip()
path = data.get('path', '')
new_name = data.get('name', name).strip()
path = data.get('path', '')
valid_users = data.get('validUsers', '')
force_user = data.get('forceUser', '').strip()
force_group = data.get('forceGroup', '').strip()
guest_ok = data.get('guestOk', False)
if not VALID_NAME.match(new_name):
return jsonify({'error': 'invalid share name'}), 400
if force_user and not VALID_NAME.match(force_user):
return jsonify({'error': 'invalid force user'}), 400
if force_group and not VALID_NAME.match(force_group):
return jsonify({'error': 'invalid force group'}), 400
try:
clean_users = _validate_users(valid_users)
safe_path = validate_path(path)
except ValueError as e:
return jsonify({'error': str(e)}), 400
lines = [
f'[{new_name}]\n',
f' path = {safe_path}\n',
f' valid users = {clean_users}\n',
' writable = yes\n',
' browseable = yes\n',
]
if force_user:
lines.append(f' force user = {force_user}\n')
if force_group:
lines.append(f' force group = {force_group}\n')
if guest_ok:
lines.append(' guest ok = yes\n')
sections = _parse_smb_conf()
for s in sections:
if s['name'] == name:
s['name'] = new_name
s['lines'] = [
f'[{new_name}]\n',
f' path = {safe_path}\n',
f' valid users = {clean_users}\n',
' writable = yes\n',
' browseable = yes\n',
]
s['lines'] = lines
break
else:
return jsonify({'error': f'share {name!r} not found'}), 404
@@ -402,8 +434,16 @@ def edit_nfs():
if not VALID_NFS_CLIENT.match(clients):
return jsonify({'error': 'invalid client spec'}), 400
options = 'ro' if ro else 'rw'
new_rest = f'{clients}({options},sync,no_subtree_check)'
no_root_squash = data.get('noRootSquash', False)
all_squash = data.get('allSquash', False)
options = ','.join(filter(None, [
'ro' if ro else 'rw',
'sync',
'no_subtree_check',
'no_root_squash' if no_root_squash else None,
'all_squash' if all_squash else None,
]))
new_rest = f'{clients}({options})'
entries = _parse_exports()
for e in entries: