##// END OF EJS Templates
core: moved users and user groups autocomplete into pyramid....
marcink -
r1666:80369ba7 default
parent child Browse files
Show More
@@ -0,0 +1,33 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 def includeme(config):
23
24 config.add_route(
25 name='user_autocomplete_data',
26 pattern='/_users')
27
28 config.add_route(
29 name='user_group_autocomplete_data',
30 pattern='/_user_groups')
31
32 # Scan module for configuration decorators.
33 config.scan()
@@ -0,0 +1,19 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
@@ -0,0 +1,112 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import json
22 import pytest
23
24 from rhodecode.tests import TestController
25 from rhodecode.tests.fixture import Fixture
26
27
28 fixture = Fixture()
29
30
31 def route_path(name, params=None, **kwargs):
32 import urllib
33
34 base_url = {
35 'user_autocomplete_data': '/_users',
36 'user_group_autocomplete_data': '/_user_groups'
37 }[name].format(**kwargs)
38
39 if params:
40 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
41 return base_url
42
43
44 class TestUserAutocompleteData(TestController):
45
46 def test_returns_list_of_users(self, user_util, xhr_header):
47 self.log_user()
48 user = user_util.create_user(active=True)
49 user_name = user.username
50 response = self.app.get(
51 route_path('user_autocomplete_data'),
52 extra_environ=xhr_header, status=200)
53 result = json.loads(response.body)
54 values = [suggestion['value'] for suggestion in result['suggestions']]
55 assert user_name in values
56
57 def test_returns_inactive_users_when_active_flag_sent(
58 self, user_util, xhr_header):
59 self.log_user()
60 user = user_util.create_user(active=False)
61 user_name = user.username
62
63 response = self.app.get(
64 route_path('user_autocomplete_data',
65 params=dict(user_groups='true', active='0')),
66 extra_environ=xhr_header, status=200)
67 result = json.loads(response.body)
68 values = [suggestion['value'] for suggestion in result['suggestions']]
69 assert user_name in values
70
71 response = self.app.get(
72 route_path('user_autocomplete_data',
73 params=dict(user_groups='true', active='1')),
74 extra_environ=xhr_header, status=200)
75 result = json.loads(response.body)
76 values = [suggestion['value'] for suggestion in result['suggestions']]
77 assert user_name not in values
78
79 def test_returns_groups_when_user_groups_flag_sent(
80 self, user_util, xhr_header):
81 self.log_user()
82 group = user_util.create_user_group(user_groups_active=True)
83 group_name = group.users_group_name
84 response = self.app.get(
85 route_path('user_autocomplete_data',
86 params=dict(user_groups='true')),
87 extra_environ=xhr_header, status=200)
88 result = json.loads(response.body)
89 values = [suggestion['value'] for suggestion in result['suggestions']]
90 assert group_name in values
91
92 @pytest.mark.parametrize('query, count', [
93 ('hello1', 0),
94 ('dev', 2),
95 ])
96 def test_result_is_limited_when_query_is_sent(self, user_util, xhr_header,
97 query, count):
98 self.log_user()
99
100 user_util._test_name = 'dev-test'
101 user_util.create_user()
102
103 user_util._test_name = 'dev-group-test'
104 user_util.create_user_group()
105
106 response = self.app.get(
107 route_path('user_autocomplete_data',
108 params=dict(user_groups='true', query=query)),
109 extra_environ=xhr_header, status=200)
110
111 result = json.loads(response.body)
112 assert len(result['suggestions']) == count
@@ -0,0 +1,117 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 # -*- coding: utf-8 -*-
21
22 # Copyright (C) 2016-2017 RhodeCode GmbH
23 #
24 # This program is free software: you can redistribute it and/or modify
25 # it under the terms of the GNU Affero General Public License, version 3
26 # (only), as published by the Free Software Foundation.
27 #
28 # This program is distributed in the hope that it will be useful,
29 # but WITHOUT ANY WARRANTY; without even the implied warranty of
30 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 # GNU General Public License for more details.
32 #
33 # You should have received a copy of the GNU Affero General Public License
34 # along with this program. If not, see <http://www.gnu.org/licenses/>.
35 #
36 # This program is dual-licensed. If you wish to learn more about the
37 # RhodeCode Enterprise Edition, including its added features, Support services,
38 # and proprietary license terms, please see https://rhodecode.com/licenses/
39
40 import json
41
42 import pytest
43
44 from rhodecode.tests import TestController
45 from rhodecode.tests.fixture import Fixture
46
47
48 fixture = Fixture()
49
50
51 def route_path(name, params=None, **kwargs):
52 import urllib
53
54 base_url = {
55 'user_autocomplete_data': '/_users',
56 'user_group_autocomplete_data': '/_user_groups'
57 }[name].format(**kwargs)
58
59 if params:
60 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
61 return base_url
62
63
64 class TestUserGroupAutocompleteData(TestController):
65
66 def test_returns_list_of_user_groups(self, user_util, xhr_header):
67 self.log_user()
68 user_group = user_util.create_user_group(active=True)
69 user_group_name = user_group.users_group_name
70 response = self.app.get(
71 route_path('user_group_autocomplete_data'),
72 extra_environ=xhr_header, status=200)
73 result = json.loads(response.body)
74 values = [suggestion['value'] for suggestion in result['suggestions']]
75 assert user_group_name in values
76
77 def test_returns_inactive_user_groups_when_active_flag_sent(
78 self, user_util, xhr_header):
79 self.log_user()
80 user_group = user_util.create_user_group(active=False)
81 user_group_name = user_group.users_group_name
82
83 response = self.app.get(
84 route_path('user_group_autocomplete_data',
85 params=dict(active='0')),
86 extra_environ=xhr_header, status=200)
87 result = json.loads(response.body)
88 values = [suggestion['value'] for suggestion in result['suggestions']]
89 assert user_group_name in values
90
91 response = self.app.get(
92 route_path('user_group_autocomplete_data',
93 params=dict(active='1')),
94 extra_environ=xhr_header, status=200)
95 result = json.loads(response.body)
96 values = [suggestion['value'] for suggestion in result['suggestions']]
97 assert user_group_name not in values
98
99 @pytest.mark.parametrize('query, count', [
100 ('hello1', 0),
101 ('dev', 1),
102 ])
103 def test_result_is_limited_when_query_is_sent(self, user_util, xhr_header, query, count):
104 self.log_user()
105
106 user_util._test_name = 'dev-test'
107 user_util.create_user_group()
108
109 response = self.app.get(
110 route_path('user_group_autocomplete_data',
111 params=dict(user_groups='true',
112 query=query)),
113 extra_environ=xhr_header, status=200)
114
115 result = json.loads(response.body)
116
117 assert len(result['suggestions']) == count
@@ -0,0 +1,81 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import logging
22
23 from pyramid.view import view_config
24
25 from rhodecode.apps._base import BaseAppView
26 from rhodecode.lib.auth import LoginRequired, NotAnonymous
27 from rhodecode.lib.utils2 import str2bool
28 from rhodecode.model.repo import RepoModel
29
30 log = logging.getLogger(__name__)
31
32
33 class HomeView(BaseAppView):
34
35 def load_default_context(self):
36 c = self._get_local_tmpl_context()
37 c.user = c.auth_user.get_instance()
38 self._register_global_c(c)
39 return c
40
41 @LoginRequired()
42 @view_config(
43 route_name='user_autocomplete_data', request_method='GET',
44 renderer='json_ext', xhr=True)
45 def user_autocomplete_data(self):
46 query = self.request.GET.get('query')
47 active = str2bool(self.request.GET.get('active') or True)
48 include_groups = str2bool(self.request.GET.get('user_groups'))
49
50 log.debug('generating user list, query:%s, active:%s, with_groups:%s',
51 query, active, include_groups)
52
53 repo_model = RepoModel()
54 _users = repo_model.get_users(
55 name_contains=query, only_active=active)
56
57 if include_groups:
58 # extend with user groups
59 _user_groups = repo_model.get_user_groups(
60 name_contains=query, only_active=active)
61 _users = _users + _user_groups
62
63 return {'suggestions': _users}
64
65 @LoginRequired()
66 @NotAnonymous()
67 @view_config(
68 route_name='user_group_autocomplete_data', request_method='GET',
69 renderer='json_ext', xhr=True)
70 def user_group_autocomplete_data(self):
71 query = self.request.GET.get('query')
72 active = str2bool(self.request.GET.get('active') or True)
73 log.debug('generating user group list, query:%s, active:%s',
74 query, active)
75
76 repo_model = RepoModel()
77 _user_groups = repo_model.get_user_groups(
78 name_contains=query, only_active=active)
79 _user_groups = _user_groups
80
81 return {'suggestions': _user_groups}
@@ -288,6 +288,7 b' def includeme(config):'
288 config.include('rhodecode.apps.admin')
288 config.include('rhodecode.apps.admin')
289 config.include('rhodecode.apps.channelstream')
289 config.include('rhodecode.apps.channelstream')
290 config.include('rhodecode.apps.login')
290 config.include('rhodecode.apps.login')
291 config.include('rhodecode.apps.home')
291 config.include('rhodecode.apps.repository')
292 config.include('rhodecode.apps.repository')
292 config.include('rhodecode.apps.user_profile')
293 config.include('rhodecode.apps.user_profile')
293 config.include('rhodecode.apps.my_account')
294 config.include('rhodecode.apps.my_account')
@@ -193,11 +193,6 b' def make_map(config):'
193 rmap.connect('repo_list_data', '/_repos', controller='home',
193 rmap.connect('repo_list_data', '/_repos', controller='home',
194 action='repo_list_data')
194 action='repo_list_data')
195
195
196 rmap.connect('user_autocomplete_data', '/_users', controller='home',
197 action='user_autocomplete_data', jsroute=True)
198 rmap.connect('user_group_autocomplete_data', '/_user_groups', controller='home',
199 action='user_group_autocomplete_data', jsroute=True)
200
201 # TODO: johbo: Static links, to be replaced by our redirection mechanism
196 # TODO: johbo: Static links, to be replaced by our redirection mechanism
202 rmap.connect('rst_help',
197 rmap.connect('rst_help',
203 'http://docutils.sourceforge.net/docs/user/rst/quickref.html',
198 'http://docutils.sourceforge.net/docs/user/rst/quickref.html',
@@ -255,36 +255,3 b' class HomeController(BaseController):'
255 'results': res
255 'results': res
256 }
256 }
257 return data
257 return data
258
259 @LoginRequired()
260 @XHRRequired()
261 @jsonify
262 def user_autocomplete_data(self):
263 query = request.GET.get('query')
264 active = str2bool(request.GET.get('active') or True)
265
266 repo_model = RepoModel()
267 _users = repo_model.get_users(
268 name_contains=query, only_active=active)
269
270 if request.GET.get('user_groups'):
271 # extend with user groups
272 _user_groups = repo_model.get_user_groups(
273 name_contains=query, only_active=active)
274 _users = _users + _user_groups
275
276 return {'suggestions': _users}
277
278 @LoginRequired()
279 @XHRRequired()
280 @jsonify
281 def user_group_autocomplete_data(self):
282 query = request.GET.get('query')
283 active = str2bool(request.GET.get('active') or True)
284
285 repo_model = RepoModel()
286 _user_groups = repo_model.get_user_groups(
287 name_contains=query, only_active=active)
288 _user_groups = _user_groups
289
290 return {'suggestions': _user_groups}
@@ -286,6 +286,10 b' class Fixture(object):'
286 gr = UserGroup.get_by_group_name(group_name=name)
286 gr = UserGroup.get_by_group_name(group_name=name)
287 if gr:
287 if gr:
288 return gr
288 return gr
289 # map active flag to the real attribute. For API consistency of fixtures
290 if 'active' in kwargs:
291 kwargs['users_group_active'] = kwargs['active']
292 del kwargs['active']
289 form_data = self._get_user_group_create_params(name, **kwargs)
293 form_data = self._get_user_group_create_params(name, **kwargs)
290 owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
294 owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
291 user_group = UserGroupModel().create(
295 user_group = UserGroupModel().create(
@@ -132,77 +132,6 b' class TestHomeController(TestController)'
132 response.mustcontain(no=[version_string])
132 response.mustcontain(no=[version_string])
133
133
134
134
135 class TestUserAutocompleteData(TestController):
136 def test_returns_list_of_users(self, user_util):
137 self.log_user()
138 user = user_util.create_user(is_active=True)
139 user_name = user.username
140 response = self.app.get(
141 url(controller='home', action='user_autocomplete_data'),
142 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
143 result = json.loads(response.body)
144 values = [suggestion['value'] for suggestion in result['suggestions']]
145 assert user_name in values
146
147 def test_returns_inactive_users_when_active_flag_sent(self, user_util):
148 self.log_user()
149 user = user_util.create_user(is_active=False)
150 user_name = user.username
151 response = self.app.get(
152 url(controller='home', action='user_autocomplete_data',
153 user_groups='true', active='0'),
154 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
155 result = json.loads(response.body)
156 values = [suggestion['value'] for suggestion in result['suggestions']]
157 assert user_name in values
158
159 def test_returns_groups_when_user_groups_sent(self, user_util):
160 self.log_user()
161 group = user_util.create_user_group(user_groups_active=True)
162 group_name = group.users_group_name
163 response = self.app.get(
164 url(controller='home', action='user_autocomplete_data',
165 user_groups='true'),
166 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
167 result = json.loads(response.body)
168 values = [suggestion['value'] for suggestion in result['suggestions']]
169 assert group_name in values
170
171 def test_result_is_limited_when_query_is_sent(self):
172 self.log_user()
173 fake_result = [
174 {
175 'first_name': 'John',
176 'value_display': 'hello{} (John Smith)'.format(i),
177 'icon_link': '/images/user14.png',
178 'value': 'hello{}'.format(i),
179 'last_name': 'Smith',
180 'username': 'hello{}'.format(i),
181 'id': i,
182 'value_type': u'user'
183 }
184 for i in range(10)
185 ]
186 users_patcher = patch.object(
187 RepoModel, 'get_users', return_value=fake_result)
188 groups_patcher = patch.object(
189 RepoModel, 'get_user_groups', return_value=fake_result)
190
191 query = 'hello'
192 with users_patcher as users_mock, groups_patcher as groups_mock:
193 response = self.app.get(
194 url(controller='home', action='user_autocomplete_data',
195 user_groups='true', query=query),
196 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
197
198 result = json.loads(response.body)
199 users_mock.assert_called_once_with(
200 name_contains=query, only_active=True)
201 groups_mock.assert_called_once_with(
202 name_contains=query, only_active=True)
203 assert len(result['suggestions']) == 20
204
205
206 def assert_and_get_content(result):
135 def assert_and_get_content(result):
207 repos = []
136 repos = []
208 groups = []
137 groups = []
General Comments 0
You need to be logged in to leave comments. Login now