def user_create(operation_logger, username, firstname, lastname, domain, password, mailbox_quota="0", mail=None): from yunohost.domain import domain_list, _get_maindomain from yunohost.hook import hook_callback 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) if mail is not None: logger.warning( "Packagers ! Using --mail in 'yunohost user create' is deprecated ... please use --domain instead." ) domain = mail.split("@")[-1] # Validate domain used for email address/xmpp account if domain is None: if msettings.get('interface') == 'api': raise YunohostError('Invalide usage, specify domain argument') else: # On affiche les differents domaines possibles msignals.display(m18n.n('domains_available')) for domain in domain_list()['domains']: msignals.display("- {}".format(domain)) maindomain = _get_maindomain() domain = msignals.prompt( m18n.n('ask_user_domain') + ' (default: %s)' % maindomain) if not domain: domain = maindomain # Check that the domain exists if domain not in domain_list()['domains']: raise YunohostError('domain_name_unknown', domain=domain) mail = username + '@' + domain ldap = _get_ldap_interface() if username in user_list()["users"]: raise YunohostError("user_already_exists", user=username) # Validate uniqueness of username and mail in LDAP try: ldap.validate_uniqueness({ 'uid': username, 'mail': mail, 'cn': username }) except Exception as e: raise YunohostError('user_creation_failed', user=username, error=e) # Validate uniqueness of username in system users all_existing_usernames = {x.pw_name for x in pwd.getpwall()} if username in all_existing_usernames: raise YunohostError('system_username_exists') main_domain = _get_maindomain() aliases = [ 'root@' + main_domain, 'admin@' + main_domain, 'webmaster@' + main_domain, 'postmaster@' + main_domain, 'abuse@' + main_domain, ] if mail in aliases: raise YunohostError('mail_unavailable') operation_logger.start() # Get random UID/GID all_uid = {str(x.pw_uid) for x in pwd.getpwall()} all_gid = {str(x.gr_gid) for x in grp.getgrall()} uid_guid_found = False while not uid_guid_found: # LXC uid number is limited to 65536 by default uid = str(random.randint(200, 65000)) uid_guid_found = uid not in all_uid and uid not in all_gid # Adapt values for LDAP fullname = '%s %s' % (firstname, lastname) attr_dict = { 'objectClass': ['mailAccount', 'inetOrgPerson', 'posixAccount', 'userPermissionYnh'], 'givenName': [firstname], 'sn': [lastname], 'displayName': [fullname], 'cn': [fullname], 'uid': [username], 'mail': mail, # NOTE: this one seems to be already a list 'maildrop': [username], 'mailuserquota': [mailbox_quota], 'userPassword': [_hash_user_password(password)], 'gidNumber': [uid], 'uidNumber': [uid], 'homeDirectory': ['/home/' + username], 'loginShell': ['/bin/false'] } # If it is the first user, add some aliases if not ldap.search(base='ou=users,dc=yunohost,dc=org', filter='uid=*'): attr_dict['mail'] = [attr_dict['mail']] + aliases try: ldap.add('uid=%s,ou=users' % username, attr_dict) except Exception as 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: # Attempt to create user home folder subprocess.check_call(["mkhomedir_helper", username]) except subprocess.CalledProcessError: if not os.path.isdir('/home/{0}'.format(username)): logger.warning(m18n.n('user_home_creation_failed'), 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_update(groupname='all_users', add=username, force=True, sync_perm=True) # Trigger post_user_create hooks env_dict = { "YNH_USER_USERNAME": username, "YNH_USER_MAIL": mail, "YNH_USER_PASSWORD": password, "YNH_USER_FIRSTNAME": firstname, "YNH_USER_LASTNAME": lastname } hook_callback('post_user_create', args=[username, mail], env=env_dict) # TODO: Send a welcome mail to user logger.success(m18n.n('user_created')) return {'fullname': fullname, 'username': username, 'mail': mail}
def user_create( operation_logger, username, firstname, lastname, domain, password, mailbox_quota="0", mail=None, ): from yunohost.domain import domain_list, _get_maindomain from yunohost.hook import hook_callback 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) if mail is not None: logger.warning( "Packagers ! Using --mail in 'yunohost user create' is deprecated ... please use --domain instead." ) domain = mail.split("@")[-1] # Validate domain used for email address/xmpp account if domain is None: if msettings.get("interface") == "api": raise YunohostValidationError( "Invalid usage, you should specify a domain argument") else: # On affiche les differents domaines possibles msignals.display(m18n.n("domains_available")) for domain in domain_list()["domains"]: msignals.display("- {}".format(domain)) maindomain = _get_maindomain() domain = msignals.prompt( m18n.n("ask_user_domain") + " (default: %s)" % maindomain) if not domain: domain = maindomain # Check that the domain exists if domain not in domain_list()["domains"]: raise YunohostValidationError("domain_name_unknown", domain=domain) mail = username + "@" + domain ldap = _get_ldap_interface() if username in user_list()["users"]: raise YunohostValidationError("user_already_exists", user=username) # Validate uniqueness of username and mail in LDAP try: ldap.validate_uniqueness({ "uid": username, "mail": mail, "cn": username }) except Exception as e: raise YunohostValidationError("user_creation_failed", user=username, error=e) # Validate uniqueness of username in system users all_existing_usernames = {x.pw_name for x in pwd.getpwall()} if username in all_existing_usernames: raise YunohostValidationError("system_username_exists") main_domain = _get_maindomain() aliases = [ "root@" + main_domain, "admin@" + main_domain, "webmaster@" + main_domain, "postmaster@" + main_domain, "abuse@" + main_domain, ] if mail in aliases: raise YunohostValidationError("mail_unavailable") operation_logger.start() # Get random UID/GID all_uid = {str(x.pw_uid) for x in pwd.getpwall()} all_gid = {str(x.gr_gid) for x in grp.getgrall()} uid_guid_found = False while not uid_guid_found: # LXC uid number is limited to 65536 by default uid = str(random.randint(1001, 65000)) uid_guid_found = uid not in all_uid and uid not in all_gid # Adapt values for LDAP fullname = "%s %s" % (firstname, lastname) attr_dict = { "objectClass": [ "mailAccount", "inetOrgPerson", "posixAccount", "userPermissionYnh", ], "givenName": [firstname], "sn": [lastname], "displayName": [fullname], "cn": [fullname], "uid": [username], "mail": mail, # NOTE: this one seems to be already a list "maildrop": [username], "mailuserquota": [mailbox_quota], "userPassword": [_hash_user_password(password)], "gidNumber": [uid], "uidNumber": [uid], "homeDirectory": ["/home/" + username], "loginShell": ["/bin/false"], } # If it is the first user, add some aliases if not ldap.search(base="ou=users,dc=yunohost,dc=org", filter="uid=*"): attr_dict["mail"] = [attr_dict["mail"]] + aliases try: ldap.add("uid=%s,ou=users" % username, attr_dict) except Exception as 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: # Attempt to create user home folder subprocess.check_call(["mkhomedir_helper", username]) except subprocess.CalledProcessError: if not os.path.isdir("/home/{0}".format(username)): logger.warning(m18n.n("user_home_creation_failed"), 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_update(groupname="all_users", add=username, force=True, sync_perm=True) # Trigger post_user_create hooks env_dict = { "YNH_USER_USERNAME": username, "YNH_USER_MAIL": mail, "YNH_USER_PASSWORD": password, "YNH_USER_FIRSTNAME": firstname, "YNH_USER_LASTNAME": lastname, } hook_callback("post_user_create", args=[username, mail], env=env_dict) # TODO: Send a welcome mail to user logger.success(m18n.n("user_created")) return {"fullname": fullname, "username": username, "mail": mail}