diff --git a/rhodecode/apps/home/__init__.py b/rhodecode/apps/home/__init__.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/apps/home/__init__.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2016-2017 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/
+
+
+def includeme(config):
+
+ config.add_route(
+ name='user_autocomplete_data',
+ pattern='/_users')
+
+ config.add_route(
+ name='user_group_autocomplete_data',
+ pattern='/_user_groups')
+
+ # Scan module for configuration decorators.
+ config.scan()
diff --git a/rhodecode/apps/home/tests/__init__.py b/rhodecode/apps/home/tests/__init__.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/apps/home/tests/__init__.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2016-2017 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/
diff --git a/rhodecode/apps/home/tests/test_get_user_data.py b/rhodecode/apps/home/tests/test_get_user_data.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/apps/home/tests/test_get_user_data.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2016-2017 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 json
+import pytest
+
+from rhodecode.tests import TestController
+from rhodecode.tests.fixture import Fixture
+
+
+fixture = Fixture()
+
+
+def route_path(name, params=None, **kwargs):
+ import urllib
+
+ base_url = {
+ 'user_autocomplete_data': '/_users',
+ 'user_group_autocomplete_data': '/_user_groups'
+ }[name].format(**kwargs)
+
+ if params:
+ base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
+ return base_url
+
+
+class TestUserAutocompleteData(TestController):
+
+ def test_returns_list_of_users(self, user_util, xhr_header):
+ self.log_user()
+ user = user_util.create_user(active=True)
+ user_name = user.username
+ response = self.app.get(
+ route_path('user_autocomplete_data'),
+ extra_environ=xhr_header, status=200)
+ result = json.loads(response.body)
+ values = [suggestion['value'] for suggestion in result['suggestions']]
+ assert user_name in values
+
+ def test_returns_inactive_users_when_active_flag_sent(
+ self, user_util, xhr_header):
+ self.log_user()
+ user = user_util.create_user(active=False)
+ user_name = user.username
+
+ response = self.app.get(
+ route_path('user_autocomplete_data',
+ params=dict(user_groups='true', active='0')),
+ extra_environ=xhr_header, status=200)
+ result = json.loads(response.body)
+ values = [suggestion['value'] for suggestion in result['suggestions']]
+ assert user_name in values
+
+ response = self.app.get(
+ route_path('user_autocomplete_data',
+ params=dict(user_groups='true', active='1')),
+ extra_environ=xhr_header, status=200)
+ result = json.loads(response.body)
+ values = [suggestion['value'] for suggestion in result['suggestions']]
+ assert user_name not in values
+
+ def test_returns_groups_when_user_groups_flag_sent(
+ self, user_util, xhr_header):
+ self.log_user()
+ group = user_util.create_user_group(user_groups_active=True)
+ group_name = group.users_group_name
+ response = self.app.get(
+ route_path('user_autocomplete_data',
+ params=dict(user_groups='true')),
+ extra_environ=xhr_header, status=200)
+ result = json.loads(response.body)
+ values = [suggestion['value'] for suggestion in result['suggestions']]
+ assert group_name in values
+
+ @pytest.mark.parametrize('query, count', [
+ ('hello1', 0),
+ ('dev', 2),
+ ])
+ def test_result_is_limited_when_query_is_sent(self, user_util, xhr_header,
+ query, count):
+ self.log_user()
+
+ user_util._test_name = 'dev-test'
+ user_util.create_user()
+
+ user_util._test_name = 'dev-group-test'
+ user_util.create_user_group()
+
+ response = self.app.get(
+ route_path('user_autocomplete_data',
+ params=dict(user_groups='true', query=query)),
+ extra_environ=xhr_header, status=200)
+
+ result = json.loads(response.body)
+ assert len(result['suggestions']) == count
diff --git a/rhodecode/apps/home/tests/test_get_user_group_data.py b/rhodecode/apps/home/tests/test_get_user_group_data.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/apps/home/tests/test_get_user_group_data.py
@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2016-2017 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/
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2016-2017 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 json
+
+import pytest
+
+from rhodecode.tests import TestController
+from rhodecode.tests.fixture import Fixture
+
+
+fixture = Fixture()
+
+
+def route_path(name, params=None, **kwargs):
+ import urllib
+
+ base_url = {
+ 'user_autocomplete_data': '/_users',
+ 'user_group_autocomplete_data': '/_user_groups'
+ }[name].format(**kwargs)
+
+ if params:
+ base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
+ return base_url
+
+
+class TestUserGroupAutocompleteData(TestController):
+
+ def test_returns_list_of_user_groups(self, user_util, xhr_header):
+ self.log_user()
+ user_group = user_util.create_user_group(active=True)
+ user_group_name = user_group.users_group_name
+ response = self.app.get(
+ route_path('user_group_autocomplete_data'),
+ extra_environ=xhr_header, status=200)
+ result = json.loads(response.body)
+ values = [suggestion['value'] for suggestion in result['suggestions']]
+ assert user_group_name in values
+
+ def test_returns_inactive_user_groups_when_active_flag_sent(
+ self, user_util, xhr_header):
+ self.log_user()
+ user_group = user_util.create_user_group(active=False)
+ user_group_name = user_group.users_group_name
+
+ response = self.app.get(
+ route_path('user_group_autocomplete_data',
+ params=dict(active='0')),
+ extra_environ=xhr_header, status=200)
+ result = json.loads(response.body)
+ values = [suggestion['value'] for suggestion in result['suggestions']]
+ assert user_group_name in values
+
+ response = self.app.get(
+ route_path('user_group_autocomplete_data',
+ params=dict(active='1')),
+ extra_environ=xhr_header, status=200)
+ result = json.loads(response.body)
+ values = [suggestion['value'] for suggestion in result['suggestions']]
+ assert user_group_name not in values
+
+ @pytest.mark.parametrize('query, count', [
+ ('hello1', 0),
+ ('dev', 1),
+ ])
+ def test_result_is_limited_when_query_is_sent(self, user_util, xhr_header, query, count):
+ self.log_user()
+
+ user_util._test_name = 'dev-test'
+ user_util.create_user_group()
+
+ response = self.app.get(
+ route_path('user_group_autocomplete_data',
+ params=dict(user_groups='true',
+ query=query)),
+ extra_environ=xhr_header, status=200)
+
+ result = json.loads(response.body)
+
+ assert len(result['suggestions']) == count
diff --git a/rhodecode/apps/home/views.py b/rhodecode/apps/home/views.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/apps/home/views.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2016-2017 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 logging
+
+from pyramid.view import view_config
+
+from rhodecode.apps._base import BaseAppView
+from rhodecode.lib.auth import LoginRequired, NotAnonymous
+from rhodecode.lib.utils2 import str2bool
+from rhodecode.model.repo import RepoModel
+
+log = logging.getLogger(__name__)
+
+
+class HomeView(BaseAppView):
+
+ def load_default_context(self):
+ c = self._get_local_tmpl_context()
+ c.user = c.auth_user.get_instance()
+ self._register_global_c(c)
+ return c
+
+ @LoginRequired()
+ @view_config(
+ route_name='user_autocomplete_data', request_method='GET',
+ renderer='json_ext', xhr=True)
+ def user_autocomplete_data(self):
+ query = self.request.GET.get('query')
+ active = str2bool(self.request.GET.get('active') or True)
+ include_groups = str2bool(self.request.GET.get('user_groups'))
+
+ log.debug('generating user list, query:%s, active:%s, with_groups:%s',
+ query, active, include_groups)
+
+ repo_model = RepoModel()
+ _users = repo_model.get_users(
+ name_contains=query, only_active=active)
+
+ if include_groups:
+ # extend with user groups
+ _user_groups = repo_model.get_user_groups(
+ name_contains=query, only_active=active)
+ _users = _users + _user_groups
+
+ return {'suggestions': _users}
+
+ @LoginRequired()
+ @NotAnonymous()
+ @view_config(
+ route_name='user_group_autocomplete_data', request_method='GET',
+ renderer='json_ext', xhr=True)
+ def user_group_autocomplete_data(self):
+ query = self.request.GET.get('query')
+ active = str2bool(self.request.GET.get('active') or True)
+ log.debug('generating user group list, query:%s, active:%s',
+ query, active)
+
+ repo_model = RepoModel()
+ _user_groups = repo_model.get_user_groups(
+ name_contains=query, only_active=active)
+ _user_groups = _user_groups
+
+ return {'suggestions': _user_groups}
diff --git a/rhodecode/config/middleware.py b/rhodecode/config/middleware.py
--- a/rhodecode/config/middleware.py
+++ b/rhodecode/config/middleware.py
@@ -288,6 +288,7 @@ def includeme(config):
config.include('rhodecode.apps.admin')
config.include('rhodecode.apps.channelstream')
config.include('rhodecode.apps.login')
+ config.include('rhodecode.apps.home')
config.include('rhodecode.apps.repository')
config.include('rhodecode.apps.user_profile')
config.include('rhodecode.apps.my_account')
diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py
--- a/rhodecode/config/routing.py
+++ b/rhodecode/config/routing.py
@@ -193,11 +193,6 @@ def make_map(config):
rmap.connect('repo_list_data', '/_repos', controller='home',
action='repo_list_data')
- rmap.connect('user_autocomplete_data', '/_users', controller='home',
- action='user_autocomplete_data', jsroute=True)
- rmap.connect('user_group_autocomplete_data', '/_user_groups', controller='home',
- action='user_group_autocomplete_data', jsroute=True)
-
# TODO: johbo: Static links, to be replaced by our redirection mechanism
rmap.connect('rst_help',
'http://docutils.sourceforge.net/docs/user/rst/quickref.html',
diff --git a/rhodecode/controllers/home.py b/rhodecode/controllers/home.py
--- a/rhodecode/controllers/home.py
+++ b/rhodecode/controllers/home.py
@@ -255,36 +255,3 @@ class HomeController(BaseController):
'results': res
}
return data
-
- @LoginRequired()
- @XHRRequired()
- @jsonify
- def user_autocomplete_data(self):
- query = request.GET.get('query')
- active = str2bool(request.GET.get('active') or True)
-
- repo_model = RepoModel()
- _users = repo_model.get_users(
- name_contains=query, only_active=active)
-
- if request.GET.get('user_groups'):
- # extend with user groups
- _user_groups = repo_model.get_user_groups(
- name_contains=query, only_active=active)
- _users = _users + _user_groups
-
- return {'suggestions': _users}
-
- @LoginRequired()
- @XHRRequired()
- @jsonify
- def user_group_autocomplete_data(self):
- query = request.GET.get('query')
- active = str2bool(request.GET.get('active') or True)
-
- repo_model = RepoModel()
- _user_groups = repo_model.get_user_groups(
- name_contains=query, only_active=active)
- _user_groups = _user_groups
-
- return {'suggestions': _user_groups}
diff --git a/rhodecode/tests/fixture.py b/rhodecode/tests/fixture.py
--- a/rhodecode/tests/fixture.py
+++ b/rhodecode/tests/fixture.py
@@ -286,6 +286,10 @@ class Fixture(object):
gr = UserGroup.get_by_group_name(group_name=name)
if gr:
return gr
+ # map active flag to the real attribute. For API consistency of fixtures
+ if 'active' in kwargs:
+ kwargs['users_group_active'] = kwargs['active']
+ del kwargs['active']
form_data = self._get_user_group_create_params(name, **kwargs)
owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
user_group = UserGroupModel().create(
diff --git a/rhodecode/tests/functional/test_home.py b/rhodecode/tests/functional/test_home.py
--- a/rhodecode/tests/functional/test_home.py
+++ b/rhodecode/tests/functional/test_home.py
@@ -132,77 +132,6 @@ class TestHomeController(TestController)
response.mustcontain(no=[version_string])
-class TestUserAutocompleteData(TestController):
- def test_returns_list_of_users(self, user_util):
- self.log_user()
- user = user_util.create_user(is_active=True)
- user_name = user.username
- response = self.app.get(
- url(controller='home', action='user_autocomplete_data'),
- headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
- result = json.loads(response.body)
- values = [suggestion['value'] for suggestion in result['suggestions']]
- assert user_name in values
-
- def test_returns_inactive_users_when_active_flag_sent(self, user_util):
- self.log_user()
- user = user_util.create_user(is_active=False)
- user_name = user.username
- response = self.app.get(
- url(controller='home', action='user_autocomplete_data',
- user_groups='true', active='0'),
- headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
- result = json.loads(response.body)
- values = [suggestion['value'] for suggestion in result['suggestions']]
- assert user_name in values
-
- def test_returns_groups_when_user_groups_sent(self, user_util):
- self.log_user()
- group = user_util.create_user_group(user_groups_active=True)
- group_name = group.users_group_name
- response = self.app.get(
- url(controller='home', action='user_autocomplete_data',
- user_groups='true'),
- headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
- result = json.loads(response.body)
- values = [suggestion['value'] for suggestion in result['suggestions']]
- assert group_name in values
-
- def test_result_is_limited_when_query_is_sent(self):
- self.log_user()
- fake_result = [
- {
- 'first_name': 'John',
- 'value_display': 'hello{} (John Smith)'.format(i),
- 'icon_link': '/images/user14.png',
- 'value': 'hello{}'.format(i),
- 'last_name': 'Smith',
- 'username': 'hello{}'.format(i),
- 'id': i,
- 'value_type': u'user'
- }
- for i in range(10)
- ]
- users_patcher = patch.object(
- RepoModel, 'get_users', return_value=fake_result)
- groups_patcher = patch.object(
- RepoModel, 'get_user_groups', return_value=fake_result)
-
- query = 'hello'
- with users_patcher as users_mock, groups_patcher as groups_mock:
- response = self.app.get(
- url(controller='home', action='user_autocomplete_data',
- user_groups='true', query=query),
- headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
-
- result = json.loads(response.body)
- users_mock.assert_called_once_with(
- name_contains=query, only_active=True)
- groups_mock.assert_called_once_with(
- name_contains=query, only_active=True)
- assert len(result['suggestions']) == 20
-
-
def assert_and_get_content(result):
repos = []
groups = []