##// END OF EJS Templates
autocomplete: allow to pass in a GET flag to control if non-active users should be returned in...
marcink -
r226:6371ca5e default
parent child Browse files
Show More
@@ -1,284 +1,289 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Home controller for RhodeCode Enterprise
22 Home controller for RhodeCode Enterprise
23 """
23 """
24
24
25 import logging
25 import logging
26 import time
26 import time
27 import re
27 import re
28
28
29 from pylons import tmpl_context as c, request, url, config
29 from pylons import tmpl_context as c, request, url, config
30 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
31 from sqlalchemy.sql import func
31 from sqlalchemy.sql import func
32
32
33 from rhodecode.lib.auth import (
33 from rhodecode.lib.auth import (
34 LoginRequired, HasPermissionAllDecorator, AuthUser,
34 LoginRequired, HasPermissionAllDecorator, AuthUser,
35 HasRepoGroupPermissionAnyDecorator, XHRRequired)
35 HasRepoGroupPermissionAnyDecorator, XHRRequired)
36 from rhodecode.lib.base import BaseController, render
36 from rhodecode.lib.base import BaseController, render
37 from rhodecode.lib.index import searcher_from_config
37 from rhodecode.lib.index import searcher_from_config
38 from rhodecode.lib.ext_json import json
38 from rhodecode.lib.ext_json import json
39 from rhodecode.lib.utils import jsonify
39 from rhodecode.lib.utils import jsonify
40 from rhodecode.lib.utils2 import safe_unicode
40 from rhodecode.lib.utils2 import safe_unicode, str2bool
41 from rhodecode.model.db import Repository, RepoGroup
41 from rhodecode.model.db import Repository, RepoGroup
42 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.repo import RepoModel
43 from rhodecode.model.repo_group import RepoGroupModel
43 from rhodecode.model.repo_group import RepoGroupModel
44 from rhodecode.model.scm import RepoList, RepoGroupList
44 from rhodecode.model.scm import RepoList, RepoGroupList
45
45
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49
49
50 class HomeController(BaseController):
50 class HomeController(BaseController):
51 def __before__(self):
51 def __before__(self):
52 super(HomeController, self).__before__()
52 super(HomeController, self).__before__()
53
53
54 def ping(self):
54 def ping(self):
55 """
55 """
56 Ping, doesn't require login, good for checking out the platform
56 Ping, doesn't require login, good for checking out the platform
57 """
57 """
58 instance_id = getattr(c, 'rhodecode_instanceid', '')
58 instance_id = getattr(c, 'rhodecode_instanceid', '')
59 return 'pong[%s] => %s' % (instance_id, self.ip_addr,)
59 return 'pong[%s] => %s' % (instance_id, self.ip_addr,)
60
60
61 @LoginRequired()
61 @LoginRequired()
62 @HasPermissionAllDecorator('hg.admin')
62 @HasPermissionAllDecorator('hg.admin')
63 def error_test(self):
63 def error_test(self):
64 """
64 """
65 Test exception handling and emails on errors
65 Test exception handling and emails on errors
66 """
66 """
67 class TestException(Exception):
67 class TestException(Exception):
68 pass
68 pass
69
69
70 msg = ('RhodeCode Enterprise %s test exception. Generation time: %s'
70 msg = ('RhodeCode Enterprise %s test exception. Generation time: %s'
71 % (c.rhodecode_name, time.time()))
71 % (c.rhodecode_name, time.time()))
72 raise TestException(msg)
72 raise TestException(msg)
73
73
74 def _get_groups_and_repos(self, repo_group_id=None):
74 def _get_groups_and_repos(self, repo_group_id=None):
75 # repo groups groups
75 # repo groups groups
76 repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
76 repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
77 _perms = ['group.read', 'group.write', 'group.admin']
77 _perms = ['group.read', 'group.write', 'group.admin']
78 repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
78 repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
79 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
79 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
80 repo_group_list=repo_group_list_acl, admin=False)
80 repo_group_list=repo_group_list_acl, admin=False)
81
81
82 # repositories
82 # repositories
83 repo_list = Repository.get_all_repos(group_id=repo_group_id)
83 repo_list = Repository.get_all_repos(group_id=repo_group_id)
84 _perms = ['repository.read', 'repository.write', 'repository.admin']
84 _perms = ['repository.read', 'repository.write', 'repository.admin']
85 repo_list_acl = RepoList(repo_list, perm_set=_perms)
85 repo_list_acl = RepoList(repo_list, perm_set=_perms)
86 repo_data = RepoModel().get_repos_as_dict(
86 repo_data = RepoModel().get_repos_as_dict(
87 repo_list=repo_list_acl, admin=False)
87 repo_list=repo_list_acl, admin=False)
88
88
89 return repo_data, repo_group_data
89 return repo_data, repo_group_data
90
90
91 @LoginRequired()
91 @LoginRequired()
92 def index(self):
92 def index(self):
93 c.repo_group = None
93 c.repo_group = None
94
94
95 repo_data, repo_group_data = self._get_groups_and_repos()
95 repo_data, repo_group_data = self._get_groups_and_repos()
96 # json used to render the grids
96 # json used to render the grids
97 c.repos_data = json.dumps(repo_data)
97 c.repos_data = json.dumps(repo_data)
98 c.repo_groups_data = json.dumps(repo_group_data)
98 c.repo_groups_data = json.dumps(repo_group_data)
99
99
100 return render('/index.html')
100 return render('/index.html')
101
101
102 @LoginRequired()
102 @LoginRequired()
103 @HasRepoGroupPermissionAnyDecorator('group.read', 'group.write',
103 @HasRepoGroupPermissionAnyDecorator('group.read', 'group.write',
104 'group.admin')
104 'group.admin')
105 def index_repo_group(self, group_name):
105 def index_repo_group(self, group_name):
106 """GET /repo_group_name: Show a specific item"""
106 """GET /repo_group_name: Show a specific item"""
107 c.repo_group = RepoGroupModel()._get_repo_group(group_name)
107 c.repo_group = RepoGroupModel()._get_repo_group(group_name)
108 repo_data, repo_group_data = self._get_groups_and_repos(
108 repo_data, repo_group_data = self._get_groups_and_repos(
109 c.repo_group.group_id)
109 c.repo_group.group_id)
110
110
111 # json used to render the grids
111 # json used to render the grids
112 c.repos_data = json.dumps(repo_data)
112 c.repos_data = json.dumps(repo_data)
113 c.repo_groups_data = json.dumps(repo_group_data)
113 c.repo_groups_data = json.dumps(repo_group_data)
114
114
115 return render('index_repo_group.html')
115 return render('index_repo_group.html')
116
116
117 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
117 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
118 query = Repository.query()\
118 query = Repository.query()\
119 .order_by(func.length(Repository.repo_name))\
119 .order_by(func.length(Repository.repo_name))\
120 .order_by(Repository.repo_name)
120 .order_by(Repository.repo_name)
121
121
122 if repo_type:
122 if repo_type:
123 query = query.filter(Repository.repo_type == repo_type)
123 query = query.filter(Repository.repo_type == repo_type)
124
124
125 if name_contains:
125 if name_contains:
126 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
126 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
127 query = query.filter(
127 query = query.filter(
128 Repository.repo_name.ilike(ilike_expression))
128 Repository.repo_name.ilike(ilike_expression))
129 query = query.limit(limit)
129 query = query.limit(limit)
130
130
131 all_repos = query.all()
131 all_repos = query.all()
132 repo_iter = self.scm_model.get_repos(all_repos)
132 repo_iter = self.scm_model.get_repos(all_repos)
133 return [
133 return [
134 {
134 {
135 'id': obj['name'],
135 'id': obj['name'],
136 'text': obj['name'],
136 'text': obj['name'],
137 'type': 'repo',
137 'type': 'repo',
138 'obj': obj['dbrepo'],
138 'obj': obj['dbrepo'],
139 'url': url('summary_home', repo_name=obj['name'])
139 'url': url('summary_home', repo_name=obj['name'])
140 }
140 }
141 for obj in repo_iter]
141 for obj in repo_iter]
142
142
143 def _get_repo_group_list(self, name_contains=None, limit=20):
143 def _get_repo_group_list(self, name_contains=None, limit=20):
144 query = RepoGroup.query()\
144 query = RepoGroup.query()\
145 .order_by(func.length(RepoGroup.group_name))\
145 .order_by(func.length(RepoGroup.group_name))\
146 .order_by(RepoGroup.group_name)
146 .order_by(RepoGroup.group_name)
147
147
148 if name_contains:
148 if name_contains:
149 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
149 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
150 query = query.filter(
150 query = query.filter(
151 RepoGroup.group_name.ilike(ilike_expression))
151 RepoGroup.group_name.ilike(ilike_expression))
152 query = query.limit(limit)
152 query = query.limit(limit)
153
153
154 all_groups = query.all()
154 all_groups = query.all()
155 repo_groups_iter = self.scm_model.get_repo_groups(all_groups)
155 repo_groups_iter = self.scm_model.get_repo_groups(all_groups)
156 return [
156 return [
157 {
157 {
158 'id': obj.group_name,
158 'id': obj.group_name,
159 'text': obj.group_name,
159 'text': obj.group_name,
160 'type': 'group',
160 'type': 'group',
161 'obj': {},
161 'obj': {},
162 'url': url('repo_group_home', group_name=obj.group_name)
162 'url': url('repo_group_home', group_name=obj.group_name)
163 }
163 }
164 for obj in repo_groups_iter]
164 for obj in repo_groups_iter]
165
165
166 def _get_hash_commit_list(self, hash_starts_with=None, limit=20):
166 def _get_hash_commit_list(self, hash_starts_with=None, limit=20):
167 if not hash_starts_with or len(hash_starts_with) < 3:
167 if not hash_starts_with or len(hash_starts_with) < 3:
168 return []
168 return []
169
169
170 commit_hashes = re.compile('([0-9a-f]{2,40})').findall(hash_starts_with)
170 commit_hashes = re.compile('([0-9a-f]{2,40})').findall(hash_starts_with)
171
171
172 if len(commit_hashes) != 1:
172 if len(commit_hashes) != 1:
173 return []
173 return []
174
174
175 commit_hash_prefix = commit_hashes[0]
175 commit_hash_prefix = commit_hashes[0]
176
176
177 auth_user = AuthUser(
177 auth_user = AuthUser(
178 user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
178 user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
179 searcher = searcher_from_config(config)
179 searcher = searcher_from_config(config)
180 result = searcher.search(
180 result = searcher.search(
181 'commit_id:%s*' % commit_hash_prefix, 'commit', auth_user)
181 'commit_id:%s*' % commit_hash_prefix, 'commit', auth_user)
182
182
183 return [
183 return [
184 {
184 {
185 'id': entry['commit_id'],
185 'id': entry['commit_id'],
186 'text': entry['commit_id'],
186 'text': entry['commit_id'],
187 'type': 'commit',
187 'type': 'commit',
188 'obj': {'repo': entry['repository']},
188 'obj': {'repo': entry['repository']},
189 'url': url('changeset_home',
189 'url': url('changeset_home',
190 repo_name=entry['repository'], revision=entry['commit_id'])
190 repo_name=entry['repository'], revision=entry['commit_id'])
191 }
191 }
192 for entry in result['results']]
192 for entry in result['results']]
193
193
194 @LoginRequired()
194 @LoginRequired()
195 @XHRRequired()
195 @XHRRequired()
196 @jsonify
196 @jsonify
197 def goto_switcher_data(self):
197 def goto_switcher_data(self):
198 query = request.GET.get('query')
198 query = request.GET.get('query')
199 log.debug('generating goto switcher list, query %s', query)
199 log.debug('generating goto switcher list, query %s', query)
200
200
201 res = []
201 res = []
202 repo_groups = self._get_repo_group_list(query)
202 repo_groups = self._get_repo_group_list(query)
203 if repo_groups:
203 if repo_groups:
204 res.append({
204 res.append({
205 'text': _('Groups'),
205 'text': _('Groups'),
206 'children': repo_groups
206 'children': repo_groups
207 })
207 })
208
208
209 repos = self._get_repo_list(query)
209 repos = self._get_repo_list(query)
210 if repos:
210 if repos:
211 res.append({
211 res.append({
212 'text': _('Repositories'),
212 'text': _('Repositories'),
213 'children': repos
213 'children': repos
214 })
214 })
215
215
216 commits = self._get_hash_commit_list(query)
216 commits = self._get_hash_commit_list(query)
217 if commits:
217 if commits:
218 unique_repos = {}
218 unique_repos = {}
219 for commit in commits:
219 for commit in commits:
220 unique_repos.setdefault(commit['obj']['repo'], []
220 unique_repos.setdefault(commit['obj']['repo'], []
221 ).append(commit)
221 ).append(commit)
222
222
223 for repo in unique_repos:
223 for repo in unique_repos:
224 res.append({
224 res.append({
225 'text': _('Commits in %(repo)s') % {'repo': repo},
225 'text': _('Commits in %(repo)s') % {'repo': repo},
226 'children': unique_repos[repo]
226 'children': unique_repos[repo]
227 })
227 })
228
228
229 data = {
229 data = {
230 'more': False,
230 'more': False,
231 'results': res
231 'results': res
232 }
232 }
233 return data
233 return data
234
234
235 @LoginRequired()
235 @LoginRequired()
236 @XHRRequired()
236 @XHRRequired()
237 @jsonify
237 @jsonify
238 def repo_list_data(self):
238 def repo_list_data(self):
239 query = request.GET.get('query')
239 query = request.GET.get('query')
240 repo_type = request.GET.get('repo_type')
240 repo_type = request.GET.get('repo_type')
241 log.debug('generating repo list, query:%s', query)
241 log.debug('generating repo list, query:%s', query)
242
242
243 res = []
243 res = []
244 repos = self._get_repo_list(query, repo_type=repo_type)
244 repos = self._get_repo_list(query, repo_type=repo_type)
245 if repos:
245 if repos:
246 res.append({
246 res.append({
247 'text': _('Repositories'),
247 'text': _('Repositories'),
248 'children': repos
248 'children': repos
249 })
249 })
250
250
251 data = {
251 data = {
252 'more': False,
252 'more': False,
253 'results': res
253 'results': res
254 }
254 }
255 return data
255 return data
256
256
257 @LoginRequired()
257 @LoginRequired()
258 @XHRRequired()
258 @XHRRequired()
259 @jsonify
259 @jsonify
260 def user_autocomplete_data(self):
260 def user_autocomplete_data(self):
261 query = request.GET.get('query')
261 query = request.GET.get('query')
262 active = str2bool(request.GET.get('active') or True)
262
263
263 repo_model = RepoModel()
264 repo_model = RepoModel()
264 _users = repo_model.get_users(name_contains=query)
265 _users = repo_model.get_users(
266 name_contains=query, only_active=active)
265
267
266 if request.GET.get('user_groups'):
268 if request.GET.get('user_groups'):
267 # extend with user groups
269 # extend with user groups
268 _user_groups = repo_model.get_user_groups(name_contains=query)
270 _user_groups = repo_model.get_user_groups(
271 name_contains=query, only_active=active)
269 _users = _users + _user_groups
272 _users = _users + _user_groups
270
273
271 return {'suggestions': _users}
274 return {'suggestions': _users}
272
275
273 @LoginRequired()
276 @LoginRequired()
274 @XHRRequired()
277 @XHRRequired()
275 @jsonify
278 @jsonify
276 def user_group_autocomplete_data(self):
279 def user_group_autocomplete_data(self):
277 query = request.GET.get('query')
280 query = request.GET.get('query')
281 active = str2bool(request.GET.get('active') or True)
278
282
279 repo_model = RepoModel()
283 repo_model = RepoModel()
280 _user_groups = repo_model.get_user_groups(name_contains=query)
284 _user_groups = repo_model.get_user_groups(
285 name_contains=query, only_active=active)
281 _user_groups = _user_groups
286 _user_groups = _user_groups
282
287
283 return {'suggestions': _user_groups}
288 return {'suggestions': _user_groups}
284
289
@@ -1,365 +1,379 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import json
21 import json
22
22
23 from mock import patch
23 from mock import patch
24 import pytest
24 import pytest
25
25
26 import rhodecode
26 import rhodecode
27 from rhodecode.lib.utils import map_groups
27 from rhodecode.lib.utils import map_groups
28 from rhodecode.model.db import Repository, User, RepoGroup
28 from rhodecode.model.db import Repository, User, RepoGroup
29 from rhodecode.model.meta import Session
29 from rhodecode.model.meta import Session
30 from rhodecode.model.repo import RepoModel
30 from rhodecode.model.repo import RepoModel
31 from rhodecode.model.repo_group import RepoGroupModel
31 from rhodecode.model.repo_group import RepoGroupModel
32 from rhodecode.model.settings import SettingsModel
32 from rhodecode.model.settings import SettingsModel
33 from rhodecode.tests import TestController, url, TEST_USER_ADMIN_LOGIN
33 from rhodecode.tests import TestController, url, TEST_USER_ADMIN_LOGIN
34 from rhodecode.tests.fixture import Fixture
34 from rhodecode.tests.fixture import Fixture
35
35
36
36
37 fixture = Fixture()
37 fixture = Fixture()
38
38
39
39
40 class TestHomeController(TestController):
40 class TestHomeController(TestController):
41
41
42 def test_index(self):
42 def test_index(self):
43 self.log_user()
43 self.log_user()
44 response = self.app.get(url(controller='home', action='index'))
44 response = self.app.get(url(controller='home', action='index'))
45 # if global permission is set
45 # if global permission is set
46 response.mustcontain('Add Repository')
46 response.mustcontain('Add Repository')
47
47
48 # search for objects inside the JavaScript JSON
48 # search for objects inside the JavaScript JSON
49 for repo in Repository.getAll():
49 for repo in Repository.getAll():
50 response.mustcontain('"name_raw": "%s"' % repo.repo_name)
50 response.mustcontain('"name_raw": "%s"' % repo.repo_name)
51
51
52 def test_index_contains_backend_specific_details(self, backend):
52 def test_index_contains_backend_specific_details(self, backend):
53 self.log_user()
53 self.log_user()
54 response = self.app.get(url(controller='home', action='index'))
54 response = self.app.get(url(controller='home', action='index'))
55 tip = backend.repo.get_commit().raw_id
55 tip = backend.repo.get_commit().raw_id
56
56
57 # html in javascript variable:
57 # html in javascript variable:
58 response.mustcontain(r'<i class=\"icon-%s\"' % (backend.alias, ))
58 response.mustcontain(r'<i class=\"icon-%s\"' % (backend.alias, ))
59 response.mustcontain(r'href=\"/%s\"' % (backend.repo_name, ))
59 response.mustcontain(r'href=\"/%s\"' % (backend.repo_name, ))
60
60
61 response.mustcontain("""/%s/changeset/%s""" % (backend.repo_name, tip))
61 response.mustcontain("""/%s/changeset/%s""" % (backend.repo_name, tip))
62 response.mustcontain("""Added a symlink""")
62 response.mustcontain("""Added a symlink""")
63
63
64 def test_index_with_anonymous_access_disabled(self):
64 def test_index_with_anonymous_access_disabled(self):
65 with fixture.anon_access(False):
65 with fixture.anon_access(False):
66 response = self.app.get(url(controller='home', action='index'),
66 response = self.app.get(url(controller='home', action='index'),
67 status=302)
67 status=302)
68 assert 'login' in response.location
68 assert 'login' in response.location
69
69
70 def test_index_page_on_groups(self, autologin_user, repo_group):
70 def test_index_page_on_groups(self, autologin_user, repo_group):
71 response = self.app.get(url('repo_group_home', group_name='gr1'))
71 response = self.app.get(url('repo_group_home', group_name='gr1'))
72 response.mustcontain("gr1/repo_in_group")
72 response.mustcontain("gr1/repo_in_group")
73
73
74 def test_index_page_on_group_with_trailing_slash(
74 def test_index_page_on_group_with_trailing_slash(
75 self, autologin_user, repo_group):
75 self, autologin_user, repo_group):
76 response = self.app.get(url('repo_group_home', group_name='gr1') + '/')
76 response = self.app.get(url('repo_group_home', group_name='gr1') + '/')
77 response.mustcontain("gr1/repo_in_group")
77 response.mustcontain("gr1/repo_in_group")
78
78
79 @pytest.fixture(scope='class')
79 @pytest.fixture(scope='class')
80 def repo_group(self, request):
80 def repo_group(self, request):
81 gr = fixture.create_repo_group('gr1')
81 gr = fixture.create_repo_group('gr1')
82 fixture.create_repo(name='gr1/repo_in_group', repo_group=gr)
82 fixture.create_repo(name='gr1/repo_in_group', repo_group=gr)
83
83
84 @request.addfinalizer
84 @request.addfinalizer
85 def cleanup():
85 def cleanup():
86 RepoModel().delete('gr1/repo_in_group')
86 RepoModel().delete('gr1/repo_in_group')
87 RepoGroupModel().delete(repo_group='gr1', force_delete=True)
87 RepoGroupModel().delete(repo_group='gr1', force_delete=True)
88 Session().commit()
88 Session().commit()
89
89
90 def test_index_with_name_with_tags(self, autologin_user):
90 def test_index_with_name_with_tags(self, autologin_user):
91 user = User.get_by_username('test_admin')
91 user = User.get_by_username('test_admin')
92 user.name = '<img src="/image1" onload="alert(\'Hello, World!\');">'
92 user.name = '<img src="/image1" onload="alert(\'Hello, World!\');">'
93 user.lastname = (
93 user.lastname = (
94 '<img src="/image2" onload="alert(\'Hello, World!\');">')
94 '<img src="/image2" onload="alert(\'Hello, World!\');">')
95 Session().add(user)
95 Session().add(user)
96 Session().commit()
96 Session().commit()
97
97
98 response = self.app.get(url(controller='home', action='index'))
98 response = self.app.get(url(controller='home', action='index'))
99 response.mustcontain(
99 response.mustcontain(
100 '&lt;img src=&#34;/image1&#34; onload=&#34;'
100 '&lt;img src=&#34;/image1&#34; onload=&#34;'
101 'alert(&#39;Hello, World!&#39;);&#34;&gt;')
101 'alert(&#39;Hello, World!&#39;);&#34;&gt;')
102 response.mustcontain(
102 response.mustcontain(
103 '&lt;img src=&#34;/image2&#34; onload=&#34;'
103 '&lt;img src=&#34;/image2&#34; onload=&#34;'
104 'alert(&#39;Hello, World!&#39;);&#34;&gt;')
104 'alert(&#39;Hello, World!&#39;);&#34;&gt;')
105
105
106 @pytest.mark.parametrize("name, state", [
106 @pytest.mark.parametrize("name, state", [
107 ('Disabled', False),
107 ('Disabled', False),
108 ('Enabled', True),
108 ('Enabled', True),
109 ])
109 ])
110 def test_index_show_version(self, autologin_user, name, state):
110 def test_index_show_version(self, autologin_user, name, state):
111 version_string = 'RhodeCode Enterprise %s' % rhodecode.__version__
111 version_string = 'RhodeCode Enterprise %s' % rhodecode.__version__
112
112
113 show = SettingsModel().get_setting_by_name('show_version')
113 show = SettingsModel().get_setting_by_name('show_version')
114 show.app_settings_value = state
114 show.app_settings_value = state
115 Session().add(show)
115 Session().add(show)
116 Session().commit()
116 Session().commit()
117 response = self.app.get(url(controller='home', action='index'))
117 response = self.app.get(url(controller='home', action='index'))
118 if state is True:
118 if state is True:
119 response.mustcontain(version_string)
119 response.mustcontain(version_string)
120 if state is False:
120 if state is False:
121 response.mustcontain(no=[version_string])
121 response.mustcontain(no=[version_string])
122
122
123
123
124 class TestUserAutocompleteData(TestController):
124 class TestUserAutocompleteData(TestController):
125 def test_returns_list_of_users(self, user_util):
125 def test_returns_list_of_users(self, user_util):
126 self.log_user()
126 self.log_user()
127 user = user_util.create_user(is_active=True)
127 user = user_util.create_user(is_active=True)
128 user_name = user.username
128 user_name = user.username
129 response = self.app.get(
129 response = self.app.get(
130 url(controller='home', action='user_autocomplete_data'),
130 url(controller='home', action='user_autocomplete_data'),
131 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
131 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
132 result = json.loads(response.body)
132 result = json.loads(response.body)
133 values = [suggestion['value'] for suggestion in result['suggestions']]
133 values = [suggestion['value'] for suggestion in result['suggestions']]
134 assert user_name in values
134 assert user_name in values
135
135
136 def test_returns_inactive_users_when_active_flag_sent(self, user_util):
137 self.log_user()
138 user = user_util.create_user(is_active=False)
139 user_name = user.username
140 response = self.app.get(
141 url(controller='home', action='user_autocomplete_data',
142 user_groups='true', active='0'),
143 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
144 result = json.loads(response.body)
145 values = [suggestion['value'] for suggestion in result['suggestions']]
146 assert user_name in values
147
136 def test_returns_groups_when_user_groups_sent(self, user_util):
148 def test_returns_groups_when_user_groups_sent(self, user_util):
137 self.log_user()
149 self.log_user()
138 group = user_util.create_user_group(user_groups_active=True)
150 group = user_util.create_user_group(user_groups_active=True)
139 group_name = group.users_group_name
151 group_name = group.users_group_name
140 response = self.app.get(
152 response = self.app.get(
141 url(controller='home', action='user_autocomplete_data',
153 url(controller='home', action='user_autocomplete_data',
142 user_groups='true'),
154 user_groups='true'),
143 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
155 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
144 result = json.loads(response.body)
156 result = json.loads(response.body)
145 values = [suggestion['value'] for suggestion in result['suggestions']]
157 values = [suggestion['value'] for suggestion in result['suggestions']]
146 assert group_name in values
158 assert group_name in values
147
159
148 def test_result_is_limited_when_query_is_sent(self):
160 def test_result_is_limited_when_query_is_sent(self):
149 self.log_user()
161 self.log_user()
150 fake_result = [
162 fake_result = [
151 {
163 {
152 'first_name': 'John',
164 'first_name': 'John',
153 'value_display': 'hello{} (John Smith)'.format(i),
165 'value_display': 'hello{} (John Smith)'.format(i),
154 'icon_link': '/images/user14.png',
166 'icon_link': '/images/user14.png',
155 'value': 'hello{}'.format(i),
167 'value': 'hello{}'.format(i),
156 'last_name': 'Smith',
168 'last_name': 'Smith',
157 'username': 'hello{}'.format(i),
169 'username': 'hello{}'.format(i),
158 'id': i,
170 'id': i,
159 'value_type': u'user'
171 'value_type': u'user'
160 }
172 }
161 for i in range(10)
173 for i in range(10)
162 ]
174 ]
163 users_patcher = patch.object(
175 users_patcher = patch.object(
164 RepoModel, 'get_users', return_value=fake_result)
176 RepoModel, 'get_users', return_value=fake_result)
165 groups_patcher = patch.object(
177 groups_patcher = patch.object(
166 RepoModel, 'get_user_groups', return_value=fake_result)
178 RepoModel, 'get_user_groups', return_value=fake_result)
167
179
168 query = 'hello'
180 query = 'hello'
169 with users_patcher as users_mock, groups_patcher as groups_mock:
181 with users_patcher as users_mock, groups_patcher as groups_mock:
170 response = self.app.get(
182 response = self.app.get(
171 url(controller='home', action='user_autocomplete_data',
183 url(controller='home', action='user_autocomplete_data',
172 user_groups='true', query=query),
184 user_groups='true', query=query),
173 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
185 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
174
186
175 result = json.loads(response.body)
187 result = json.loads(response.body)
176 users_mock.assert_called_once_with(name_contains=query)
188 users_mock.assert_called_once_with(
177 groups_mock.assert_called_once_with(name_contains=query)
189 name_contains=query, only_active=True)
190 groups_mock.assert_called_once_with(
191 name_contains=query, only_active=True)
178 assert len(result['suggestions']) == 20
192 assert len(result['suggestions']) == 20
179
193
180
194
181 def assert_and_get_content(result):
195 def assert_and_get_content(result):
182 repos = []
196 repos = []
183 groups = []
197 groups = []
184 commits = []
198 commits = []
185 for data in result:
199 for data in result:
186 for data_item in data['children']:
200 for data_item in data['children']:
187 assert data_item['id']
201 assert data_item['id']
188 assert data_item['text']
202 assert data_item['text']
189 assert data_item['url']
203 assert data_item['url']
190 if data_item['type'] == 'repo':
204 if data_item['type'] == 'repo':
191 repos.append(data_item)
205 repos.append(data_item)
192 elif data_item['type'] == 'group':
206 elif data_item['type'] == 'group':
193 groups.append(data_item)
207 groups.append(data_item)
194 elif data_item['type'] == 'commit':
208 elif data_item['type'] == 'commit':
195 commits.append(data_item)
209 commits.append(data_item)
196 else:
210 else:
197 raise Exception('invalid type %s' % data_item['type'])
211 raise Exception('invalid type %s' % data_item['type'])
198
212
199 return repos, groups, commits
213 return repos, groups, commits
200
214
201
215
202 class TestGotoSwitcherData(TestController):
216 class TestGotoSwitcherData(TestController):
203 required_repos_with_groups = [
217 required_repos_with_groups = [
204 'abc',
218 'abc',
205 'abc-fork',
219 'abc-fork',
206 'forks/abcd',
220 'forks/abcd',
207 'abcd',
221 'abcd',
208 'abcde',
222 'abcde',
209 'a/abc',
223 'a/abc',
210 'aa/abc',
224 'aa/abc',
211 'aaa/abc',
225 'aaa/abc',
212 'aaaa/abc',
226 'aaaa/abc',
213 'repos_abc/aaa/abc',
227 'repos_abc/aaa/abc',
214 'abc_repos/abc',
228 'abc_repos/abc',
215 'abc_repos/abcd',
229 'abc_repos/abcd',
216 'xxx/xyz',
230 'xxx/xyz',
217 'forked-abc/a/abc'
231 'forked-abc/a/abc'
218 ]
232 ]
219
233
220 @pytest.fixture(autouse=True, scope='class')
234 @pytest.fixture(autouse=True, scope='class')
221 def prepare(self, request, pylonsapp):
235 def prepare(self, request, pylonsapp):
222 for repo_and_group in self.required_repos_with_groups:
236 for repo_and_group in self.required_repos_with_groups:
223 # create structure of groups and return the last group
237 # create structure of groups and return the last group
224
238
225 repo_group = map_groups(repo_and_group)
239 repo_group = map_groups(repo_and_group)
226
240
227 RepoModel()._create_repo(
241 RepoModel()._create_repo(
228 repo_and_group, 'hg', 'test-ac', TEST_USER_ADMIN_LOGIN,
242 repo_and_group, 'hg', 'test-ac', TEST_USER_ADMIN_LOGIN,
229 repo_group=getattr(repo_group, 'group_id', None))
243 repo_group=getattr(repo_group, 'group_id', None))
230
244
231 Session().commit()
245 Session().commit()
232
246
233 request.addfinalizer(self.cleanup)
247 request.addfinalizer(self.cleanup)
234
248
235 def cleanup(self):
249 def cleanup(self):
236 # first delete all repos
250 # first delete all repos
237 for repo_and_groups in self.required_repos_with_groups:
251 for repo_and_groups in self.required_repos_with_groups:
238 repo = Repository.get_by_repo_name(repo_and_groups)
252 repo = Repository.get_by_repo_name(repo_and_groups)
239 if repo:
253 if repo:
240 RepoModel().delete(repo)
254 RepoModel().delete(repo)
241 Session().commit()
255 Session().commit()
242
256
243 # then delete all empty groups
257 # then delete all empty groups
244 for repo_and_groups in self.required_repos_with_groups:
258 for repo_and_groups in self.required_repos_with_groups:
245 if '/' in repo_and_groups:
259 if '/' in repo_and_groups:
246 r_group = repo_and_groups.rsplit('/', 1)[0]
260 r_group = repo_and_groups.rsplit('/', 1)[0]
247 repo_group = RepoGroup.get_by_group_name(r_group)
261 repo_group = RepoGroup.get_by_group_name(r_group)
248 if not repo_group:
262 if not repo_group:
249 continue
263 continue
250 parents = repo_group.parents
264 parents = repo_group.parents
251 RepoGroupModel().delete(repo_group, force_delete=True)
265 RepoGroupModel().delete(repo_group, force_delete=True)
252 Session().commit()
266 Session().commit()
253
267
254 for el in reversed(parents):
268 for el in reversed(parents):
255 RepoGroupModel().delete(el, force_delete=True)
269 RepoGroupModel().delete(el, force_delete=True)
256 Session().commit()
270 Session().commit()
257
271
258 def test_returns_list_of_repos_and_groups(self):
272 def test_returns_list_of_repos_and_groups(self):
259 self.log_user()
273 self.log_user()
260
274
261 response = self.app.get(
275 response = self.app.get(
262 url(controller='home', action='goto_switcher_data'),
276 url(controller='home', action='goto_switcher_data'),
263 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
277 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
264 result = json.loads(response.body)['results']
278 result = json.loads(response.body)['results']
265
279
266 repos, groups, commits = assert_and_get_content(result)
280 repos, groups, commits = assert_and_get_content(result)
267
281
268 assert len(repos) == len(Repository.get_all())
282 assert len(repos) == len(Repository.get_all())
269 assert len(groups) == len(RepoGroup.get_all())
283 assert len(groups) == len(RepoGroup.get_all())
270 assert len(commits) == 0
284 assert len(commits) == 0
271
285
272 def test_returns_list_of_repos_and_groups_filtered(self):
286 def test_returns_list_of_repos_and_groups_filtered(self):
273 self.log_user()
287 self.log_user()
274
288
275 response = self.app.get(
289 response = self.app.get(
276 url(controller='home', action='goto_switcher_data'),
290 url(controller='home', action='goto_switcher_data'),
277 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
291 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
278 params={'query': 'abc'}, status=200)
292 params={'query': 'abc'}, status=200)
279 result = json.loads(response.body)['results']
293 result = json.loads(response.body)['results']
280
294
281 repos, groups, commits = assert_and_get_content(result)
295 repos, groups, commits = assert_and_get_content(result)
282
296
283 assert len(repos) == 13
297 assert len(repos) == 13
284 assert len(groups) == 5
298 assert len(groups) == 5
285 assert len(commits) == 0
299 assert len(commits) == 0
286
300
287 def test_returns_list_of_properly_sorted_and_filtered(self):
301 def test_returns_list_of_properly_sorted_and_filtered(self):
288 self.log_user()
302 self.log_user()
289
303
290 response = self.app.get(
304 response = self.app.get(
291 url(controller='home', action='goto_switcher_data'),
305 url(controller='home', action='goto_switcher_data'),
292 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
306 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
293 params={'query': 'abc'}, status=200)
307 params={'query': 'abc'}, status=200)
294 result = json.loads(response.body)['results']
308 result = json.loads(response.body)['results']
295
309
296 repos, groups, commits = assert_and_get_content(result)
310 repos, groups, commits = assert_and_get_content(result)
297
311
298 test_repos = [x['text'] for x in repos[:4]]
312 test_repos = [x['text'] for x in repos[:4]]
299 assert ['abc', 'abcd', 'a/abc', 'abcde'] == test_repos
313 assert ['abc', 'abcd', 'a/abc', 'abcde'] == test_repos
300
314
301 test_groups = [x['text'] for x in groups[:4]]
315 test_groups = [x['text'] for x in groups[:4]]
302 assert ['abc_repos', 'repos_abc',
316 assert ['abc_repos', 'repos_abc',
303 'forked-abc', 'forked-abc/a'] == test_groups
317 'forked-abc', 'forked-abc/a'] == test_groups
304
318
305
319
306 class TestRepoListData(TestController):
320 class TestRepoListData(TestController):
307 def test_returns_list_of_repos_and_groups(self, user_util):
321 def test_returns_list_of_repos_and_groups(self, user_util):
308 self.log_user()
322 self.log_user()
309
323
310 response = self.app.get(
324 response = self.app.get(
311 url(controller='home', action='repo_list_data'),
325 url(controller='home', action='repo_list_data'),
312 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
326 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
313 result = json.loads(response.body)['results']
327 result = json.loads(response.body)['results']
314
328
315 repos, groups, commits = assert_and_get_content(result)
329 repos, groups, commits = assert_and_get_content(result)
316
330
317 assert len(repos) == len(Repository.get_all())
331 assert len(repos) == len(Repository.get_all())
318 assert len(groups) == 0
332 assert len(groups) == 0
319 assert len(commits) == 0
333 assert len(commits) == 0
320
334
321 def test_returns_list_of_repos_and_groups_filtered(self):
335 def test_returns_list_of_repos_and_groups_filtered(self):
322 self.log_user()
336 self.log_user()
323
337
324 response = self.app.get(
338 response = self.app.get(
325 url(controller='home', action='repo_list_data'),
339 url(controller='home', action='repo_list_data'),
326 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
340 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
327 params={'query': 'vcs_test_git'}, status=200)
341 params={'query': 'vcs_test_git'}, status=200)
328 result = json.loads(response.body)['results']
342 result = json.loads(response.body)['results']
329
343
330 repos, groups, commits = assert_and_get_content(result)
344 repos, groups, commits = assert_and_get_content(result)
331
345
332 assert len(repos) == len(Repository.query().filter(
346 assert len(repos) == len(Repository.query().filter(
333 Repository.repo_name.ilike('%vcs_test_git%')).all())
347 Repository.repo_name.ilike('%vcs_test_git%')).all())
334 assert len(groups) == 0
348 assert len(groups) == 0
335 assert len(commits) == 0
349 assert len(commits) == 0
336
350
337 def test_returns_list_of_repos_and_groups_filtered_with_type(self):
351 def test_returns_list_of_repos_and_groups_filtered_with_type(self):
338 self.log_user()
352 self.log_user()
339
353
340 response = self.app.get(
354 response = self.app.get(
341 url(controller='home', action='repo_list_data'),
355 url(controller='home', action='repo_list_data'),
342 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
356 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
343 params={'query': 'vcs_test_git', 'repo_type': 'git'}, status=200)
357 params={'query': 'vcs_test_git', 'repo_type': 'git'}, status=200)
344 result = json.loads(response.body)['results']
358 result = json.loads(response.body)['results']
345
359
346 repos, groups, commits = assert_and_get_content(result)
360 repos, groups, commits = assert_and_get_content(result)
347
361
348 assert len(repos) == len(Repository.query().filter(
362 assert len(repos) == len(Repository.query().filter(
349 Repository.repo_name.ilike('%vcs_test_git%')).all())
363 Repository.repo_name.ilike('%vcs_test_git%')).all())
350 assert len(groups) == 0
364 assert len(groups) == 0
351 assert len(commits) == 0
365 assert len(commits) == 0
352
366
353 def test_returns_list_of_repos_non_ascii_query(self):
367 def test_returns_list_of_repos_non_ascii_query(self):
354 self.log_user()
368 self.log_user()
355 response = self.app.get(
369 response = self.app.get(
356 url(controller='home', action='repo_list_data'),
370 url(controller='home', action='repo_list_data'),
357 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
371 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
358 params={'query': 'ć_vcs_test_ą', 'repo_type': 'git'}, status=200)
372 params={'query': 'ć_vcs_test_ą', 'repo_type': 'git'}, status=200)
359 result = json.loads(response.body)['results']
373 result = json.loads(response.body)['results']
360
374
361 repos, groups, commits = assert_and_get_content(result)
375 repos, groups, commits = assert_and_get_content(result)
362
376
363 assert len(repos) == 0
377 assert len(repos) == 0
364 assert len(groups) == 0
378 assert len(groups) == 0
365 assert len(commits) == 0
379 assert len(commits) == 0
General Comments 0
You need to be logged in to leave comments. Login now