diff --git a/CHANGES.rst b/CHANGES.rst index 73a7d2c5..2a3a4212 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,7 +12,7 @@ Changes Features / Changes ~~~~~~~~~~~~~~~~~~ -* Create an additional settings/environment variable ``MAGPIE_SUPPLEMENTAL_USER_NAME_REGEX`` that acts as an additional +* Create an additional settings/environment variable ``MAGPIE_USER_NAME_EXTRA_REGEX`` that acts as an additional check for whether a ``username`` is valid. This creates a further restriction on this value which is useful when there are additional limits on the ``username`` that should be enforced by `Magpie`. diff --git a/config/magpie.ini b/config/magpie.ini index d6893721..e41b0685 100644 --- a/config/magpie.ini +++ b/config/magpie.ini @@ -63,7 +63,7 @@ magpie.user_registration_notify_email_template = # --- user validation settings --- -#magpie.supplemental_user_name_regex = +#magpie.user_name_extra_regex = # --- user assignment to groups with t&c --- magpie.group_terms_submission_email_template = diff --git a/docs/configuration.rst b/docs/configuration.rst index 9b580612..490d2d10 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -1433,7 +1433,7 @@ approval procedures. User Validation Settings ~~~~~~~~~~~~~~~~~~~~~~~~ -.. envvar:: MAGPIE_SUPPLEMENTAL_USER_NAME_REGEX +.. envvar:: MAGPIE_USER_NAME_EXTRA_REGEX (Default: ``None``) @@ -1441,7 +1441,7 @@ User Validation Settings A (python3 syntax) regular expression used to validate a ``username`` when creating or updating a `User`. - For example, if ``MAGPIE_SUPPLEMENTAL_USER_NAME_REGEX='^\w+$'``, then a `User` can have ``userA`` as a ``username`` + For example, if ``MAGPIE_USER_NAME_EXTRA_REGEX='^\w+$'``, then a `User` can have ``userA`` as a ``username`` but not ``user.A`` or ``user-A``. Note that `Magpie` enforces other restrictions that must also be met for a ``username`` to be considered valid. diff --git a/magpie/api/management/user/user_utils.py b/magpie/api/management/user/user_utils.py index 0536b239..737b25e9 100644 --- a/magpie/api/management/user/user_utils.py +++ b/magpie/api/management/user/user_utils.py @@ -872,14 +872,14 @@ def check_user_info(user_name=None, email=None, password=None, group_name=None, ax.verify_param(user_name, matches=True, param_name="user_name", param_compare=ax.PARAM_REGEX, http_error=HTTPBadRequest, msg_on_fail=s.Users_CheckInfo_UserNameValue_BadRequestResponseSchema.description) - supplemental_regex = get_constant("MAGPIE_SUPPLEMENTAL_USER_NAME_REGEX", raise_missing=False, + extra_regex = get_constant("MAGPIE_USER_NAME_EXTRA_REGEX", raise_missing=False, raise_not_set=False) - if supplemental_regex: + if extra_regex: ax.verify_param( - user_name, matches=True, param_name="user_name", param_compare=supplemental_regex, + user_name, matches=True, param_name="user_name", param_compare=extra_regex, http_error=HTTPBadRequest, - msg_on_fail=s.Users_CheckInfo_UserNameValueSupplementalRegex_BadRequestResponseSchema.description, - param_content={"setting": "magpie.supplemental_user_name_regex"} + msg_on_fail=s.Users_CheckInfo_UserNameValueExtraRegex_BadRequestResponseSchema.description, + param_content={"setting": "magpie.user_name_extra_regex"} ) name_range = range(1, 1 + get_constant("MAGPIE_USER_NAME_MAX_LENGTH")) ax.verify_param(len(user_name), is_in=True, param_name="user_name", param_compare=name_range, diff --git a/magpie/api/schemas.py b/magpie/api/schemas.py index cbdc53ef..cd7fb8f5 100644 --- a/magpie/api/schemas.py +++ b/magpie/api/schemas.py @@ -1962,8 +1962,8 @@ class Users_CheckInfo_UserNameValue_BadRequestResponseSchema(BaseResponseSchemaA body = ErrorResponseBodySchema(code=HTTPBadRequest.code, description=description) -class Users_CheckInfo_UserNameValueSupplementalRegex_BadRequestResponseSchema(BaseResponseSchemaAPI): - description = "Invalid 'user_name' value specified. Does not match the supplemental user name regex." +class Users_CheckInfo_UserNameValueExtraRegex_BadRequestResponseSchema(BaseResponseSchemaAPI): + description = "Invalid 'user_name' value specified. Does not match the extra user name regex." body = ErrorResponseBodySchema(code=HTTPBadRequest.code, description=description) diff --git a/tests/interfaces.py b/tests/interfaces.py index 2438f65f..37ba7c8c 100644 --- a/tests/interfaces.py +++ b/tests/interfaces.py @@ -7517,12 +7517,15 @@ def test_AddUser_FormSubmit(self): utils.check_val_is_in(self.test_user_name, body) @runner.MAGPIE_TEST_USERS - def test_AddUser_FormSubmit_WithSupplementalUsernameRegex_Invalid(self): + def test_AddUser_FormSubmit_WithExtraUsernameRegex_Invalid(self): """ - Check that the supplemental_user_name_regex setting is used to validate a new user name when the user name is + Check that the extra_user_name_regex setting is used to validate a new user name when the user name is invalid according to that regex but is valid according to the ax.PARAM_REGEX. + + .. versionadded:: 3.37 """ - with utils.mocked_get_settings(settings={"magpie.supplemental_user_name_regex": "^$"}): + utils.warn_version(self, "extra username regex added", "3.37", skip=True) + with utils.mocked_get_settings(settings={"magpie.user_name_extra_regex": "^$"}): data = {"user_name": self.test_user_name, "group_name": get_constant("MAGPIE_USERS_GROUP"), "email": "{}@mail.com".format(self.test_user_name), "password": self.test_user_name, "confirm": self.test_user_name} @@ -7531,16 +7534,19 @@ def test_AddUser_FormSubmit_WithSupplementalUsernameRegex_Invalid(self): resp = utils.TestSetup.check_FormSubmit(self, form_match=form, form_submit="create", form_data=data, path=path) body = utils.check_ui_response_basic_info(resp) - msg = s.Users_CheckInfo_UserNameValueSupplementalRegex_BadRequestResponseSchema.description + msg = s.Users_CheckInfo_UserNameValueExtraRegex_BadRequestResponseSchema.description utils.check_val_is_in(msg, html.unescape(body)) @runner.MAGPIE_TEST_USERS - def test_AddUser_FormSubmit_WithSupplementalUsernameRegex_ValidGoodUsername(self): + def test_AddUser_FormSubmit_WithExtraUsernameRegex_ValidGoodUsername(self): """ - Check that the supplemental_user_name_regex setting is used to validate a new user name when the user name is + Check that the user_name_extra_regex setting is used to validate a new user name when the user name is valid according to that regex and the ax.PARAM_REGEX. + + .. versionadded:: 3.37 """ - with utils.mocked_get_settings(settings={"magpie.supplemental_user_name_regex": "^.*$"}): + utils.warn_version(self, "extra username regex added", "3.37", skip=True) + with utils.mocked_get_settings(settings={"magpie.user_name_extra_regex": "^.*$"}): data = {"user_name": self.test_user_name, "group_name": get_constant("MAGPIE_USERS_GROUP"), "email": "{}@mail.com".format(self.test_user_name), "password": self.test_user_name, "confirm": self.test_user_name} @@ -7556,12 +7562,15 @@ def test_AddUser_FormSubmit_WithSupplementalUsernameRegex_ValidGoodUsername(self utils.check_val_is_in(self.test_user_name, body) @runner.MAGPIE_TEST_USERS - def test_AddUser_FormSubmit_WithSupplementalUsernameRegex_InvalidBadUsername(self): + def test_AddUser_FormSubmit_WithExtraUsernameRegex_InvalidBadUsername(self): """ - Check that the supplemental_user_name_regex setting is used to validate a new user name when the user name is + Check that the extra_user_name_regex setting is used to validate a new user name when the user name is valid according to that regex but not the ax.PARAM_REGEX. + + .. versionadded:: 3.37 """ - with utils.mocked_get_settings(settings={"magpie.supplemental_user_name_regex": "^.*$"}): + utils.warn_version(self, "extra username regex added", "3.37", skip=True) + with utils.mocked_get_settings(settings={"magpie.user_name_extra_regex": "^.*$"}): email = "{}@mail.com".format(self.test_user_name) # the @ symbol is invalid according to the ax.PARAM_REGEX data = {"user_name": email, "group_name": get_constant("MAGPIE_USERS_GROUP"), "email": email, "password": self.test_user_name, "confirm": self.test_user_name} @@ -7572,10 +7581,10 @@ def test_AddUser_FormSubmit_WithSupplementalUsernameRegex_InvalidBadUsername(sel body = utils.check_ui_response_basic_info(resp) # the error message should indicate that the user name is invalid according to the original regex - # (ax.PARAM_REGEX) not the supplemental regex + # (ax.PARAM_REGEX) not the extra regex msg = s.Users_CheckInfo_UserNameValue_BadRequestResponseSchema.description utils.check_val_is_in(msg, html.unescape(body)) - msg = s.Users_CheckInfo_UserNameValueSupplementalRegex_BadRequestResponseSchema.description + msg = s.Users_CheckInfo_UserNameValueExtraRegex_BadRequestResponseSchema.description utils.check_val_not_in(msg, html.unescape(body)) @runner.MAGPIE_TEST_STATUS diff --git a/tests/test_magpie_api.py b/tests/test_magpie_api.py index 68d593e9..a00a9bb5 100644 --- a/tests/test_magpie_api.py +++ b/tests/test_magpie_api.py @@ -451,6 +451,82 @@ def test_PostUserGroupWithTerms_Fail(self): utils.check_val_type(body["user_names"], list) utils.check_val_not_in(self.test_user_name, body["user_names"]) + @runner.MAGPIE_TEST_USERS + def test_PostUsers_NoExtraRegex_ValidRegex(self): + """ + Check that the user_name_extra_regex setting is not used to validate a new user name when user_name_extra_regex + is falsy. + + .. versionadded:: 3.37 + """ + utils.warn_version(self, "extra username regex added", "3.37", skip=True) + with utils.mocked_get_settings(settings={"magpie.user_name_extra_regex": None}): + data = { + "user_name": self.test_user_name, + "password": self.test_user_name, + "email": "email@example.com", + } + resp = utils.test_request(self, "POST", "/users", data=data, + headers=self.json_headers, cookies=self.cookies, expect_errors=True) + utils.check_response_basic_info(resp, 201, expected_method="POST") + + @runner.MAGPIE_TEST_USERS + def test_PostUsers_WithExtraRegex_InvalidExtraRegex(self): + """ + Check that the user_name_extra_regex setting is used to validate a new user name when the user name is + invalid according to that regex but is valid according to the ax.PARAM_REGEX. + + .. versionadded:: 3.37 + """ + utils.warn_version(self, "extra username regex added", "3.37", skip=True) + with utils.mocked_get_settings(settings={"magpie.user_name_extra_regex": "^$"}): + data = { + "user_name": self.test_user_name, + "password": self.test_user_name, + "email": "email@example.com", + } + resp = utils.test_request(self, "POST", "/users", data=data, + headers=self.json_headers, cookies=self.cookies, expect_errors=True) + utils.check_response_basic_info(resp, 400, expected_method="POST") + + @runner.MAGPIE_TEST_USERS + def test_PostUsers_WithExtraRegex_InvalidRegex(self): + """ + Check that the user_name_extra_regex setting is used to validate a new user name when the user name is + valid according to that regex but is invalid according to the ax.PARAM_REGEX. + + .. versionadded:: 3.37 + """ + utils.warn_version(self, "extra username regex added", "3.37", skip=True) + with utils.mocked_get_settings(settings={"magpie.user_name_extra_regex": "^.*$"}): + data = { + "user_name": "email@example.com", + "password": self.test_user_name, + "email": "email@example.com", + } + resp = utils.test_request(self, "POST", "/users", data=data, + headers=self.json_headers, cookies=self.cookies, expect_errors=True) + utils.check_response_basic_info(resp, 400, expected_method="POST") + + + @runner.MAGPIE_TEST_USERS + def test_PostUsers_WithExtraRegex_ValidBoth(self): + """ + Check that the user_name_extra_regex setting is used to validate a new user name when the user name is + valid according to that regex and the ax.PARAM_REGEX. + + .. versionadded:: 3.37 + """ + utils.warn_version(self, "extra username regex added", "3.37", skip=True) + with utils.mocked_get_settings(settings={"magpie.user_name_extra_regex": "^.*$"}): + data = { + "user_name": self.test_user_name, + "password": self.test_user_name, + "email": "email@example.com", + } + resp = utils.test_request(self, "POST", "/users", data=data, + headers=self.json_headers, cookies=self.cookies, expect_errors=True) + utils.check_response_basic_info(resp, 201, expected_method="POST") @runner.MAGPIE_TEST_API @runner.MAGPIE_TEST_LOCAL