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
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user