Get rid of all those crazy 'auth' arguments. Instead : directly fetch the ldap interface when and where it's actually needed

This commit is contained in:
Alexandre Aubin 2019-05-10 02:11:40 +02:00
parent c15cc788ed
commit f010f49528
8 changed files with 186 additions and 154 deletions

View file

@ -38,12 +38,12 @@ from collections import OrderedDict
from datetime import datetime
from moulinette import msignals, m18n, msettings
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import read_json
from yunohost.service import service_log, service_status, _run_service_command
from yunohost.utils import packages
from yunohost.utils.error import YunohostError
from yunohost.log import is_unit_operation, OperationLogger
logger = getActionLogger('yunohost.app')
@ -437,7 +437,7 @@ def app_map(app=None, raw=False, user=None):
@is_unit_operation()
def app_change_url(operation_logger, auth, app, domain, path):
def app_change_url(operation_logger, app, domain, path):
"""
Modify the URL at which an application is installed.
@ -468,7 +468,7 @@ def app_change_url(operation_logger, auth, app, domain, path):
raise YunohostError("app_change_url_identical_domains", domain=domain, path=path)
# Check the url is available
conflicts = _get_conflicting_apps(auth, domain, path, ignore_app=app)
conflicts = _get_conflicting_apps(domain, path, ignore_app=app)
if conflicts:
apps = []
for path, app_id, app_label in conflicts:
@ -484,7 +484,7 @@ def app_change_url(operation_logger, auth, app, domain, path):
# Retrieve arguments list for change_url script
# TODO: Allow to specify arguments
args_odict = _parse_args_from_manifest(manifest, 'change_url', auth=auth)
args_odict = _parse_args_from_manifest(manifest, 'change_url')
args_list = args_odict.values()
args_list.append(app)
@ -538,7 +538,7 @@ def app_change_url(operation_logger, auth, app, domain, path):
app_setting(app, 'domain', value=domain)
app_setting(app, 'path', value=path)
app_ssowatconf(auth)
app_ssowatconf()
# avoid common mistakes
if _run_service_command("reload", "nginx") == False:
@ -557,7 +557,7 @@ def app_change_url(operation_logger, auth, app, domain, path):
hook_callback('post_app_change_url', args=args_list, env=env_dict)
def app_upgrade(auth, app=[], url=None, file=None):
def app_upgrade(app=[], url=None, file=None):
"""
Upgrade app
@ -633,7 +633,7 @@ def app_upgrade(auth, app=[], url=None, file=None):
# Retrieve arguments list for upgrade script
# TODO: Allow to specify arguments
args_odict = _parse_args_from_manifest(manifest, 'upgrade', auth=auth)
args_odict = _parse_args_from_manifest(manifest, 'upgrade')
args_list = args_odict.values()
args_list.append(app_instance_name)
@ -693,7 +693,7 @@ def app_upgrade(auth, app=[], url=None, file=None):
if not_upgraded_apps:
raise YunohostError('app_not_upgraded', apps=', '.join(not_upgraded_apps))
app_ssowatconf(auth)
app_ssowatconf()
logger.success(m18n.n('upgrade_complete'))
@ -703,7 +703,7 @@ def app_upgrade(auth, app=[], url=None, file=None):
@is_unit_operation()
def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on_failure=False, force=False):
def app_install(operation_logger, app, label=None, args=None, no_remove_on_failure=False, force=False):
"""
Install apps
@ -795,7 +795,7 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on
# Retrieve arguments list for install script
args_dict = {} if not args else \
dict(urlparse.parse_qsl(args, keep_blank_values=True))
args_odict = _parse_args_from_manifest(manifest, 'install', args=args_dict, auth=auth)
args_odict = _parse_args_from_manifest(manifest, 'install', args=args_dict)
args_list = args_odict.values()
args_list.append(app_instance_name)
@ -887,7 +887,7 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on
shutil.rmtree(app_setting_path)
shutil.rmtree(extracted_app_folder)
app_ssowatconf(auth)
app_ssowatconf()
if packages.dpkg_is_broken():
logger.error(m18n.n("this_action_broke_dpkg"))
@ -914,7 +914,7 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on
os.system('chown -R root: %s' % app_setting_path)
os.system('chown -R admin: %s/scripts' % app_setting_path)
app_ssowatconf(auth)
app_ssowatconf()
logger.success(m18n.n('installation_complete'))
@ -922,7 +922,7 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on
@is_unit_operation()
def app_remove(operation_logger, auth, app):
def app_remove(operation_logger, app):
"""
Remove app
@ -974,13 +974,13 @@ def app_remove(operation_logger, auth, app):
shutil.rmtree(app_setting_path)
shutil.rmtree('/tmp/yunohost_remove')
hook_remove(app)
app_ssowatconf(auth)
app_ssowatconf()
if packages.dpkg_is_broken():
raise YunohostError("this_action_broke_dpkg")
def app_addaccess(auth, apps, users=[]):
def app_addaccess(apps, users=[]):
"""
Grant access right to users (everyone by default)
@ -995,7 +995,7 @@ def app_addaccess(auth, apps, users=[]):
result = {}
if not users:
users = user_list(auth)['users'].keys()
users = user_list()['users'].keys()
elif not isinstance(users, list):
users = [users, ]
if not isinstance(apps, list):
@ -1025,7 +1025,7 @@ def app_addaccess(auth, apps, users=[]):
for allowed_user in users:
if allowed_user not in allowed_users:
try:
user_info(auth, allowed_user)
user_info(allowed_user)
except YunohostError:
logger.warning(m18n.n('user_unknown', user=allowed_user))
continue
@ -1041,12 +1041,12 @@ def app_addaccess(auth, apps, users=[]):
result[app] = allowed_users
app_ssowatconf(auth)
app_ssowatconf()
return {'allowed_users': result}
def app_removeaccess(auth, apps, users=[]):
def app_removeaccess(apps, users=[]):
"""
Revoke access right to users (everyone by default)
@ -1088,7 +1088,7 @@ def app_removeaccess(auth, apps, users=[]):
if allowed_user not in users:
allowed_users.add(allowed_user)
else:
for allowed_user in user_list(auth)['users'].keys():
for allowed_user in user_list()['users'].keys():
if allowed_user not in users:
allowed_users.add(allowed_user)
@ -1102,12 +1102,12 @@ def app_removeaccess(auth, apps, users=[]):
operation_logger.success()
app_ssowatconf(auth)
app_ssowatconf()
return {'allowed_users': result}
def app_clearaccess(auth, apps):
def app_clearaccess(apps):
"""
Reset access rights for the app
@ -1140,7 +1140,7 @@ def app_clearaccess(auth, apps):
operation_logger.success()
app_ssowatconf(auth)
app_ssowatconf()
def app_debug(app):
@ -1167,7 +1167,7 @@ def app_debug(app):
@is_unit_operation()
def app_makedefault(operation_logger, auth, app, domain=None):
def app_makedefault(operation_logger, app, domain=None):
"""
Redirect domain root to an app
@ -1185,7 +1185,7 @@ def app_makedefault(operation_logger, auth, app, domain=None):
if domain is None:
domain = app_domain
operation_logger.related_to.append(('domain', domain))
elif domain not in domain_list(auth)['domains']:
elif domain not in domain_list()['domains']:
raise YunohostError('domain_unknown')
operation_logger.start()
@ -1264,7 +1264,7 @@ def app_checkport(port):
raise YunohostError('port_unavailable', port=int(port))
def app_register_url(auth, app, domain, path):
def app_register_url(app, domain, path):
"""
Book/register a web path for a given app
@ -1290,7 +1290,7 @@ def app_register_url(auth, app, domain, path):
raise YunohostError('app_already_installed_cant_change_url')
# Check the url is available
conflicts = _get_conflicting_apps(auth, domain, path)
conflicts = _get_conflicting_apps(domain, path)
if conflicts:
apps = []
for path, app_id, app_label in conflicts:
@ -1307,7 +1307,7 @@ def app_register_url(auth, app, domain, path):
app_setting(app, 'path', value=path)
def app_checkurl(auth, url, app=None):
def app_checkurl(url, app=None):
"""
Check availability of a web path
@ -1337,7 +1337,7 @@ def app_checkurl(auth, url, app=None):
apps_map = app_map(raw=True)
if domain not in domain_list(auth)['domains']:
if domain not in domain_list()['domains']:
raise YunohostError('domain_unknown')
if domain in apps_map:
@ -1394,7 +1394,7 @@ def app_initdb(user, password=None, db=None, sql=None):
logger.success(m18n.n('mysql_db_initialized'))
def app_ssowatconf(auth):
def app_ssowatconf():
"""
Regenerate SSOwat configuration file
@ -1404,7 +1404,7 @@ def app_ssowatconf(auth):
from yunohost.user import user_list
main_domain = _get_maindomain()
domains = domain_list(auth)['domains']
domains = domain_list()['domains']
skipped_urls = []
skipped_regex = []
@ -1481,7 +1481,7 @@ def app_ssowatconf(auth):
'redirected_urls': redirected_urls,
'redirected_regex': redirected_regex,
'users': {username: app_map(user=username)
for username in user_list(auth)['users'].keys()},
for username in user_list()['users'].keys()},
}
with open('/etc/ssowat/conf.json', 'w+') as f:
@ -1490,14 +1490,14 @@ def app_ssowatconf(auth):
logger.success(m18n.n('ssowat_conf_generated'))
def app_change_label(auth, app, new_label):
def app_change_label(app, new_label):
installed = _is_installed(app)
if not installed:
raise YunohostError('app_not_installed', app=app)
app_setting(app, "label", value=new_label)
app_ssowatconf(auth)
app_ssowatconf()
# actions todo list:
@ -2143,7 +2143,7 @@ def _check_manifest_requirements(manifest, app_instance_name):
spec=spec, app=app_instance_name)
def _parse_args_from_manifest(manifest, action, args={}, auth=None):
def _parse_args_from_manifest(manifest, action, args={}):
"""Parse arguments needed for an action from the manifest
Retrieve specified arguments for the action from the manifest, and parse
@ -2162,10 +2162,10 @@ def _parse_args_from_manifest(manifest, action, args={}, auth=None):
return OrderedDict()
action_args = manifest['arguments'][action]
return _parse_action_args_in_yunohost_format(args, action_args, auth)
return _parse_action_args_in_yunohost_format(args, action_args)
def _parse_args_for_action(action, args={}, auth=None):
def _parse_args_for_action(action, args={}):
"""Parse arguments needed for an action from the actions list
Retrieve specified arguments for the action from the manifest, and parse
@ -2186,10 +2186,10 @@ def _parse_args_for_action(action, args={}, auth=None):
action_args = action['arguments']
return _parse_action_args_in_yunohost_format(args, action_args, auth)
return _parse_action_args_in_yunohost_format(args, action_args)
def _parse_action_args_in_yunohost_format(args, action_args, auth=None):
def _parse_action_args_in_yunohost_format(args, action_args):
"""Parse arguments store in either manifest.json or actions.json
"""
from yunohost.domain import (domain_list, _get_maindomain,
@ -2242,12 +2242,12 @@ def _parse_action_args_in_yunohost_format(args, action_args, auth=None):
arg_default = _get_maindomain()
ask_string += ' (default: {0})'.format(arg_default)
msignals.display(m18n.n('domains_available'))
for domain in domain_list(auth)['domains']:
for domain in domain_list()['domains']:
msignals.display("- {}".format(domain))
elif arg_type == 'user':
msignals.display(m18n.n('users_available'))
for user in user_list(auth)['users'].keys():
for user in user_list()['users'].keys():
msignals.display("- {}".format(user))
elif arg_type == 'password':
@ -2283,11 +2283,11 @@ def _parse_action_args_in_yunohost_format(args, action_args, auth=None):
# Validate argument type
if arg_type == 'domain':
if arg_value not in domain_list(auth)['domains']:
if arg_value not in domain_list()['domains']:
raise YunohostError('app_argument_invalid', name=arg_name, error=m18n.n('domain_unknown'))
elif arg_type == 'user':
try:
user_info(auth, arg_value)
user_info(arg_value)
except YunohostError as e:
raise YunohostError('app_argument_invalid', name=arg_name, error=e)
elif arg_type == 'app':
@ -2328,7 +2328,7 @@ def _parse_action_args_in_yunohost_format(args, action_args, auth=None):
domain, path = _normalize_domain_path(domain, path)
# Check the url is available
conflicts = _get_conflicting_apps(auth, domain, path)
conflicts = _get_conflicting_apps(domain, path)
if conflicts:
apps = []
for path, app_id, app_label in conflicts:

View file

@ -2090,7 +2090,7 @@ def backup_create(name=None, description=None, methods=[],
}
def backup_restore(auth, name, system=[], apps=[], force=False):
def backup_restore(name, system=[], apps=[], force=False):
"""
Restore from a local backup archive

