From 78a2d012bb6926185d047f452712bb073c34fd4c Mon Sep 17 00:00:00 2001 From: ekhae Date: Fri, 16 Aug 2019 17:59:22 +0000 Subject: [PATCH 1/7] UX improved about mail and domains --- data/actionsmap/yunohost.yml | 31 +++++++++++++------------------ locales/en.json | 1 + src/yunohost/user.py | 22 +++++++++++++++++----- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index d61538c5c..13a3cfaaf 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -97,15 +97,6 @@ user: pattern: &pattern_lastname - !!str ^([^\W\d_]{2,30}[ ,.'-]{0,3})+$ - "pattern_lastname" - -m: - full: --mail - help: Main unique email address - extra: - ask: ask_email - required: True - pattern: &pattern_email - - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$ - - "pattern_email" -p: full: --password help: User password @@ -116,6 +107,13 @@ user: - !!str ^.{3,}$ - "pattern_password" comment: good_practices_about_user_password + -d: + full: --domain + help: Domain for email and xmpp + extra: + pattern: &pattern_domain + - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$ + - "pattern_domain" -q: full: --mailbox-quota help: Mailbox size quota @@ -157,7 +155,9 @@ user: -m: full: --mail extra: - pattern: *pattern_email + pattern: &pattern_email + - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$ + - "pattern_email" -p: full: --change-password help: New password to set @@ -419,9 +419,7 @@ domain: domain: help: Domain name to add extra: - pattern: &pattern_domain - - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$ - - "pattern_domain" + pattern: *pattern_domain -d: full: --dyndns help: Subscribe to the DynDNS service @@ -1340,7 +1338,7 @@ dyndns: tools: category_help: Specific tools actions: - + ### tools_adminpw() adminpw: action_help: Change password of admin and root users @@ -1368,9 +1366,6 @@ tools: postinstall: action_help: YunoHost post-install api: POST /postinstall - configuration: - # We need to be able to run the postinstall without being authenticated, otherwise we can't run the postinstall - authenticate: false arguments: -d: full: --domain @@ -1378,7 +1373,7 @@ tools: extra: ask: ask_main_domain pattern: *pattern_domain - required: True + required: False -p: full: --password help: YunoHost admin password diff --git a/locales/en.json b/locales/en.json index 83cc84442..afc9db13a 100644 --- a/locales/en.json +++ b/locales/en.json @@ -60,6 +60,7 @@ "apps_catalog_failed_to_download": "Unable to download the {apps_catalog} app catalog: {error}", "apps_catalog_obsolete_cache": "The app catalog cache is empty or obsolete.", "apps_catalog_update_success": "The application catalog has been updated!", + "ask_domain": "Choose a domain", "ask_email": "E-mail address", "ask_firstname": "First name", "ask_lastname": "Last name", diff --git a/src/yunohost/user.py b/src/yunohost/user.py index d19da177c..bd8252d0e 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -105,7 +105,7 @@ def user_list(fields=None): @is_unit_operation([('username', 'user')]) -def user_create(operation_logger, username, firstname, lastname, mail, password, +def user_create(operation_logger, username, firstname, lastname, domain, password, mailbox_quota="0"): """ Create user @@ -126,7 +126,22 @@ def user_create(operation_logger, username, firstname, lastname, mail, password, # Ensure sufficiently complex password assert_password_is_strong_enough("user", password) + from moulinette import msignals, msettings, m18n + from yunohost.domain import domain_list + if domain is None: + if msettings.get('interface') == 'api': + raise YunohostError('Invalide usage, specify domain argument') + else: + # On affiche les differents domaines possibles + for domain_checked in domain_list()['domains'] : + msignals.display("- {}".format(domain_checked)) + domain = msignals.prompt(m18n.n('ask_domain')) + # Check that the domain exists + if domain not in domain_list()['domains']: + raise YunohostError('domain_unknown', domain) + + mail=username+'@'+ domain ldap = _get_ldap_interface() if username in user_list()["users"]: @@ -158,10 +173,6 @@ def user_create(operation_logger, username, firstname, lastname, mail, password, if mail in aliases: raise YunohostError('mail_unavailable') - # Check that the mail domain exists - if mail.split("@")[1] not in domain_list()['domains']: - raise YunohostError('mail_domain_unknown', domain=mail.split("@")[1]) - operation_logger.start() # Get random UID/GID @@ -176,6 +187,7 @@ def user_create(operation_logger, username, firstname, lastname, mail, password, # Adapt values for LDAP fullname = '%s %s' % (firstname, lastname) + attr_dict = { 'objectClass': ['mailAccount', 'inetOrgPerson', 'posixAccount', 'userPermissionYnh'], 'givenName': [firstname], From 4a15358ed9618df18701c57c15666167eaafa17f Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 27 Aug 2020 17:31:17 +0200 Subject: [PATCH 2/7] Revert a few unecessary changes / polish code --- data/actionsmap/yunohost.yml | 7 +++++-- src/yunohost/user.py | 7 +++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 13a3cfaaf..803c5bfda 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -1338,7 +1338,7 @@ dyndns: tools: category_help: Specific tools actions: - + ### tools_adminpw() adminpw: action_help: Change password of admin and root users @@ -1366,6 +1366,9 @@ tools: postinstall: action_help: YunoHost post-install api: POST /postinstall + configuration: + # We need to be able to run the postinstall without being authenticated, otherwise we can't run the postinstall + authenticate: false arguments: -d: full: --domain @@ -1373,7 +1376,7 @@ tools: extra: ask: ask_main_domain pattern: *pattern_domain - required: False + required: True -p: full: --password help: YunoHost admin password diff --git a/src/yunohost/user.py b/src/yunohost/user.py index bd8252d0e..98dafc24d 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -34,7 +34,7 @@ import string import subprocess import copy -from moulinette import m18n +from moulinette import msignals, msettings, m18n from moulinette.utils.log import getActionLogger from moulinette.utils.filesystem import read_json, write_to_json, read_yaml, write_to_yaml @@ -126,8 +126,7 @@ def user_create(operation_logger, username, firstname, lastname, domain, passwor # Ensure sufficiently complex password assert_password_is_strong_enough("user", password) - from moulinette import msignals, msettings, m18n - from yunohost.domain import domain_list + if domain is None: if msettings.get('interface') == 'api': raise YunohostError('Invalide usage, specify domain argument') @@ -141,7 +140,7 @@ def user_create(operation_logger, username, firstname, lastname, domain, passwor if domain not in domain_list()['domains']: raise YunohostError('domain_unknown', domain) - mail=username+'@'+ domain + mail = username + '@' + domain ldap = _get_ldap_interface() if username in user_list()["users"]: From dea6a187125c55dff9d64921c355fd1414072cd7 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 27 Aug 2020 17:31:33 +0200 Subject: [PATCH 3/7] Polish UX --- data/actionsmap/yunohost.yml | 2 +- locales/en.json | 2 +- src/yunohost/user.py | 12 +++++++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 803c5bfda..e2439b2dc 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -109,7 +109,7 @@ user: comment: good_practices_about_user_password -d: full: --domain - help: Domain for email and xmpp + help: Domain for the email address and xmpp account extra: pattern: &pattern_domain - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$ diff --git a/locales/en.json b/locales/en.json index afc9db13a..20bad0a8f 100644 --- a/locales/en.json +++ b/locales/en.json @@ -60,7 +60,7 @@ "apps_catalog_failed_to_download": "Unable to download the {apps_catalog} app catalog: {error}", "apps_catalog_obsolete_cache": "The app catalog cache is empty or obsolete.", "apps_catalog_update_success": "The application catalog has been updated!", - "ask_domain": "Choose a domain", + "ask_user_domain": "Domain to use for the user's email address and XMPP account", "ask_email": "E-mail address", "ask_firstname": "First name", "ask_lastname": "Last name", diff --git a/src/yunohost/user.py b/src/yunohost/user.py index 98dafc24d..2f5c13d97 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -127,14 +127,20 @@ def user_create(operation_logger, username, firstname, lastname, domain, passwor # Ensure sufficiently complex password assert_password_is_strong_enough("user", password) + # 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 - for domain_checked in domain_list()['domains'] : - msignals.display("- {}".format(domain_checked)) - domain = msignals.prompt(m18n.n('ask_domain')) + 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']: From ef4c3066ece6291dac7b3c0ae14b17420b56aed3 Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Wed, 2 Sep 2020 12:55:37 +0200 Subject: [PATCH 4/7] [fix] Accept chinese/arabic domain --- data/actionsmap/yunohost.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index e2439b2dc..5f7f3bc66 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -112,7 +112,7 @@ user: help: Domain for the email address and xmpp account extra: pattern: &pattern_domain - - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$ + - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W\d_]{2,})$ - "pattern_domain" -q: full: --mailbox-quota @@ -156,7 +156,7 @@ user: full: --mail extra: pattern: &pattern_email - - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$ + - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W\d_]{2,})$ - "pattern_email" -p: full: --change-password From b94187466463169e7e9e85960e75401e24a10923 Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Wed, 2 Sep 2020 12:56:41 +0200 Subject: [PATCH 5/7] [fix] Accept all domain --- data/actionsmap/yunohost.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 5f7f3bc66..e0f33e554 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -112,7 +112,7 @@ user: help: Domain for the email address and xmpp account extra: pattern: &pattern_domain - - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W\d_]{2,})$ + - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$ - "pattern_domain" -q: full: --mailbox-quota @@ -156,7 +156,7 @@ user: full: --mail extra: pattern: &pattern_email - - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W\d_]{2,})$ + - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$ - "pattern_email" -p: full: --change-password From 3fc4baa08fc9eba73004b90048736c792fcb0fc8 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 5 Sep 2020 17:21:45 +0200 Subject: [PATCH 6/7] Propagate change to unit tests --- src/yunohost/tests/test_user-group.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/yunohost/tests/test_user-group.py b/src/yunohost/tests/test_user-group.py index f1eae9c4e..361b411f3 100644 --- a/src/yunohost/tests/test_user-group.py +++ b/src/yunohost/tests/test_user-group.py @@ -25,10 +25,10 @@ def setup_function(function): global maindomain maindomain = _get_maindomain() - - user_create("alice", "Alice", "White", "alice@" + maindomain, "test123Ynh") - user_create("bob", "Bob", "Snow", "bob@" + maindomain, "test123Ynh") - user_create("jack", "Jack", "Black", "jack@" + maindomain, "test123Ynh") + + user_create("alice", "Alice", "White", maindomain, "test123Ynh") + user_create("bob", "Bob", "Snow", maindomain, "test123Ynh") + user_create("jack", "Jack", "Black", maindomain, "test123Ynh") user_group_create("dev") user_group_create("apps") @@ -79,7 +79,7 @@ def test_list_groups(): def test_create_user(mocker): with message(mocker, "user_created"): - user_create("albert", "Albert", "Good", "alber@" + maindomain, "test123Ynh") + user_create("albert", "Albert", "Good", maindomain, "test123Ynh") group_res = user_group_list()['groups'] assert "albert" in user_list()['users'] @@ -123,25 +123,26 @@ def test_del_group(mocker): # -def test_create_user_with_mail_address_already_taken(mocker): - with raiseYunohostError(mocker, "user_creation_failed"): - user_create("alice2", "Alice", "White", "alice@" + maindomain, "test123Ynh") - - def test_create_user_with_password_too_simple(mocker): with raiseYunohostError(mocker, "password_listed"): - user_create("other", "Alice", "White", "other@" + maindomain, "12") + user_create("other", "Alice", "White", maindomain, "12") def test_create_user_already_exists(mocker): with raiseYunohostError(mocker, "user_already_exists"): - user_create("alice", "Alice", "White", "other@" + maindomain, "test123Ynh") + user_create("alice", "Alice", "White", maindomain, "test123Ynh") +def test_create_user_with_domain_that_doesnt_exists(mocker): + with raiseYunohostError(mocker, "domain_unknown"): + user_create("alice", "Alice", "White", "doesnt.exists", "test123Ynh") def test_update_user_with_mail_address_already_taken(mocker): with raiseYunohostError(mocker, "user_update_failed"): user_update("bob", add_mailalias="alice@" + maindomain) +def test_update_user_with_mail_address_with_unknown_domain(mocker): + with raiseYunohostError(mocker, "mail_domain_unknown"): + user_update("alice", add_mailalias="alice@doesnt.exists") def test_del_user_that_does_not_exist(mocker): with raiseYunohostError(mocker, "user_unknown"): From 5805acbf6a124cb548d34077803dfcbfa1d1cca4 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 5 Sep 2020 18:35:35 +0200 Subject: [PATCH 7/7] Reimplement --mail as a deprecated option --- data/actionsmap/yunohost.yml | 3 +++ src/yunohost/user.py | 26 +++++--------------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index e0f33e554..054418ebd 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -97,6 +97,9 @@ user: pattern: &pattern_lastname - !!str ^([^\W\d_]{2,30}[ ,.'-]{0,3})+$ - "pattern_lastname" + -m: + full: --mail + help: (Deprecated, see --domain) Main unique email address -p: full: --password help: User password diff --git a/src/yunohost/user.py b/src/yunohost/user.py index 2f5c13d97..77062b6da 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -46,16 +46,7 @@ logger = getActionLogger('yunohost.user') def user_list(fields=None): - """ - List users - Keyword argument: - filter -- LDAP filter used to search - offset -- Starting number for user fetching - limit -- Maximum number of user fetched - fields -- fields to fetch - - """ from yunohost.utils.ldap import _get_ldap_interface user_attrs = { @@ -106,19 +97,8 @@ def user_list(fields=None): @is_unit_operation([('username', 'user')]) def user_create(operation_logger, username, firstname, lastname, domain, password, - mailbox_quota="0"): - """ - Create user + mailbox_quota="0", mail=None): - Keyword argument: - firstname - lastname - username -- Must be unique - mail -- Main mail address must be unique - password - mailbox_quota -- Mailbox size quota - - """ from yunohost.domain import domain_list, _get_maindomain from yunohost.hook import hook_callback from yunohost.utils.password import assert_password_is_strong_enough @@ -127,6 +107,10 @@ def user_create(operation_logger, username, firstname, lastname, domain, passwor # 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':