def clean_user_groups(): for u in user_list()["users"]: user_delete(u) for g in user_group_list()["groups"]: if g not in ["all_users", "visitors"]: user_group_delete(g)
def test_del_group(mocker): with message(mocker, "group_deleted", group="dev"): user_group_delete("dev") group_res = user_group_list()["groups"] assert "dev" not in group_res
def permission_sync_to_user(): """ Sychronise the inheritPermission attribut in the permission object from the user<->group link and the group<->permission link """ import os from yunohost.app import app_ssowatconf from yunohost.user import user_group_list from yunohost.utils.ldap import _get_ldap_interface ldap = _get_ldap_interface() groups = user_group_list(full=True)["groups"] permissions = user_permission_list(full=True)["permissions"] for permission_name, permission_infos in permissions.items(): # These are the users currently allowed because there's an 'inheritPermission' object corresponding to it currently_allowed_users = set(permission_infos["corresponding_users"]) # These are the users that should be allowed because they are member of a group that is allowed for this permission ... should_be_allowed_users = set([ user for group in permission_infos["allowed"] for user in groups[group]["members"] ]) # Note that a LDAP operation with the same value that is in LDAP crash SLAP. # So we need to check before each ldap operation that we really change something in LDAP if currently_allowed_users == should_be_allowed_users: # We're all good, this permission is already correctly synchronized ! continue new_inherited_perms = { "inheritPermission": [ "uid=%s,ou=users,dc=yunohost,dc=org" % u for u in should_be_allowed_users ], "memberUid": should_be_allowed_users, } # Commit the change with the new inherited stuff try: ldap.update("cn=%s,ou=permission" % permission_name, new_inherited_perms) except Exception as e: raise YunohostError("permission_update_failed", permission=permission_name, error=e) logger.debug("The permission database has been resynchronized") app_ssowatconf() # Reload unscd, otherwise the group ain't propagated to the LDAP database os.system("nscd --invalidate=passwd") os.system("nscd --invalidate=group")
def test_update_group_add_user_already_in(mocker): with message(mocker, "group_user_already_in_group", user="******", group="apps"): user_group_update("apps", add=["bob"]) group_res = user_group_list()["groups"] assert group_res["apps"]["members"] == ["bob"]
def test_create_group(mocker): with message(mocker, "group_created", group="adminsys"): user_group_create("adminsys") group_res = user_group_list()["groups"] assert "adminsys" in group_res assert "members" in group_res["adminsys"].keys() assert group_res["adminsys"]["members"] == []
def test_del_user(mocker): with message(mocker, "user_deleted"): user_delete("alice") group_res = user_group_list()["groups"] assert "alice" not in user_list() assert "alice" not in group_res assert "alice" not in group_res["all_users"]["members"]
def test_create_user(mocker): with message(mocker, "user_created"): user_create("albert", "Albert", "Good", maindomain, "test123Ynh") group_res = user_group_list()["groups"] assert "albert" in user_list()["users"] assert "albert" in group_res assert "albert" in group_res["albert"]["members"] assert "albert" in group_res["all_users"]["members"]
def test_list_groups(): res = user_group_list()["groups"] assert "all_users" in res assert "alice" in res assert "bob" in res assert "jack" in res for u in ["alice", "bob", "jack"]: assert u in res assert u in res[u]["members"] assert u in res["all_users"]["members"]
def clean_user_groups_permission(): for u in user_list()['users']: user_delete(u) for g in user_group_list()['groups']: if g not in ["all_users", "visitors"]: user_group_delete(g) for p in user_permission_list()['permissions']: if any( p.startswith(name) for name in ["wiki", "blog", "site", "web", "permissions_app"]): permission_delete(p, force=True, sync_perm=False) socket.getaddrinfo = prv_getaddrinfo
def permission_create( operation_logger, permission, allowed=None, url=None, additional_urls=None, auth_header=True, label=None, show_tile=False, protected=False, sync_perm=True, ): """ Create a new permission for a specific application Keyword argument: permission -- Name of the permission (e.g. mail or nextcloud or wordpress.editors) allowed -- (optional) List of group/user to allow for the permission url -- (optional) URL for which access will be allowed/forbidden additional_urls -- (optional) List of additional URL for which access will be allowed/forbidden auth_header -- (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application label -- (optional) Define a name for the permission. This label will be shown on the SSO and in the admin. Default is "permission name" show_tile -- (optional) Define if a tile will be shown in the SSO protected -- (optional) Define if the permission can be added/removed to the visitor group If provided, 'url' is assumed to be relative to the app domain/path if they start with '/'. For example: / -> domain.tld/app /admin -> domain.tld/app/admin domain.tld/app/api -> domain.tld/app/api 'url' can be later treated as a regex if it starts with "re:". For example: re:/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$ re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$ """ from yunohost.utils.ldap import _get_ldap_interface from yunohost.user import user_group_list ldap = _get_ldap_interface() # By default, manipulate main permission if "." not in permission: permission = permission + ".main" # Validate uniqueness of permission in LDAP if ldap.get_conflict({"cn": permission}, base_dn="ou=permission,dc=yunohost,dc=org"): raise YunohostValidationError("permission_already_exist", permission=permission) # Get random GID all_gid = {x.gr_gid for x in grp.getgrall()} uid_guid_found = False while not uid_guid_found: gid = str(random.randint(200, 99999)) uid_guid_found = gid not in all_gid app, subperm = permission.split(".") attr_dict = { "objectClass": ["top", "permissionYnh", "posixGroup"], "cn": str(permission), "gidNumber": gid, "authHeader": ["TRUE"], "label": [ str(label) if label else (subperm if subperm != "main" else app.title()) ], "showTile": [ "FALSE" ], # Dummy value, it will be fixed when we call '_update_ldap_group_permission' "isProtected": [ "FALSE" ], # Dummy value, it will be fixed when we call '_update_ldap_group_permission' } if allowed is not None: if not isinstance(allowed, list): allowed = [allowed] # Validate that the groups to add actually exist all_existing_groups = user_group_list()["groups"].keys() for group in allowed or []: if group not in all_existing_groups: raise YunohostValidationError("group_unknown", group=group) operation_logger.related_to.append(("app", permission.split(".")[0])) operation_logger.start() try: ldap.add("cn=%s,ou=permission" % permission, attr_dict) except Exception as e: raise YunohostError("permission_creation_failed", permission=permission, error=e) permission_url( permission, url=url, add_url=additional_urls, auth_header=auth_header, sync_perm=False, ) new_permission = _update_ldap_group_permission( permission=permission, allowed=allowed, label=label, show_tile=show_tile, protected=protected, sync_perm=sync_perm, ) logger.debug(m18n.n("permission_created", permission=permission)) return new_permission
def user_permission_update( operation_logger, permission, add=None, remove=None, label=None, show_tile=None, protected=None, force=False, sync_perm=True, ): """ Allow or Disallow a user or group to a permission for a specific application Keyword argument: permission -- Name of the permission (e.g. mail or or wordpress or wordpress.editors) add -- (optional) List of groups or usernames to add to this permission remove -- (optional) List of groups or usernames to remove from to this permission label -- (optional) Define a name for the permission. This label will be shown on the SSO and in the admin show_tile -- (optional) Define if a tile will be shown in the SSO protected -- (optional) Define if the permission can be added/removed to the visitor group force -- (optional) Give the possibility to add/remove access from the visitor group to a protected permission """ from yunohost.user import user_group_list # By default, manipulate main permission if "." not in permission: permission = permission + ".main" existing_permission = user_permission_info(permission) # Refuse to add "visitors" to mail, xmpp ... they require an account to make sense. if add and "visitors" in add and permission.split(".")[0] in SYSTEM_PERMS: raise YunohostValidationError("permission_require_account", permission=permission) # Refuse to add "visitors" to protected permission if ((add and "visitors" in add and existing_permission["protected"]) or (remove and "visitors" in remove and existing_permission["protected"])) and not force: raise YunohostValidationError("permission_protected", permission=permission) # Fetch currently allowed groups for this permission current_allowed_groups = existing_permission["allowed"] operation_logger.related_to.append(("app", permission.split(".")[0])) # Compute new allowed group list (and make sure what we're doing make sense) new_allowed_groups = copy.copy(current_allowed_groups) all_existing_groups = user_group_list()["groups"].keys() if add: groups_to_add = [add] if not isinstance(add, list) else add for group in groups_to_add: if group not in all_existing_groups: raise YunohostValidationError("group_unknown", group=group) if group in current_allowed_groups: logger.warning( m18n.n("permission_already_allowed", permission=permission, group=group)) else: operation_logger.related_to.append(("group", group)) new_allowed_groups += [group] if remove: groups_to_remove = [remove] if not isinstance(remove, list) else remove for group in groups_to_remove: if group not in current_allowed_groups: logger.warning( m18n.n( "permission_already_disallowed", permission=permission, group=group, )) else: operation_logger.related_to.append(("group", group)) new_allowed_groups = [ g for g in new_allowed_groups if g not in groups_to_remove ] # If we end up with something like allowed groups is ["all_users", "volunteers"] # we shall warn the users that they should probably choose between one or # the other, because the current situation is probably not what they expect # / is temporary ? Note that it's fine to have ["all_users", "visitors"] # though, but it's not fine to have ["all_users", "visitors", "volunteers"] if "all_users" in new_allowed_groups and len(new_allowed_groups) >= 2: if "visitors" not in new_allowed_groups or len( new_allowed_groups) >= 3: logger.warning( m18n.n("permission_currently_allowed_for_all_users")) # Note that we can get this argument as string if we it come from the CLI if isinstance(show_tile, str): if show_tile.lower() == "true": show_tile = True else: show_tile = False if (existing_permission["url"] and existing_permission["url"].startswith("re:") and show_tile): logger.warning( m18n.n( "regex_incompatible_with_tile", regex=existing_permission["url"], permission=permission, )) # Commit the new allowed group list operation_logger.start() new_permission = _update_ldap_group_permission( permission=permission, allowed=new_allowed_groups, label=label, show_tile=show_tile, protected=protected, sync_perm=sync_perm, ) logger.debug(m18n.n("permission_updated", permission=permission)) return new_permission
def test_update_group_add_user_that_doesnt_exist(mocker): with raiseYunohostError(mocker, "user_unknown"): user_group_update("dev", add=["doesnt_exist"]) assert "doesnt_exist" not in user_group_list()["groups"]["dev"]["members"]
def test_update_group_primary_manually(mocker): with raiseYunohostError(mocker, "group_cannot_edit_primary_group"): user_group_update("alice", remove=["alice"]) assert "alice" in user_group_list()["groups"]["alice"]["members"]
def test_update_group_remove_user_not_already_in(mocker): with message(mocker, "group_user_not_in_group", user="******", group="apps"): user_group_update("apps", remove=["jack"]) group_res = user_group_list()["groups"] assert group_res["apps"]["members"] == ["bob"]
def test_update_group_remove_user(mocker): with message(mocker, "group_updated", group="apps"): user_group_update("apps", remove=["bob"]) group_res = user_group_list()["groups"] assert group_res["apps"]["members"] == []
def test_update_group_add_user(mocker): with message(mocker, "group_updated", group="dev"): user_group_update("dev", add=["bob"]) group_res = user_group_list()["groups"] assert set(group_res["dev"]["members"]) == set(["alice", "bob"])