From a92ff5307774d657b601051b31e0e52634472180 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 12 Sep 2019 00:20:22 +0200 Subject: [PATCH] Propagate changes to other parts of the code relying on groups and permissions --- src/yunohost/app.py | 29 +++++++----------- src/yunohost/backup.py | 61 ++++++++++++++++---------------------- src/yunohost/permission.py | 9 ++++-- 3 files changed, 44 insertions(+), 55 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 14396b1cd..f505dd088 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -465,7 +465,7 @@ def app_change_url(operation_logger, app, domain, path): """ from yunohost.hook import hook_exec, hook_callback from yunohost.domain import _normalize_domain_path, _get_conflicting_apps - from yunohost.permission import permission_update + from yunohost.permission import permission_urls installed = _is_installed(app) if not installed: @@ -555,7 +555,7 @@ def app_change_url(operation_logger, app, domain, path): app_setting(app, 'domain', value=domain) app_setting(app, 'path', value=path) - permission_update(app, permission="main", add_url=[domain+path], remove_url=[old_domain+old_path], sync_perm=True) + permission_urls(app+".main", add=[domain+path], remove=[old_domain+old_path], sync_perm=True) # avoid common mistakes if _run_service_command("reload", "nginx") is False: @@ -738,7 +738,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu from yunohost.utils.ldap import _get_ldap_interface from yunohost.hook import hook_add, hook_remove, hook_exec, hook_callback from yunohost.log import OperationLogger - from yunohost.permission import permission_create, permission_update, permission_delete, permission_sync_to_user + from yunohost.permission import permission_create, permission_urls, permission_delete, permission_sync_to_user ldap = _get_ldap_interface() # Fetch or extract sources @@ -875,7 +875,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu # Create permission before the install (useful if the install script redefine the permission) # Note that sync_perm is disabled to avoid triggering a whole bunch of code and messages # can't be sure that we don't have one case when it's needed - permission_create(app=app_instance_name, permission="main", sync_perm=False) + permission_create(app_instance_name+".main", sync_perm=False) # Execute the app install script install_retcode = 1 @@ -910,11 +910,9 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu args=[app_instance_name], env=env_dict_remove )[0] # Remove all permission in LDAP - result = ldap.search(base='ou=permission,dc=yunohost,dc=org', - filter='(&(objectclass=permissionYnh)(cn=*.%s))' % app_instance_name, attrs=['cn']) - permission_list = [p['cn'][0] for p in result] - for l in permission_list: - permission_delete(app_instance_name, l.split('.')[0], force=True) + for permission_name in user_permission_list()["permissions"].keys(): + if permission_name.startswith(app_instance_name+"."): + permission_delete(permission_name, force=True) if remove_retcode != 0: msg = m18n.n('app_not_properly_removed', @@ -960,8 +958,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu domain = app_settings.get('domain', None) path = app_settings.get('path', None) if domain and path: - permission_update(app_instance_name, permission="main", add_url=[domain+path], sync_perm=False) - + permission_urls(app_instance_name+".main", add=[domain+path], sync_perm=False) permission_sync_to_user() logger.success(m18n.n('installation_complete')) @@ -978,7 +975,6 @@ def app_remove(operation_logger, app): app -- App(s) to delete """ - from yunohost.utils.ldap import _get_ldap_interface from yunohost.hook import hook_exec, hook_remove, hook_callback from yunohost.permission import permission_delete, permission_sync_to_user if not _is_installed(app): @@ -1026,12 +1022,9 @@ def app_remove(operation_logger, app): hook_remove(app) # Remove all permission in LDAP - ldap = _get_ldap_interface() - result = ldap.search(base='ou=permission,dc=yunohost,dc=org', - filter='(&(objectclass=permissionYnh)(cn=*.%s))' % app, attrs=['cn']) - permission_list = [p['cn'][0] for p in result] - for l in permission_list: - permission_delete(app, l.split('.')[0], force=True, sync_perm=False) + for permission_name in user_permission_list()["permissions"].keys(): + if permission_name.startswith(app+"."): + permission_delete(permission_name, force=True, sync_perm=False) permission_sync_to_user() diff --git a/src/yunohost/backup.py b/src/yunohost/backup.py index fdbd8c62c..0527f89bf 100644 --- a/src/yunohost/backup.py +++ b/src/yunohost/backup.py @@ -703,6 +703,10 @@ class BackupManager(): self._import_to_list_to_backup(env_dict["YNH_BACKUP_CSV"]) # backup permissions + # + # FIXME : why can't we instead use a simple yaml file to store the + # relevant info and recreate the permission object from it ... + # logger.debug(m18n.n('backup_permission', app=app)) ldap_url = "ldap:///dc=yunohost,dc=org???(&(objectClass=permissionYnh)(cn=*.%s))" % app os.system("slapcat -b dc=yunohost,dc=org -H '%s' -l '%s/permission.ldif'" % (ldap_url, settings_dir)) @@ -919,7 +923,7 @@ class RestoreManager(): successfull_apps = self.targets.list("apps", include=["Success", "Warning"]) - permission_sync_to_user(force=False) + permission_sync_to_user() if os.path.ismount(self.work_dir): ret = subprocess.call(["umount", self.work_dir]) @@ -1183,18 +1187,11 @@ class RestoreManager(): if system_targets == []: return - from yunohost.utils.ldap import _get_ldap_interface - ldap = _get_ldap_interface() + from yunohost.permission import permission_create, user_permission_update, user_permission_list # Backup old permission for apps # We need to do that because in case of an app is installed we can't remove the permission for this app - old_apps_permission = [] - try: - old_apps_permission = ldap.search('ou=permission,dc=yunohost,dc=org', - '(&(objectClass=permissionYnh)(!(cn=main.mail))(!(cn=main.xmpp))(!(cn=main.sftp)))', - ['cn', 'objectClass', 'groupPermission', 'URL', 'gidNumber']) - except: - logger.info(m18n.n('apps_permission_not_found')) + old_apps_permission = user_permission_list(ignore_system_perms=True)["permissions"] # Start register change on system operation_logger = OperationLogger('backup_restore_system') @@ -1232,12 +1229,11 @@ class RestoreManager(): regen_conf() - # Check if we need to do the migration 0009 : setup group and permission + # Check that at least a group exists (all_users) to know if we need to + # do the migration 0011 : setup group and permission + # # Legacy code - result = ldap.search('ou=groups,dc=yunohost,dc=org', - '(&(objectclass=groupOfNamesYnh)(cn=all_users))', - ['cn']) - if not result: + if not user_group_list["groups"]: from yunohost.tools import _get_migration_by_name setup_group_permission = _get_migration_by_name("setup_group_permission") # Update LDAP schema restart slapd @@ -1245,22 +1241,16 @@ class RestoreManager(): regen_conf(names=['slapd'], force=True) setup_group_permission.migrate_LDAP_db() - # Remove all permission for all app which sill in the LDAP - for per in ldap.search('ou=permission,dc=yunohost,dc=org', - '(&(objectClass=permissionYnh)(!(cn=mail.main))(!(cn=xmpp.main))(!(cn=sftp.main)))', - ['cn']): - if not ldap.remove('cn=%s,ou=permission' % per['cn'][0]): - raise YunohostError('permission_deletion_failed', - permission=per['cn'][0].split('.')[0], - app=per['cn'][0].split('.')[1]) + # Remove all permission for all app which is still in the LDAP + for permission_name in user_permission_list(ignore_system_perms=True)["permissions"].keys(): + permission_delete(permission_name) # Restore permission for the app which is installed - for per in old_apps_permission: - # FIXME : will come here later to fix this following previous commits ... - permission_name, app_name = per['cn'][0].split('.') + for permission_name, permission_infos in old_apps_permission.items(): + app_name = permission_name.split(".")[0] if _is_installed(app_name): - if not ldap.add('cn=%s,ou=permission' % per['cn'][0], per): - raise YunohostError('apps_permission_restoration_failed', permission=permission_name, app=app_name) + permission_create(permission_name, urls=permission_infos["urls"], sync_perm=False) + user_permission_update(permission_name, remove="all_users", add=permission_infos["allowed"]) def _restore_apps(self): @@ -1368,6 +1358,10 @@ class RestoreManager(): restore_script = os.path.join(tmp_folder_for_app_restore, 'restore') # Restore permissions + # + # FIXME : why can't we instead use a simple yaml file to store the + # relevant info and recreate the permission object from it ... + # if os.path.isfile(app_settings_in_archive + '/permission.ldif'): filtred_entries = ['entryUUID', 'creatorsName', 'createTimestamp', 'entryCSN', 'structuralObjectClass', 'modifiersName', 'modifyTimestamp', 'inheritPermission', 'memberUid'] @@ -1422,7 +1416,6 @@ class RestoreManager(): operation_logger.start() # Execute remove script - # TODO: call app_remove instead if hook_exec(remove_script, args=[app_instance_name], env=env_dict_remove)[0] != 0: msg = m18n.n('app_not_properly_removed', app=app_instance_name) @@ -1434,12 +1427,10 @@ class RestoreManager(): # Cleaning app directory shutil.rmtree(app_settings_new_path, ignore_errors=True) - # Remove all permission in LDAP - result = ldap.search(base='ou=permission,dc=yunohost,dc=org', - filter='(&(objectclass=permissionYnh)(cn=*.%s))' % app_instance_name, attrs=['cn']) - permission_list = [p['cn'][0] for p in result] - for l in permission_list: - permission_delete(app_instance_name, l.split('.')[0], force=True) + # Remove all permission in LDAP for this app + for permission_name in user_permission_list()["permissions"].keys(): + if permission_name.startswith(app_instance_name+"."): + permission_delete(permission_name, force=True) # TODO Cleaning app hooks else: diff --git a/src/yunohost/permission.py b/src/yunohost/permission.py index 21ee960fa..4d935d3c0 100644 --- a/src/yunohost/permission.py +++ b/src/yunohost/permission.py @@ -36,6 +36,8 @@ from yunohost.log import is_unit_operation logger = getActionLogger('yunohost.user') +SYSTEM_PERMS = ["mail", "xmpp", "stfp"] + # # # The followings are the methods exposed through the "yunohost user permission" interface @@ -43,7 +45,7 @@ logger = getActionLogger('yunohost.user') # -def user_permission_list(short=False, full=False): +def user_permission_list(short=False, full=False, ignore_system_perms=True): """ List permissions and corresponding accesses """ @@ -62,8 +64,11 @@ def user_permission_list(short=False, full=False): for infos in permissions_infos: name = infos['cn'][0] - permissions[name] = {} + if ignore_system_perms and name.split(".")[0] in SYSTEM_PERMS: + continue + + permissions[name] = {} permissions[name]["allowed"] = [_ldap_path_extract(p, "cn") for p in infos.get('groupPermission', [])] if full: