# Copyright (C) 2010-2024 RhodeCode GmbH # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License, version 3 # (only), as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # # This program is dual-licensed. If you wish to learn more about the # RhodeCode Enterprise Edition, including its added features, Support services, # and proprietary license terms, please see https://rhodecode.com/licenses/ import pytest from rhodecode.tests import assert_session_flash from rhodecode.tests.utils import AssertResponse from rhodecode.model.db import Session from rhodecode.model.settings import SettingsModel def assert_auth_settings_updated(response): assert response.status_int == 302, 'Expected response HTTP Found 302' assert_session_flash(response, 'Auth settings updated successfully') @pytest.mark.usefixtures("autologin_user", "app") class TestAuthSettingsView(object): def _enable_plugins(self, plugins_list, csrf_token, override=None, verify_response=False): test_url = '/_admin/auth' params = { 'auth_plugins': plugins_list, 'csrf_token': csrf_token, } if override: params.update(override) _enabled_plugins = [] for plugin in plugins_list.split(','): plugin_name = plugin.partition('#')[-1] enabled_plugin = '%s_enabled' % plugin_name cache_ttl = '%s_cache_ttl' % plugin_name # default params that are needed for each plugin, # `enabled` and `cache_ttl` params.update({ enabled_plugin: True, cache_ttl: 0 }) _enabled_plugins.append(enabled_plugin) # we need to clean any enabled plugin before, since they require # form params to be present db_plugin = SettingsModel().get_setting_by_name('auth_plugins') db_plugin.app_settings_value = \ 'egg:rhodecode-enterprise-ce#rhodecode' Session().add(db_plugin) Session().commit() for _plugin in _enabled_plugins: db_plugin = SettingsModel().get_setting_by_name(_plugin) if db_plugin: Session().delete(db_plugin) Session().commit() response = self.app.post(url=test_url, params=params) if verify_response: assert_auth_settings_updated(response) return params def _post_ldap_settings(self, params, override=None, force=False): params.update({ 'filter': 'user', 'user_member_of': '', 'user_search_base': '', 'user_search_filter': 'test_filter', 'host': 'dc.example.com', 'port': '999', 'timeout': 3600, 'tls_kind': 'PLAIN', 'tls_reqcert': 'NEVER', 'tls_cert_dir':'/etc/openldap/cacerts', 'dn_user': 'test_user', 'dn_pass': 'test_pass', 'base_dn': 'test_base_dn', 'search_scope': 'BASE', 'attr_login': 'test_attr_login', 'attr_firstname': 'ima', 'attr_lastname': 'tester', 'attr_email': 'test@example.com', 'cache_ttl': '0', }) if force: params = {} params.update(override or {}) test_url = '/_admin/auth/ldap/' response = self.app.post(url=test_url, params=params) return response def test_index(self): response = self.app.get('/_admin/auth') response.mustcontain('Authentication Plugins') @pytest.mark.parametrize("disable_plugin, needs_import", [ ('egg:rhodecode-enterprise-ce#headers', None), ('egg:rhodecode-enterprise-ce#crowd', None), ('egg:rhodecode-enterprise-ce#jasig_cas', None), ('egg:rhodecode-enterprise-ce#ldap', None), ('egg:rhodecode-enterprise-ce#pam', "pam"), ]) def test_disable_plugin(self, csrf_token, disable_plugin, needs_import): # TODO: johbo: "pam" is currently not available on darwin, # although the docs state that it should work on darwin. if needs_import: pytest.importorskip(needs_import) self._enable_plugins( 'egg:rhodecode-enterprise-ce#rhodecode,' + disable_plugin, csrf_token, verify_response=True) self._enable_plugins( 'egg:rhodecode-enterprise-ce#rhodecode', csrf_token, verify_response=True) def test_ldap_save_settings(self, csrf_token): params = self._enable_plugins( 'egg:rhodecode-enterprise-ce#rhodecode,' 'egg:rhodecode-enterprise-ce#ldap', csrf_token) response = self._post_ldap_settings(params) assert_auth_settings_updated(response) new_settings = SettingsModel().get_auth_settings() assert new_settings['auth_ldap_host'] == u'dc.example.com', \ 'fail db write compare' def test_ldap_error_form_wrong_port_number(self, csrf_token): params = self._enable_plugins( 'egg:rhodecode-enterprise-ce#rhodecode,' 'egg:rhodecode-enterprise-ce#ldap', csrf_token) invalid_port_value = 'invalid-port-number' response = self._post_ldap_settings(params, override={ 'port': invalid_port_value, }) assertr = response.assert_response() assertr.element_contains( '.form .field #port ~ .error-message', invalid_port_value) def test_ldap_error_form(self, csrf_token): params = self._enable_plugins( 'egg:rhodecode-enterprise-ce#rhodecode,' 'egg:rhodecode-enterprise-ce#ldap', csrf_token) response = self._post_ldap_settings(params, override={ 'attr_login': '', }) response.mustcontain("""The LDAP Login""" """ attribute of the CN must be specified""") def test_post_ldap_group_settings(self, csrf_token): params = self._enable_plugins( 'egg:rhodecode-enterprise-ce#rhodecode,' 'egg:rhodecode-enterprise-ce#ldap', csrf_token) response = self._post_ldap_settings(params, override={ 'host': 'dc-legacy.example.com', 'port': '999', 'tls_kind': 'PLAIN', 'tls_reqcert': 'NEVER', 'dn_user': 'test_user', 'dn_pass': 'test_pass', 'base_dn': 'test_base_dn', 'filter': 'test_filter', 'search_scope': 'BASE', 'attr_login': 'test_attr_login', 'attr_firstname': 'ima', 'attr_lastname': 'tester', 'attr_email': 'test@example.com', 'cache_ttl': '60', 'csrf_token': csrf_token, } ) assert_auth_settings_updated(response) new_settings = SettingsModel().get_auth_settings() assert new_settings['auth_ldap_host'] == u'dc-legacy.example.com', \ 'fail db write compare'