mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Add users_add bulk operation
This commit is contained in:
parent
3f070edb61
commit
5efd72a9d7
2 changed files with 72 additions and 13 deletions
|
@ -7,7 +7,7 @@ import os
|
||||||
from .conftest import message, raiseYunohostError, get_test_apps_dir
|
from .conftest import message, raiseYunohostError, get_test_apps_dir
|
||||||
|
|
||||||
from yunohost.domain import _get_maindomain, domain_add, domain_remove, domain_list
|
from yunohost.domain import _get_maindomain, domain_add, domain_remove, domain_list
|
||||||
from yunohost.user import user_create, user_list, user_delete
|
from yunohost.user import user_create, user_list, user_delete, User, users_add
|
||||||
from yunohost.authenticators.ldap_ynhuser import Authenticator, SESSION_FOLDER, short_hash
|
from yunohost.authenticators.ldap_ynhuser import Authenticator, SESSION_FOLDER, short_hash
|
||||||
from yunohost.app import app_install, app_remove, app_setting, app_ssowatconf, app_change_url
|
from yunohost.app import app_install, app_remove, app_setting, app_ssowatconf, app_change_url
|
||||||
from yunohost.permission import user_permission_list, user_permission_update
|
from yunohost.permission import user_permission_list, user_permission_update
|
||||||
|
@ -44,10 +44,11 @@ def setup_module(module):
|
||||||
assert os.system("systemctl is-active yunohost-portal-api >/dev/null") == 0
|
assert os.system("systemctl is-active yunohost-portal-api >/dev/null") == 0
|
||||||
|
|
||||||
userlist = user_list()["users"]
|
userlist = user_list()["users"]
|
||||||
if "alice" not in userlist:
|
users_to_add = [ user for user in [
|
||||||
user_create("alice", maindomain, dummy_password, fullname="Alice White", admin=True)
|
User("alice", maindomain, dummy_password, fullname="Alice White", admin=True),
|
||||||
if "bob" not in userlist:
|
User("bob", maindomain, dummy_password, fullname="Bob Marley"),
|
||||||
user_create("bob", maindomain, dummy_password, fullname="Bob Marley")
|
] if user.name not in userlist ]
|
||||||
|
users_add(users_to_add)
|
||||||
|
|
||||||
domainlist = domain_list()["domains"]
|
domainlist = domain_list()["domains"]
|
||||||
domains = [ domain for domain in [ subdomain, secondarydomain ] if domain not in domainlist ]
|
domains = [ domain for domain in [ subdomain, secondarydomain ] if domain not in domainlist ]
|
||||||
|
|
74
src/user.py
74
src/user.py
|
@ -24,6 +24,7 @@ import random
|
||||||
import subprocess
|
import subprocess
|
||||||
import copy
|
import copy
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
from moulinette import Moulinette, m18n
|
from moulinette import Moulinette, m18n
|
||||||
from moulinette.utils.process import check_output
|
from moulinette.utils.process import check_output
|
||||||
|
@ -49,6 +50,20 @@ FIELDS_FOR_IMPORT = {
|
||||||
|
|
||||||
ADMIN_ALIASES = ["root", "admin", "admins", "webmaster", "postmaster", "abuse"]
|
ADMIN_ALIASES = ["root", "admin", "admins", "webmaster", "postmaster", "abuse"]
|
||||||
|
|
||||||
|
class User:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str,
|
||||||
|
domain: str,
|
||||||
|
password: str,
|
||||||
|
fullname: Optional[str] = None,
|
||||||
|
admin: bool = False,
|
||||||
|
):
|
||||||
|
self.name = name
|
||||||
|
self.password = password
|
||||||
|
self.domain = domain
|
||||||
|
self.fullname = fullname
|
||||||
|
self.admin = admin
|
||||||
|
|
||||||
def user_list(fields=None):
|
def user_list(fields=None):
|
||||||
from yunohost.utils.ldap import _get_ldap_interface
|
from yunohost.utils.ldap import _get_ldap_interface
|
||||||
|
@ -131,6 +146,40 @@ def shellexists(shell):
|
||||||
"""Check if the provided shell exists and is executable."""
|
"""Check if the provided shell exists and is executable."""
|
||||||
return os.path.isfile(shell) and os.access(shell, os.X_OK)
|
return os.path.isfile(shell) and os.access(shell, os.X_OK)
|
||||||
|
|
||||||
|
# Used in tests to create many users at once.
|
||||||
|
# The permissions are synchronized at the end of the entire operation.
|
||||||
|
@is_unit_operation()
|
||||||
|
def users_add(
|
||||||
|
operation_logger,
|
||||||
|
users: List[User],
|
||||||
|
):
|
||||||
|
hooks = []
|
||||||
|
for user in users:
|
||||||
|
# Only force regen_conf on the last iteration
|
||||||
|
hooks.append(user_create(user.name, user.domain, user.password, fullname=user.fullname, admin=user.admin, do_regen_conf=False))
|
||||||
|
|
||||||
|
# Invalidate passwd and group to take user and group creation into account
|
||||||
|
subprocess.call(["nscd", "-i", "passwd"])
|
||||||
|
subprocess.call(["nscd", "-i", "group"])
|
||||||
|
|
||||||
|
# Add new users to all_users group
|
||||||
|
user_group_update(groupname="all_users", add=[ user.name for user in users ], force=True, sync_perm=False)
|
||||||
|
|
||||||
|
# Do we have new admins?
|
||||||
|
admins = [ user.name for user in users if user.admin ]
|
||||||
|
if len(admins) > 0:
|
||||||
|
user_group_update(groupname="admins", add=admins, sync_perm=False)
|
||||||
|
|
||||||
|
from yunohost.permission import permission_sync_to_user
|
||||||
|
from yunohost.hook import hook_callback
|
||||||
|
|
||||||
|
# Now we can sync the permissions
|
||||||
|
permission_sync_to_user()
|
||||||
|
|
||||||
|
for hook in hooks:
|
||||||
|
# Trigger post_user_create hooks
|
||||||
|
hook_callback("post_user_create", args=[hook["YNH_USER_USERNAME"], hook["YNH_USER_PASSWORD"]], env=hook)
|
||||||
|
logger.success(m18n.n("user_created"))
|
||||||
|
|
||||||
@is_unit_operation([("username", "user")])
|
@is_unit_operation([("username", "user")])
|
||||||
def user_create(
|
def user_create(
|
||||||
|
@ -143,6 +192,7 @@ def user_create(
|
||||||
admin=False,
|
admin=False,
|
||||||
from_import=False,
|
from_import=False,
|
||||||
loginShell=None,
|
loginShell=None,
|
||||||
|
do_regen_conf=True,
|
||||||
):
|
):
|
||||||
if not fullname or not fullname.strip():
|
if not fullname or not fullname.strip():
|
||||||
raise YunohostValidationError(
|
raise YunohostValidationError(
|
||||||
|
@ -260,9 +310,6 @@ def user_create(
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise YunohostError("user_creation_failed", user=username, error=e)
|
raise YunohostError("user_creation_failed", user=username, error=e)
|
||||||
|
|
||||||
# Invalidate passwd and group to take user and group creation into account
|
|
||||||
subprocess.call(["nscd", "-i", "passwd"])
|
|
||||||
subprocess.call(["nscd", "-i", "group"])
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Attempt to create user home folder
|
# Attempt to create user home folder
|
||||||
|
@ -277,13 +324,8 @@ def user_create(
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
logger.warning(f"Failed to protect /home/{username}", exc_info=1)
|
logger.warning(f"Failed to protect /home/{username}", exc_info=1)
|
||||||
|
|
||||||
# Create group for user and add to group 'all_users'
|
|
||||||
user_group_create(groupname=username, gid=uid, primary_group=True, sync_perm=False)
|
user_group_create(groupname=username, gid=uid, primary_group=True, sync_perm=False)
|
||||||
user_group_update(groupname="all_users", add=username, force=True, sync_perm=True)
|
|
||||||
if admin:
|
|
||||||
user_group_update(groupname="admins", add=username, sync_perm=True)
|
|
||||||
|
|
||||||
# Trigger post_user_create hooks
|
|
||||||
env_dict = {
|
env_dict = {
|
||||||
"YNH_USER_USERNAME": username,
|
"YNH_USER_USERNAME": username,
|
||||||
"YNH_USER_MAIL": mail,
|
"YNH_USER_MAIL": mail,
|
||||||
|
@ -292,6 +334,22 @@ def user_create(
|
||||||
"YNH_USER_LASTNAME": lastname,
|
"YNH_USER_LASTNAME": lastname,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# If do_regen_conf is False, it means we are in a higher operation that will
|
||||||
|
# finish synchronizing everything, then run the hooks... so we return early,
|
||||||
|
# transmitting the env_dict for further hook run.
|
||||||
|
if not do_regen_conf:
|
||||||
|
return env_dict
|
||||||
|
|
||||||
|
# Invalidate passwd and group to take user and group creation into account
|
||||||
|
subprocess.call(["nscd", "-i", "passwd"])
|
||||||
|
subprocess.call(["nscd", "-i", "group"])
|
||||||
|
|
||||||
|
# Create group for user and add to group 'all_users'
|
||||||
|
user_group_update(groupname="all_users", add=username, force=True, sync_perm=not admin)
|
||||||
|
if admin:
|
||||||
|
user_group_update(groupname="admins", add=username, sync_perm=True)
|
||||||
|
|
||||||
|
# Trigger post_user_create hooks
|
||||||
hook_callback("post_user_create", args=[username, mail], env=env_dict)
|
hook_callback("post_user_create", args=[username, mail], env=env_dict)
|
||||||
|
|
||||||
# TODO: Send a welcome mail to user
|
# TODO: Send a welcome mail to user
|
||||||
|
|
Loading…
Add table
Reference in a new issue