##// END OF EJS Templates
goto-switcher: optimized performance and query capabilities....
marcink -
r2038:2bdf9d4d default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,305 +1,321 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import re
22 22 import logging
23 23
24 24 from pyramid.view import view_config
25 25
26 26 from rhodecode.apps._base import BaseAppView
27 27 from rhodecode.lib import helpers as h
28 28 from rhodecode.lib.auth import LoginRequired, NotAnonymous, \
29 29 HasRepoGroupPermissionAnyDecorator
30 30 from rhodecode.lib.index import searcher_from_config
31 31 from rhodecode.lib.utils2 import safe_unicode, str2bool
32 32 from rhodecode.lib.ext_json import json
33 from rhodecode.model.db import func, Repository, RepoGroup
33 from rhodecode.model.db import (
34 func, or_, in_filter_generator, Repository, RepoGroup)
34 35 from rhodecode.model.repo import RepoModel
35 36 from rhodecode.model.repo_group import RepoGroupModel
36 from rhodecode.model.scm import ScmModel, RepoGroupList, RepoList
37 from rhodecode.model.scm import RepoGroupList, RepoList
37 38 from rhodecode.model.user import UserModel
38 39 from rhodecode.model.user_group import UserGroupModel
39 40
40 41 log = logging.getLogger(__name__)
41 42
42 43
43 44 class HomeView(BaseAppView):
44 45
45 46 def load_default_context(self):
46 47 c = self._get_local_tmpl_context()
47 48 c.user = c.auth_user.get_instance()
48 49 self._register_global_c(c)
49 50 return c
50 51
51 52 @LoginRequired()
52 53 @view_config(
53 54 route_name='user_autocomplete_data', request_method='GET',
54 55 renderer='json_ext', xhr=True)
55 56 def user_autocomplete_data(self):
56 57 query = self.request.GET.get('query')
57 58 active = str2bool(self.request.GET.get('active') or True)
58 59 include_groups = str2bool(self.request.GET.get('user_groups'))
59 60 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
60 61 skip_default_user = str2bool(self.request.GET.get('skip_default_user'))
61 62
62 63 log.debug('generating user list, query:%s, active:%s, with_groups:%s',
63 64 query, active, include_groups)
64 65
65 66 _users = UserModel().get_users(
66 67 name_contains=query, only_active=active)
67 68
68 69 def maybe_skip_default_user(usr):
69 70 if skip_default_user and usr['username'] == UserModel.cls.DEFAULT_USER:
70 71 return False
71 72 return True
72 73 _users = filter(maybe_skip_default_user, _users)
73 74
74 75 if include_groups:
75 76 # extend with user groups
76 77 _user_groups = UserGroupModel().get_user_groups(
77 78 name_contains=query, only_active=active,
78 79 expand_groups=expand_groups)
79 80 _users = _users + _user_groups
80 81
81 82 return {'suggestions': _users}
82 83
83 84 @LoginRequired()
84 85 @NotAnonymous()
85 86 @view_config(
86 87 route_name='user_group_autocomplete_data', request_method='GET',
87 88 renderer='json_ext', xhr=True)
88 89 def user_group_autocomplete_data(self):
89 90 query = self.request.GET.get('query')
90 91 active = str2bool(self.request.GET.get('active') or True)
91 92 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
92 93
93 94 log.debug('generating user group list, query:%s, active:%s',
94 95 query, active)
95 96
96 97 _user_groups = UserGroupModel().get_user_groups(
97 98 name_contains=query, only_active=active,
98 99 expand_groups=expand_groups)
99 100 _user_groups = _user_groups
100 101
101 102 return {'suggestions': _user_groups}
102 103
103 104 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
105 allowed_ids = self._rhodecode_user.repo_acl_ids(
106 ['repository.read', 'repository.write', 'repository.admin'],
107 cache=False, name_filter=name_contains)
108
104 109 query = Repository.query()\
105 110 .order_by(func.length(Repository.repo_name))\
106 .order_by(Repository.repo_name)
111 .order_by(Repository.repo_name)\
112 .filter(or_(
113 # generate multiple IN to fix limitation problems
114 *in_filter_generator(Repository.repo_id, allowed_ids)
115 ))
107 116
108 117 if repo_type:
109 118 query = query.filter(Repository.repo_type == repo_type)
110 119
111 120 if name_contains:
112 121 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
113 122 query = query.filter(
114 123 Repository.repo_name.ilike(ilike_expression))
115 124 query = query.limit(limit)
116 125
117 all_repos = query.all()
118 # permission checks are inside this function
119 repo_iter = ScmModel().get_repos(all_repos)
126 acl_repo_iter = query
127
120 128 return [
121 129 {
122 'id': obj['name'],
123 'text': obj['name'],
130 'id': obj.repo_name,
131 'text': obj.repo_name,
124 132 'type': 'repo',
125 'obj': obj['dbrepo'],
126 'url': h.route_path('repo_summary', repo_name=obj['name'])
133 'obj': {'repo_type': obj.repo_type, 'private': obj.private},
134 'url': h.route_path('repo_summary', repo_name=obj.repo_name)
127 135 }
128 for obj in repo_iter]
136 for obj in acl_repo_iter]
129 137
130 138 def _get_repo_group_list(self, name_contains=None, limit=20):
139 allowed_ids = self._rhodecode_user.repo_group_acl_ids(
140 ['group.read', 'group.write', 'group.admin'],
141 cache=False, name_filter=name_contains)
142
131 143 query = RepoGroup.query()\
132 144 .order_by(func.length(RepoGroup.group_name))\
133 .order_by(RepoGroup.group_name)
145 .order_by(RepoGroup.group_name) \
146 .filter(or_(
147 # generate multiple IN to fix limitation problems
148 *in_filter_generator(RepoGroup.group_id, allowed_ids)
149 ))
134 150
135 151 if name_contains:
136 152 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
137 153 query = query.filter(
138 154 RepoGroup.group_name.ilike(ilike_expression))
139 155 query = query.limit(limit)
140 156
141 all_groups = query.all()
142 repo_groups_iter = ScmModel().get_repo_groups(all_groups)
157 acl_repo_iter = query
158
143 159 return [
144 160 {
145 161 'id': obj.group_name,
146 162 'text': obj.group_name,
147 163 'type': 'group',
148 164 'obj': {},
149 165 'url': h.route_path(
150 166 'repo_group_home', repo_group_name=obj.group_name)
151 167 }
152 for obj in repo_groups_iter]
168 for obj in acl_repo_iter]
153 169
154 170 def _get_hash_commit_list(self, auth_user, query=None):
155 171 if not query or len(query) < 3:
156 172 return []
157 173
158 174 commit_hashes = re.compile('(?:commit:)([0-9a-f]{2,40})').findall(query)
159 175
160 176 if len(commit_hashes) != 1:
161 177 return []
162 178
163 179 commit_hash_prefix = commit_hashes[0]
164 180
165 181 searcher = searcher_from_config(self.request.registry.settings)
166 182 result = searcher.search(
167 183 'commit_id:%s*' % commit_hash_prefix, 'commit', auth_user,
168 184 raise_on_exc=False)
169 185
170 186 return [
171 187 {
172 188 'id': entry['commit_id'],
173 189 'text': entry['commit_id'],
174 190 'type': 'commit',
175 191 'obj': {'repo': entry['repository']},
176 192 'url': h.route_path(
177 193 'repo_commit',
178 194 repo_name=entry['repository'], commit_id=entry['commit_id'])
179 195 }
180 196 for entry in result['results']]
181 197
182 198 @LoginRequired()
183 199 @view_config(
184 200 route_name='repo_list_data', request_method='GET',
185 201 renderer='json_ext', xhr=True)
186 202 def repo_list_data(self):
187 203 _ = self.request.translate
188 204
189 205 query = self.request.GET.get('query')
190 206 repo_type = self.request.GET.get('repo_type')
191 207 log.debug('generating repo list, query:%s, repo_type:%s',
192 208 query, repo_type)
193 209
194 210 res = []
195 211 repos = self._get_repo_list(query, repo_type=repo_type)
196 212 if repos:
197 213 res.append({
198 214 'text': _('Repositories'),
199 215 'children': repos
200 216 })
201 217
202 218 data = {
203 219 'more': False,
204 220 'results': res
205 221 }
206 222 return data
207 223
208 224 @LoginRequired()
209 225 @view_config(
210 226 route_name='goto_switcher_data', request_method='GET',
211 227 renderer='json_ext', xhr=True)
212 228 def goto_switcher_data(self):
213 229 c = self.load_default_context()
214 230
215 231 _ = self.request.translate
216 232
217 233 query = self.request.GET.get('query')
218 234 log.debug('generating goto switcher list, query %s', query)
219 235
220 236 res = []
221 237 repo_groups = self._get_repo_group_list(query)
222 238 if repo_groups:
223 239 res.append({
224 240 'text': _('Groups'),
225 241 'children': repo_groups
226 242 })
227 243
228 244 repos = self._get_repo_list(query)
229 245 if repos:
230 246 res.append({
231 247 'text': _('Repositories'),
232 248 'children': repos
233 249 })
234 250
235 251 commits = self._get_hash_commit_list(c.auth_user, query)
236 252 if commits:
237 253 unique_repos = {}
238 254 for commit in commits:
239 255 unique_repos.setdefault(commit['obj']['repo'], []
240 256 ).append(commit)
241 257
242 258 for repo in unique_repos:
243 259 res.append({
244 260 'text': _('Commits in %(repo)s') % {'repo': repo},
245 261 'children': unique_repos[repo]
246 262 })
247 263
248 264 data = {
249 265 'more': False,
250 266 'results': res
251 267 }
252 268 return data
253 269
254 270 def _get_groups_and_repos(self, repo_group_id=None):
255 271 # repo groups groups
256 272 repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
257 273 _perms = ['group.read', 'group.write', 'group.admin']
258 274 repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
259 275 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
260 276 repo_group_list=repo_group_list_acl, admin=False)
261 277
262 278 # repositories
263 279 repo_list = Repository.get_all_repos(group_id=repo_group_id)
264 280 _perms = ['repository.read', 'repository.write', 'repository.admin']
265 281 repo_list_acl = RepoList(repo_list, perm_set=_perms)
266 282 repo_data = RepoModel().get_repos_as_dict(
267 283 repo_list=repo_list_acl, admin=False)
268 284
269 285 return repo_data, repo_group_data
270 286
271 287 @LoginRequired()
272 288 @view_config(
273 289 route_name='home', request_method='GET',
274 290 renderer='rhodecode:templates/index.mako')
275 291 def main_page(self):
276 292 c = self.load_default_context()
277 293 c.repo_group = None
278 294
279 295 repo_data, repo_group_data = self._get_groups_and_repos()
280 296 # json used to render the grids
281 297 c.repos_data = json.dumps(repo_data)
282 298 c.repo_groups_data = json.dumps(repo_group_data)
283 299
284 300 return self._get_template_context(c)
285 301
286 302 @LoginRequired()
287 303 @HasRepoGroupPermissionAnyDecorator(
288 304 'group.read', 'group.write', 'group.admin')
289 305 @view_config(
290 306 route_name='repo_group_home', request_method='GET',
291 307 renderer='rhodecode:templates/index_repo_group.mako')
292 308 @view_config(
293 309 route_name='repo_group_home_slash', request_method='GET',
294 310 renderer='rhodecode:templates/index_repo_group.mako')
295 311 def repo_group_main_page(self):
296 312 c = self.load_default_context()
297 313 c.repo_group = self.request.db_repo_group
298 314 repo_data, repo_group_data = self._get_groups_and_repos(
299 315 c.repo_group.group_id)
300 316
301 317 # json used to render the grids
302 318 c.repos_data = json.dumps(repo_data)
303 319 c.repo_groups_data = json.dumps(repo_group_data)
304 320
305 321 return self._get_template_context(c)
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now