View file

@ -86,7 +86,7 @@ DNS_RESOLVERS = [
#
def certificate_status(auth, domain_list, full=False):
def certificate_status(domain_list, full=False):
"""
Print the status of certificate for given domains (all by default)
@ -99,10 +99,10 @@ def certificate_status(auth, domain_list, full=False):
# If no domains given, consider all yunohost domains
if domain_list == []:
domain_list = yunohost.domain.domain_list(auth)['domains']
domain_list = yunohost.domain.domain_list()['domains']
# Else, validate that yunohost knows the domains given
else:
yunohost_domains_list = yunohost.domain.domain_list(auth)['domains']
yunohost_domains_list = yunohost.domain.domain_list()['domains']
for domain in domain_list:
# Is it in Yunohost domain list?
if domain not in yunohost_domains_list:
@ -126,7 +126,7 @@ def certificate_status(auth, domain_list, full=False):
return {"certificates": certificates}
def certificate_install(auth, domain_list, force=False, no_checks=False, self_signed=False, staging=False):
def certificate_install(domain_list, force=False, no_checks=False, self_signed=False, staging=False):
"""
Install a Let's Encrypt certificate for given domains (all by default)
@ -142,7 +142,7 @@ def certificate_install(auth, domain_list, force=False, no_checks=False, self_si
_certificate_install_selfsigned(domain_list, force)
else:
_certificate_install_letsencrypt(
auth, domain_list, force, no_checks, staging)
domain_list, force, no_checks, staging)
def _certificate_install_selfsigned(domain_list, force=False):
@ -237,7 +237,7 @@ def _certificate_install_selfsigned(domain_list, force=False):
operation_logger.error(msg)
def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=False, staging=False):
def _certificate_install_letsencrypt(domain_list, force=False, no_checks=False, staging=False):
import yunohost.domain
if not os.path.exists(ACCOUNT_KEY_FILE):
@ -246,7 +246,7 @@ def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=F
# If no domains given, consider all yunohost domains with self-signed
# certificates
if domain_list == []:
for domain in yunohost.domain.domain_list(auth)['domains']:
for domain in yunohost.domain.domain_list()['domains']:
status = _get_status(domain)
if status["CA_type"]["code"] != "self-signed":
@ -257,7 +257,7 @@ def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=F
# Else, validate that yunohost knows the domains given
else:
for domain in domain_list:
yunohost_domains_list = yunohost.domain.domain_list(auth)['domains']
yunohost_domains_list = yunohost.domain.domain_list()['domains']
if domain not in yunohost_domains_list:
raise YunohostError('certmanager_domain_unknown', domain=domain)
@ -285,7 +285,7 @@ def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=F
operation_logger.start()
_configure_for_acme_challenge(auth, domain)
_configure_for_acme_challenge(domain)
_fetch_and_enable_new_certificate(domain, staging, no_checks=no_checks)
_install_cron(no_checks=no_checks)
@ -300,7 +300,7 @@ def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=F
operation_logger.error(msg)
def certificate_renew(auth, domain_list, force=False, no_checks=False, email=False, staging=False):
def certificate_renew(domain_list, force=False, no_checks=False, email=False, staging=False):
"""
Renew Let's Encrypt certificate for given domains (all by default)
@ -317,7 +317,7 @@ def certificate_renew(auth, domain_list, force=False, no_checks=False, email=Fal
# If no domains given, consider all yunohost domains with Let's Encrypt
# certificates
if domain_list == []:
for domain in yunohost.domain.domain_list(auth)['domains']:
for domain in yunohost.domain.domain_list()['domains']:
# Does it have a Let's Encrypt cert?
status = _get_status(domain)
@ -344,7 +344,7 @@ def certificate_renew(auth, domain_list, force=False, no_checks=False, email=Fal
for domain in domain_list:
# Is it in Yunohost dmomain list?
if domain not in yunohost.domain.domain_list(auth)['domains']:
if domain not in yunohost.domain.domain_list()['domains']:
raise YunohostError('certmanager_domain_unknown', domain=domain)
status = _get_status(domain)
@ -468,7 +468,7 @@ Subject: %s
smtp.quit()
def _configure_for_acme_challenge(auth, domain):
def _configure_for_acme_challenge(domain):
nginx_conf_folder = "/etc/nginx/conf.d/%s.d" % domain
nginx_conf_file = "%s/000-acmechallenge.conf" % nginx_conf_folder
@ -511,7 +511,7 @@ location ^~ '/.well-known/acme-challenge/'
# any clean function already implemented in yunohost to do this though)
_run_service_command("reload", "nginx")
app_ssowatconf(auth)
app_ssowatconf()
def _check_acme_challenge_configuration(domain):

View file

@ -42,7 +42,7 @@ from yunohost.hook import hook_callback
logger = getActionLogger('yunohost.domain')
def domain_list(auth):
def domain_list():
"""
List domains
@ -52,10 +52,12 @@ def domain_list(auth):
limit -- Maximum number of domain fetched
"""
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
result = ldap.search('ou=domains,dc=yunohost,dc=org', 'virtualdomain=*', ['virtualdomain'])
result_list = []
result = auth.search('ou=domains,dc=yunohost,dc=org', 'virtualdomain=*', ['virtualdomain'])
for domain in result:
result_list.append(domain['virtualdomain'][0])
@ -63,7 +65,7 @@ def domain_list(auth):
@is_unit_operation()
def domain_add(operation_logger, auth, domain, dyndns=False):
def domain_add(operation_logger, domain, dyndns=False):
"""
Create a custom domain
@ -74,9 +76,12 @@ def domain_add(operation_logger, auth, domain, dyndns=False):
"""
from yunohost.hook import hook_callback
from yunohost.app import app_ssowatconf
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
try:
auth.validate_uniqueness({'virtualdomain': domain})
ldap.validate_uniqueness({'virtualdomain': domain})
except MoulinetteError:
raise YunohostError('domain_exists')
@ -107,18 +112,18 @@ def domain_add(operation_logger, auth, domain, dyndns=False):
'virtualdomain': domain,
}
if not auth.add('virtualdomain=%s,ou=domains' % domain, attr_dict):
if not ldap.add('virtualdomain=%s,ou=domains' % domain, attr_dict):
raise YunohostError('domain_creation_failed')
# Don't regen these conf if we're still in postinstall
if os.path.exists('/etc/yunohost/installed'):
regen_conf(names=['nginx', 'metronome', 'dnsmasq', 'postfix', 'rspamd'])
app_ssowatconf(auth)
app_ssowatconf()
except Exception:
# Force domain removal silently
try:
domain_remove(auth, domain, True)
domain_remove(domain, True)
except:
pass
raise
@ -129,7 +134,7 @@ def domain_add(operation_logger, auth, domain, dyndns=False):
@is_unit_operation()
def domain_remove(operation_logger, auth, domain, force=False):
def domain_remove(operation_logger, domain, force=False):
"""
Delete domains
@ -140,8 +145,9 @@ def domain_remove(operation_logger, auth, domain, force=False):
"""
from yunohost.hook import hook_callback
from yunohost.app import app_ssowatconf
from yunohost.utils.ldap import _get_ldap_interface
if not force and domain not in domain_list(auth)['domains']:
if not force and domain not in domain_list()['domains']:
raise YunohostError('domain_unknown')
# Check domain is not the main domain
@ -160,13 +166,14 @@ def domain_remove(operation_logger, auth, domain, force=False):
raise YunohostError('domain_uninstall_app_first')
operation_logger.start()
if auth.remove('virtualdomain=' + domain + ',ou=domains') or force:
ldap = _get_ldap_interface()
if ldap.remove('virtualdomain=' + domain + ',ou=domains') or force:
os.system('rm -rf /etc/yunohost/certs/%s' % domain)
else:
raise YunohostError('domain_deletion_failed')
regen_conf(names=['nginx', 'metronome', 'dnsmasq', 'postfix'])
app_ssowatconf(auth)
app_ssowatconf()
hook_callback('post_domain_remove', args=[domain])
@ -222,19 +229,19 @@ def domain_dns_conf(domain, ttl=None):
return result
def domain_cert_status(auth, domain_list, full=False):
return yunohost.certificate.certificate_status(auth, domain_list, full)
def domain_cert_status(domain_list, full=False):
return yunohost.certificate.certificate_status(domain_list, full)
def domain_cert_install(auth, domain_list, force=False, no_checks=False, self_signed=False, staging=False):
return yunohost.certificate.certificate_install(auth, domain_list, force, no_checks, self_signed, staging)
def domain_cert_install(domain_list, force=False, no_checks=False, self_signed=False, staging=False):
return yunohost.certificate.certificate_install(domain_list, force, no_checks, self_signed, staging)
def domain_cert_renew(auth, domain_list, force=False, no_checks=False, email=False, staging=False):
return yunohost.certificate.certificate_renew(auth, domain_list, force, no_checks, email, staging)
def domain_cert_renew(domain_list, force=False, no_checks=False, email=False, staging=False):
return yunohost.certificate.certificate_renew(domain_list, force, no_checks, email, staging)
def _get_conflicting_apps(auth, domain, path, ignore_app=None):
def _get_conflicting_apps(domain, path, ignore_app=None):
"""
Return a list of all conflicting apps with a domain/path (it can be empty)
@ -247,7 +254,7 @@ def _get_conflicting_apps(auth, domain, path, ignore_app=None):
domain, path = _normalize_domain_path(domain, path)
# Abort if domain is unknown
if domain not in domain_list(auth)['domains']:
if domain not in domain_list()['domains']:
raise YunohostError('domain_unknown')
# This import cannot be put on top of file because it would create a
@ -274,7 +281,7 @@ def _get_conflicting_apps(auth, domain, path, ignore_app=None):
return conflicts
def domain_url_available(auth, domain, path):
def domain_url_available(domain, path):
"""
Check availability of a web path
@ -283,7 +290,7 @@ def domain_url_available(auth, domain, path):
path -- The path to check (e.g. /coffee)
"""
return len(_get_conflicting_apps(auth, domain, path)) == 0
return len(_get_conflicting_apps(domain, path)) == 0
def _get_maindomain():

View file

@ -208,7 +208,7 @@ def log_display(path, number=50, share=False):
def is_unit_operation(entities=['app', 'domain', 'service', 'user'],
exclude=['auth', 'password'], operation_key=None):
exclude=['password'], operation_key=None):
"""
Configure quickly a unit operation
@ -222,9 +222,8 @@ def is_unit_operation(entities=['app', 'domain', 'service', 'user'],
(argname, entity_type) instead of just put the entity type.
exclude Remove some arguments from the context. By default, arguments
called 'password' and 'auth' are removed. If an argument is an object, you
need to exclude it or create manually the unit operation without this
decorator.
called 'password' are removed. If an argument is an object, you need to
exclude it or create manually the unit operation without this decorator.
operation_key A key to describe the unit operation log used to create the
filename and search a translation. Please ensure that this key prefixed by

View file

@ -11,7 +11,7 @@ from moulinette.utils.filesystem import read_file, write_to_file, chown, chmod,
SSHD_CONFIG_PATH = "/etc/ssh/sshd_config"
def user_ssh_allow(auth, username):
def user_ssh_allow(username):
"""
Allow YunoHost user connect as ssh.
@ -20,17 +20,19 @@ def user_ssh_allow(auth, username):
"""
# TODO it would be good to support different kind of shells
if not _get_user_for_ssh(auth, username):
if not _get_user_for_ssh(username):
raise YunohostError('user_unknown', user=username)
auth.update('uid=%s,ou=users' % username, {'loginShell': '/bin/bash'})
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
ldap.update('uid=%s,ou=users' % username, {'loginShell': '/bin/bash'})
# Somehow this is needed otherwise the PAM thing doesn't forget about the
# old loginShell value ?
subprocess.call(['nscd', '-i', 'passwd'])
def user_ssh_disallow(auth, username):
def user_ssh_disallow(username):
"""
Disallow YunoHost user connect as ssh.
@ -39,18 +41,20 @@ def user_ssh_disallow(auth, username):
"""
# TODO it would be good to support different kind of shells
if not _get_user_for_ssh(auth, username):
if not _get_user_for_ssh(username):
raise YunohostError('user_unknown', user=username)
auth.update('uid=%s,ou=users' % username, {'loginShell': '/bin/false'})
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
ldap.update('uid=%s,ou=users' % username, {'loginShell': '/bin/false'})
# Somehow this is needed otherwise the PAM thing doesn't forget about the
# old loginShell value ?
subprocess.call(['nscd', '-i', 'passwd'])
def user_ssh_list_keys(auth, username):
user = _get_user_for_ssh(auth, username, ["homeDirectory"])
def user_ssh_list_keys(username):
user = _get_user_for_ssh(username, ["homeDirectory"])
if not user:
raise Exception("User with username '%s' doesn't exists" % username)
@ -82,8 +86,8 @@ def user_ssh_list_keys(auth, username):
return {"keys": keys}
def user_ssh_add_key(auth, username, key, comment):
user = _get_user_for_ssh(auth, username, ["homeDirectory", "uid"])
def user_ssh_add_key(username, key, comment):
user = _get_user_for_ssh(username, ["homeDirectory", "uid"])
if not user:
raise Exception("User with username '%s' doesn't exists" % username)
@ -116,8 +120,8 @@ def user_ssh_add_key(auth, username, key, comment):
write_to_file(authorized_keys_file, authorized_keys_content)
def user_ssh_remove_key(auth, username, key):
user = _get_user_for_ssh(auth, username, ["homeDirectory", "uid"])
def user_ssh_remove_key(username, key):
user = _get_user_for_ssh(username, ["homeDirectory", "uid"])
if not user:
raise Exception("User with username '%s' doesn't exists" % username)
@ -148,8 +152,8 @@ def user_ssh_remove_key(auth, username, key):
#
def _get_user_for_ssh(auth, username, attrs=None):
def ssh_root_login_status(auth):
def _get_user_for_ssh(username, attrs=None):
def ssh_root_login_status():
# XXX temporary placed here for when the ssh_root commands are integrated
# extracted from https://github.com/YunoHost/yunohost/pull/345
# XXX should we support all the options?
@ -172,7 +176,7 @@ def _get_user_for_ssh(auth, username, attrs=None):
'username': 'root',
'fullname': '',
'mail': '',
'ssh_allowed': ssh_root_login_status(auth)["PermitRootLogin"],
'ssh_allowed': ssh_root_login_status()["PermitRootLogin"],
'shell': root_unix.pw_shell,
'home_path': root_unix.pw_dir,
}
@ -189,7 +193,9 @@ def _get_user_for_ssh(auth, username, attrs=None):
}
# TODO escape input using https://www.python-ldap.org/doc/html/ldap-filter.html
user = auth.search('ou=users,dc=yunohost,dc=org',
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
user = ldap.search('ou=users,dc=yunohost,dc=org',
'(&(objectclass=person)(uid=%s))' % username,
attrs)

View file

@ -111,10 +111,9 @@ def tools_ldapinit():
raise YunohostError('installation_failed')
logger.success(m18n.n('ldap_initialized'))
return auth
def tools_adminpw(auth, new_password, check_strength=True):
def tools_adminpw(new_password, check_strength=True):
"""
Change admin password
@ -136,8 +135,11 @@ def tools_adminpw(auth, new_password, check_strength=True):
new_hash = _hash_user_password(new_password)
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
try:
auth.update("cn=admin", {"userPassword": new_hash, })
ldap.update("cn=admin", {"userPassword": new_hash, })
except:
logger.exception('unable to change admin password')
raise YunohostError('admin_password_change_failed')
@ -161,7 +163,7 @@ def tools_adminpw(auth, new_password, check_strength=True):
@is_unit_operation()
def tools_maindomain(operation_logger, auth, new_domain=None):
def tools_maindomain(operation_logger, new_domain=None):
"""
Check the current main domain, or change it
@ -175,7 +177,7 @@ def tools_maindomain(operation_logger, auth, new_domain=None):
return {'current_main_domain': _get_maindomain()}
# Check domain exists
if new_domain not in domain_list(auth)['domains']:
if new_domain not in domain_list()['domains']:
raise YunohostError('domain_unknown')
operation_logger.related_to.append(('domain', new_domain))
@ -204,7 +206,7 @@ def tools_maindomain(operation_logger, auth, new_domain=None):
_set_hostname(new_domain)
# Generate SSOwat configuration file
app_ssowatconf(auth)
app_ssowatconf()
# Regen configurations
try:
@ -331,7 +333,7 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False,
# Initialize LDAP for YunoHost
# TODO: Improve this part by integrate ldapinit into conf_regen hook
auth = tools_ldapinit()
tools_ldapinit()
# Create required folders
folders_to_create = [
@ -405,11 +407,11 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False,
# New domain config
regen_conf(['nsswitch'], force=True)
domain_add(auth, domain, dyndns)
tools_maindomain(auth, domain)
domain_add(domain, dyndns)
tools_maindomain(domain)
# Change LDAP admin password
tools_adminpw(auth, password, check_strength=not force_password)
tools_adminpw(password, check_strength=not force_password)
# Enable UPnP silently and reload firewall
firewall_upnp('enable', no_refresh=True)
@ -573,7 +575,7 @@ def _dump_sources_list():
@is_unit_operation()
def tools_upgrade(operation_logger, auth, ignore_apps=False, ignore_packages=False):
def tools_upgrade(operation_logger, ignore_apps=False, ignore_packages=False):
"""
Update apps & package cache, then display changelog
@ -645,7 +647,7 @@ def tools_upgrade(operation_logger, auth, ignore_apps=False, ignore_packages=Fal
if not ignore_apps:
try:
app_upgrade(auth)
app_upgrade()
except Exception as e:
failure = True
logger.warning('unable to upgrade apps: %s' % str(e))
@ -659,7 +661,7 @@ def tools_upgrade(operation_logger, auth, ignore_apps=False, ignore_packages=Fal
return {"log": service_log('yunohost-api', number="100").values()[0]}
def tools_diagnosis(auth, private=False):
def tools_diagnosis(private=False):
"""
Return global info about current yunohost instance to help debugging
@ -754,7 +756,7 @@ def tools_diagnosis(auth, private=False):
diagnosis['private']['public_ip']['IPv6'] = get_public_ip(6)
# Domains
diagnosis['private']['domains'] = domain_list(auth)['domains']
diagnosis['private']['domains'] = domain_list()['domains']
diagnosis['private']['regen_conf'] = regen_conf(with_diff=True, dry_run=True)
@ -1078,18 +1080,21 @@ def tools_migrations_state():
return read_json(MIGRATIONS_STATE_PATH)
def tools_shell(auth, command=None):
def tools_shell(command=None):
"""
Launch an (i)python shell in the YunoHost context.
This is entirely aim for development.
"""
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
if command:
exec(command)
return
logger.warn("The \033[1;34mauth\033[0m is available in this context")
logger.warn("The \033[1;34mldap\033[0m interface is available in this context")
try:
from IPython import embed
embed()

View file

@ -41,7 +41,7 @@ from yunohost.log import is_unit_operation
logger = getActionLogger('yunohost.user')
def user_list(auth, fields=None):
def user_list(fields=None):
"""
List users
@ -52,6 +52,8 @@ def user_list(auth, fields=None):
fields -- fields to fetch
"""
from yunohost.utils.ldap import _get_ldap_interface
user_attrs = {
'uid': 'username',
'cn': 'fullname',
@ -75,7 +77,8 @@ def user_list(auth, fields=None):
else:
attrs = ['uid', 'cn', 'mail', 'mailuserquota', 'loginShell']
result = auth.search('ou=users,dc=yunohost,dc=org',
ldap = _get_ldap_interface()
result = ldap.search('ou=users,dc=yunohost,dc=org',
'(&(objectclass=person)(!(uid=root))(!(uid=nobody)))',
attrs)
@ -98,7 +101,7 @@ def user_list(auth, fields=None):
@is_unit_operation([('username', 'user')])
def user_create(operation_logger, auth, username, firstname, lastname, mail, password,
def user_create(operation_logger, username, firstname, lastname, mail, password,
mailbox_quota="0"):
"""
Create user
@ -116,12 +119,15 @@ def user_create(operation_logger, auth, username, firstname, lastname, mail, pas
from yunohost.hook import hook_callback
from yunohost.app import app_ssowatconf
from yunohost.utils.password import assert_password_is_strong_enough
from yunohost.utils.ldap import _get_ldap_interface
# Ensure sufficiently complex password
assert_password_is_strong_enough("user", password)
ldap = _get_ldap_interface()
# Validate uniqueness of username and mail in LDAP
auth.validate_uniqueness({
ldap.validate_uniqueness({
'uid': username,
'mail': mail
})
@ -143,7 +149,7 @@ def user_create(operation_logger, auth, username, firstname, lastname, mail, pas
raise YunohostError('mail_unavailable')
# Check that the mail domain exists
if mail.split("@")[1] not in domain_list(auth)['domains']:
if mail.split("@")[1] not in domain_list()['domains']:
raise YunohostError('mail_domain_unknown', domain=mail.split("@")[1])
operation_logger.start()
@ -177,7 +183,7 @@ def user_create(operation_logger, auth, username, firstname, lastname, mail, pas
}
# If it is the first user, add some aliases
if not auth.search(base='ou=users,dc=yunohost,dc=org', filter='uid=*'):
if not ldap.search(base='ou=users,dc=yunohost,dc=org', filter='uid=*'):
attr_dict['mail'] = [attr_dict['mail']] + aliases
# If exists, remove the redirection from the SSO
@ -197,14 +203,14 @@ def user_create(operation_logger, auth, username, firstname, lastname, mail, pas
except IOError as e:
raise YunohostError('ssowat_persistent_conf_write_error', error=e.strerror)
if auth.add('uid=%s,ou=users' % username, attr_dict):
if ldap.add('uid=%s,ou=users' % username, attr_dict):
# Invalidate passwd to take user creation into account
subprocess.call(['nscd', '-i', 'passwd'])
# Update SFTP user group
memberlist = auth.search(filter='cn=sftpusers', attrs=['memberUid'])[0]['memberUid']
memberlist = ldap.search(filter='cn=sftpusers', attrs=['memberUid'])[0]['memberUid']
memberlist.append(username)
if auth.update('cn=sftpusers,ou=groups', {'memberUid': memberlist}):
if ldap.update('cn=sftpusers,ou=groups', {'memberUid': memberlist}):
try:
# Attempt to create user home folder
subprocess.check_call(
@ -213,7 +219,7 @@ def user_create(operation_logger, auth, username, firstname, lastname, mail, pas
if not os.path.isdir('/home/{0}'.format(username)):
logger.warning(m18n.n('user_home_creation_failed'),
exc_info=1)
app_ssowatconf(auth)
app_ssowatconf()
# TODO: Send a welcome mail to user
logger.success(m18n.n('user_created'))
hook_callback('post_user_create',
@ -225,7 +231,7 @@ def user_create(operation_logger, auth, username, firstname, lastname, mail, pas
@is_unit_operation([('username', 'user')])
def user_delete(operation_logger, auth, username, purge=False):
def user_delete(operation_logger, username, purge=False):
"""
Delete user
@ -236,34 +242,37 @@ def user_delete(operation_logger, auth, username, purge=False):
"""
from yunohost.app import app_ssowatconf
from yunohost.hook import hook_callback
from yunohost.utils.ldap import _get_ldap_interface
operation_logger.start()
if auth.remove('uid=%s,ou=users' % username):
ldap = _get_ldap_interface()
if ldap.remove('uid=%s,ou=users' % username):
# Invalidate passwd to take user deletion into account
subprocess.call(['nscd', '-i', 'passwd'])
# Update SFTP user group
memberlist = auth.search(filter='cn=sftpusers', attrs=['memberUid'])[0]['memberUid']
memberlist = ldap.search(filter='cn=sftpusers', attrs=['memberUid'])[0]['memberUid']
try:
memberlist.remove(username)
except:
pass
if auth.update('cn=sftpusers,ou=groups', {'memberUid': memberlist}):
if ldap.update('cn=sftpusers,ou=groups', {'memberUid': memberlist}):
if purge:
subprocess.call(['rm', '-rf', '/home/{0}'.format(username)])
subprocess.call(['rm', '-rf', '/var/mail/{0}'.format(username)])
else:
raise YunohostError('user_deletion_failed')
app_ssowatconf(auth)
app_ssowatconf()
hook_callback('post_user_delete', args=[username, purge])
logger.success(m18n.n('user_deleted'))
@is_unit_operation([('username', 'user')], exclude=['auth', 'change_password'])
def user_update(operation_logger, auth, username, firstname=None, lastname=None, mail=None,
@is_unit_operation([('username', 'user')], exclude=['change_password'])
def user_update(operation_logger, username, firstname=None, lastname=None, mail=None,
change_password=None, add_mailforward=None, remove_mailforward=None,
add_mailalias=None, remove_mailalias=None, mailbox_quota=None):
"""
@ -284,13 +293,15 @@ def user_update(operation_logger, auth, username, firstname=None, lastname=None,
from yunohost.domain import domain_list, _get_maindomain
from yunohost.app import app_ssowatconf
from yunohost.utils.password import assert_password_is_strong_enough
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
attrs_to_fetch = ['givenName', 'sn', 'mail', 'maildrop']
new_attr_dict = {}
domains = domain_list(auth)['domains']
domains = domain_list()['domains']
# Populate user informations
result = auth.search(base='ou=users,dc=yunohost,dc=org', filter='uid=' + username, attrs=attrs_to_fetch)
result = ldap.search(base='ou=users,dc=yunohost,dc=org', filter='uid=' + username, attrs=attrs_to_fetch)
if not result:
raise YunohostError('user_unknown', user=username)
user = result[0]
@ -321,7 +332,7 @@ def user_update(operation_logger, auth, username, firstname=None, lastname=None,
'webmaster@' + main_domain,
'postmaster@' + main_domain,
]
auth.validate_uniqueness({'mail': mail})
ldap.validate_uniqueness({'mail': mail})
if mail[mail.find('@') + 1:] not in domains:
raise YunohostError('mail_domain_unknown', domain=mail[mail.find('@') + 1:])
if mail in aliases:
@ -334,7 +345,7 @@ def user_update(operation_logger, auth, username, firstname=None, lastname=None,
if not isinstance(add_mailalias, list):
add_mailalias = [add_mailalias]
for mail in add_mailalias:
auth.validate_uniqueness({'mail': mail})
ldap.validate_uniqueness({'mail': mail})
if mail[mail.find('@') + 1:] not in domains:
raise YunohostError('mail_domain_unknown', domain=mail[mail.find('@') + 1:])
user['mail'].append(mail)
@ -374,15 +385,15 @@ def user_update(operation_logger, auth, username, firstname=None, lastname=None,
operation_logger.start()
if auth.update('uid=%s,ou=users' % username, new_attr_dict):
if ldap.update('uid=%s,ou=users' % username, new_attr_dict):
logger.success(m18n.n('user_updated'))
app_ssowatconf(auth)
return user_info(auth, username)
app_ssowatconf()
return user_info(username)
else:
raise YunohostError('user_update_failed')
def user_info(auth, username):
def user_info(username):
"""
Get user informations
@ -390,6 +401,10 @@ def user_info(auth, username):
username -- Username or mail to get informations
"""
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
user_attrs = [
'cn', 'mail', 'uid', 'maildrop', 'givenName', 'sn', 'mailuserquota'
]
@ -399,7 +414,7 @@ def user_info(auth, username):
else:
filter = 'uid=' + username
result = auth.search('ou=users,dc=yunohost,dc=org', filter, user_attrs)
result = ldap.search('ou=users,dc=yunohost,dc=org', filter, user_attrs)
if result:
user = result[0]
@ -469,24 +484,24 @@ def user_info(auth, username):
import yunohost.ssh
def user_ssh_allow(auth, username):
return yunohost.ssh.user_ssh_allow(auth, username)
def user_ssh_allow(username):
return yunohost.ssh.user_ssh_allow(username)
def user_ssh_disallow(auth, username):
return yunohost.ssh.user_ssh_disallow(auth, username)
def user_ssh_disallow(username):
return yunohost.ssh.user_ssh_disallow(username)
def user_ssh_list_keys(auth, username):
return yunohost.ssh.user_ssh_list_keys(auth, username)
def user_ssh_list_keys(username):
return yunohost.ssh.user_ssh_list_keys(username)
def user_ssh_add_key(auth, username, key, comment):
return yunohost.ssh.user_ssh_add_key(auth, username, key, comment)
def user_ssh_add_key(username, key, comment):
return yunohost.ssh.user_ssh_add_key(username, key, comment)
def user_ssh_remove_key(auth, username, key):
return yunohost.ssh.user_ssh_remove_key(auth, username, key)
def user_ssh_remove_key(username, key):
return yunohost.ssh.user_ssh_remove_key(username, key)
#
# End SSH subcategory