##// END OF EJS Templates
ux: change file search to file content search which makes a better description of what we search for.
dan -
r4207:132d653a stable
parent child Browse files
Show More
@@ -1,69 +1,69 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2019 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
22 22 def assert_and_get_main_filter_content(result):
23 23 repos = []
24 24 groups = []
25 25 commits = []
26 26 users = []
27 27 for data_item in result:
28 28 assert data_item['id']
29 29 assert data_item['value']
30 30 assert data_item['value_display']
31 31 assert data_item['url']
32 32
33 33 if data_item['type'] == 'search':
34 34 display_val = data_item['value_display']
35 35 if data_item['id'] == -1:
36 assert 'File search for:' in display_val, display_val
36 assert 'File content search for:' in display_val, display_val
37 37 elif data_item['id'] == -2:
38 38 assert 'Commit search for:' in display_val, display_val
39 39 else:
40 40 assert False, 'No Proper ID returned {}'.format(data_item['id'])
41 41
42 42 elif data_item['type'] == 'repo':
43 43 repos.append(data_item)
44 44 elif data_item['type'] == 'repo_group':
45 45 groups.append(data_item)
46 46 elif data_item['type'] == 'user':
47 47 users.append(data_item)
48 48 elif data_item['type'] == 'commit':
49 49 commits.append(data_item)
50 50 else:
51 51 raise Exception('invalid type `%s`' % data_item['type'])
52 52
53 53 return repos, groups, users, commits
54 54
55 55
56 56 def assert_and_get_repo_list_content(result):
57 57 repos = []
58 58 for data in result:
59 59 for data_item in data['children']:
60 60 assert data_item['id']
61 61 assert data_item['text']
62 62 assert data_item['url']
63 63
64 64 if data_item['type'] == 'repo':
65 65 repos.append(data_item)
66 66 else:
67 67 raise Exception('invalid type %s' % data_item['type'])
68 68
69 69 return repos
@@ -1,830 +1,830 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2019 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 import collections
24 24
25 25 from pyramid.httpexceptions import HTTPNotFound
26 26 from pyramid.view import view_config
27 27
28 28 from rhodecode.apps._base import BaseAppView, DataGridAppView
29 29 from rhodecode.lib import helpers as h
30 30 from rhodecode.lib.auth import (
31 31 LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator, CSRFRequired,
32 32 HasRepoGroupPermissionAny, AuthUser)
33 33 from rhodecode.lib.codeblocks import filenode_as_lines_tokens
34 34 from rhodecode.lib.index import searcher_from_config
35 35 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
36 36 from rhodecode.lib.vcs.nodes import FileNode
37 37 from rhodecode.model.db import (
38 38 func, true, or_, case, in_filter_generator, Session,
39 39 Repository, RepoGroup, User, UserGroup)
40 40 from rhodecode.model.repo import RepoModel
41 41 from rhodecode.model.repo_group import RepoGroupModel
42 42 from rhodecode.model.user import UserModel
43 43 from rhodecode.model.user_group import UserGroupModel
44 44
45 45 log = logging.getLogger(__name__)
46 46
47 47
48 48 class HomeView(BaseAppView, DataGridAppView):
49 49
50 50 def load_default_context(self):
51 51 c = self._get_local_tmpl_context()
52 52 c.user = c.auth_user.get_instance()
53 53
54 54 return c
55 55
56 56 @LoginRequired()
57 57 @view_config(
58 58 route_name='user_autocomplete_data', request_method='GET',
59 59 renderer='json_ext', xhr=True)
60 60 def user_autocomplete_data(self):
61 61 self.load_default_context()
62 62 query = self.request.GET.get('query')
63 63 active = str2bool(self.request.GET.get('active') or True)
64 64 include_groups = str2bool(self.request.GET.get('user_groups'))
65 65 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
66 66 skip_default_user = str2bool(self.request.GET.get('skip_default_user'))
67 67
68 68 log.debug('generating user list, query:%s, active:%s, with_groups:%s',
69 69 query, active, include_groups)
70 70
71 71 _users = UserModel().get_users(
72 72 name_contains=query, only_active=active)
73 73
74 74 def maybe_skip_default_user(usr):
75 75 if skip_default_user and usr['username'] == UserModel.cls.DEFAULT_USER:
76 76 return False
77 77 return True
78 78 _users = filter(maybe_skip_default_user, _users)
79 79
80 80 if include_groups:
81 81 # extend with user groups
82 82 _user_groups = UserGroupModel().get_user_groups(
83 83 name_contains=query, only_active=active,
84 84 expand_groups=expand_groups)
85 85 _users = _users + _user_groups
86 86
87 87 return {'suggestions': _users}
88 88
89 89 @LoginRequired()
90 90 @NotAnonymous()
91 91 @view_config(
92 92 route_name='user_group_autocomplete_data', request_method='GET',
93 93 renderer='json_ext', xhr=True)
94 94 def user_group_autocomplete_data(self):
95 95 self.load_default_context()
96 96 query = self.request.GET.get('query')
97 97 active = str2bool(self.request.GET.get('active') or True)
98 98 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
99 99
100 100 log.debug('generating user group list, query:%s, active:%s',
101 101 query, active)
102 102
103 103 _user_groups = UserGroupModel().get_user_groups(
104 104 name_contains=query, only_active=active,
105 105 expand_groups=expand_groups)
106 106 _user_groups = _user_groups
107 107
108 108 return {'suggestions': _user_groups}
109 109
110 110 def _get_repo_list(self, name_contains=None, repo_type=None, repo_group_name='', limit=20):
111 111 org_query = name_contains
112 112 allowed_ids = self._rhodecode_user.repo_acl_ids(
113 113 ['repository.read', 'repository.write', 'repository.admin'],
114 114 cache=False, name_filter=name_contains) or [-1]
115 115
116 116 query = Session().query(
117 117 Repository.repo_name,
118 118 Repository.repo_id,
119 119 Repository.repo_type,
120 120 Repository.private,
121 121 )\
122 122 .filter(Repository.archived.isnot(true()))\
123 123 .filter(or_(
124 124 # generate multiple IN to fix limitation problems
125 125 *in_filter_generator(Repository.repo_id, allowed_ids)
126 126 ))
127 127
128 128 query = query.order_by(case(
129 129 [
130 130 (Repository.repo_name.startswith(repo_group_name), repo_group_name+'/'),
131 131 ],
132 132 ))
133 133 query = query.order_by(func.length(Repository.repo_name))
134 134 query = query.order_by(Repository.repo_name)
135 135
136 136 if repo_type:
137 137 query = query.filter(Repository.repo_type == repo_type)
138 138
139 139 if name_contains:
140 140 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
141 141 query = query.filter(
142 142 Repository.repo_name.ilike(ilike_expression))
143 143 query = query.limit(limit)
144 144
145 145 acl_iter = query
146 146
147 147 return [
148 148 {
149 149 'id': obj.repo_name,
150 150 'value': org_query,
151 151 'value_display': obj.repo_name,
152 152 'text': obj.repo_name,
153 153 'type': 'repo',
154 154 'repo_id': obj.repo_id,
155 155 'repo_type': obj.repo_type,
156 156 'private': obj.private,
157 157 'url': h.route_path('repo_summary', repo_name=obj.repo_name)
158 158 }
159 159 for obj in acl_iter]
160 160
161 161 def _get_repo_group_list(self, name_contains=None, repo_group_name='', limit=20):
162 162 org_query = name_contains
163 163 allowed_ids = self._rhodecode_user.repo_group_acl_ids(
164 164 ['group.read', 'group.write', 'group.admin'],
165 165 cache=False, name_filter=name_contains) or [-1]
166 166
167 167 query = Session().query(
168 168 RepoGroup.group_id,
169 169 RepoGroup.group_name,
170 170 )\
171 171 .filter(or_(
172 172 # generate multiple IN to fix limitation problems
173 173 *in_filter_generator(RepoGroup.group_id, allowed_ids)
174 174 ))
175 175
176 176 query = query.order_by(case(
177 177 [
178 178 (RepoGroup.group_name.startswith(repo_group_name), repo_group_name+'/'),
179 179 ],
180 180 ))
181 181 query = query.order_by(func.length(RepoGroup.group_name))
182 182 query = query.order_by(RepoGroup.group_name)
183 183
184 184 if name_contains:
185 185 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
186 186 query = query.filter(
187 187 RepoGroup.group_name.ilike(ilike_expression))
188 188 query = query.limit(limit)
189 189
190 190 acl_iter = query
191 191
192 192 return [
193 193 {
194 194 'id': obj.group_name,
195 195 'value': org_query,
196 196 'value_display': obj.group_name,
197 197 'text': obj.group_name,
198 198 'type': 'repo_group',
199 199 'repo_group_id': obj.group_id,
200 200 'url': h.route_path(
201 201 'repo_group_home', repo_group_name=obj.group_name)
202 202 }
203 203 for obj in acl_iter]
204 204
205 205 def _get_user_list(self, name_contains=None, limit=20):
206 206 org_query = name_contains
207 207 if not name_contains:
208 208 return [], False
209 209
210 210 # TODO(marcink): should all logged in users be allowed to search others?
211 211 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
212 212 if not allowed_user_search:
213 213 return [], False
214 214
215 215 name_contains = re.compile('(?:user:[ ]?)(.+)').findall(name_contains)
216 216 if len(name_contains) != 1:
217 217 return [], False
218 218
219 219 name_contains = name_contains[0]
220 220
221 221 query = User.query()\
222 222 .order_by(func.length(User.username))\
223 223 .order_by(User.username) \
224 224 .filter(User.username != User.DEFAULT_USER)
225 225
226 226 if name_contains:
227 227 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
228 228 query = query.filter(
229 229 User.username.ilike(ilike_expression))
230 230 query = query.limit(limit)
231 231
232 232 acl_iter = query
233 233
234 234 return [
235 235 {
236 236 'id': obj.user_id,
237 237 'value': org_query,
238 238 'value_display': 'user: `{}`'.format(obj.username),
239 239 'type': 'user',
240 240 'icon_link': h.gravatar_url(obj.email, 30),
241 241 'url': h.route_path(
242 242 'user_profile', username=obj.username)
243 243 }
244 244 for obj in acl_iter], True
245 245
246 246 def _get_user_groups_list(self, name_contains=None, limit=20):
247 247 org_query = name_contains
248 248 if not name_contains:
249 249 return [], False
250 250
251 251 # TODO(marcink): should all logged in users be allowed to search others?
252 252 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
253 253 if not allowed_user_search:
254 254 return [], False
255 255
256 256 name_contains = re.compile('(?:user_group:[ ]?)(.+)').findall(name_contains)
257 257 if len(name_contains) != 1:
258 258 return [], False
259 259
260 260 name_contains = name_contains[0]
261 261
262 262 query = UserGroup.query()\
263 263 .order_by(func.length(UserGroup.users_group_name))\
264 264 .order_by(UserGroup.users_group_name)
265 265
266 266 if name_contains:
267 267 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
268 268 query = query.filter(
269 269 UserGroup.users_group_name.ilike(ilike_expression))
270 270 query = query.limit(limit)
271 271
272 272 acl_iter = query
273 273
274 274 return [
275 275 {
276 276 'id': obj.users_group_id,
277 277 'value': org_query,
278 278 'value_display': 'user_group: `{}`'.format(obj.users_group_name),
279 279 'type': 'user_group',
280 280 'url': h.route_path(
281 281 'user_group_profile', user_group_name=obj.users_group_name)
282 282 }
283 283 for obj in acl_iter], True
284 284
285 285 def _get_hash_commit_list(self, auth_user, searcher, query, repo=None, repo_group=None):
286 286 repo_name = repo_group_name = None
287 287 if repo:
288 288 repo_name = repo.repo_name
289 289 if repo_group:
290 290 repo_group_name = repo_group.group_name
291 291
292 292 org_query = query
293 293 if not query or len(query) < 3 or not searcher:
294 294 return [], False
295 295
296 296 commit_hashes = re.compile('(?:commit:[ ]?)([0-9a-f]{2,40})').findall(query)
297 297
298 298 if len(commit_hashes) != 1:
299 299 return [], False
300 300
301 301 commit_hash = commit_hashes[0]
302 302
303 303 result = searcher.search(
304 304 'commit_id:{}*'.format(commit_hash), 'commit', auth_user,
305 305 repo_name, repo_group_name, raise_on_exc=False)
306 306
307 307 commits = []
308 308 for entry in result['results']:
309 309 repo_data = {
310 310 'repository_id': entry.get('repository_id'),
311 311 'repository_type': entry.get('repo_type'),
312 312 'repository_name': entry.get('repository'),
313 313 }
314 314
315 315 commit_entry = {
316 316 'id': entry['commit_id'],
317 317 'value': org_query,
318 318 'value_display': '`{}` commit: {}'.format(
319 319 entry['repository'], entry['commit_id']),
320 320 'type': 'commit',
321 321 'repo': entry['repository'],
322 322 'repo_data': repo_data,
323 323
324 324 'url': h.route_path(
325 325 'repo_commit',
326 326 repo_name=entry['repository'], commit_id=entry['commit_id'])
327 327 }
328 328
329 329 commits.append(commit_entry)
330 330 return commits, True
331 331
332 332 def _get_path_list(self, auth_user, searcher, query, repo=None, repo_group=None):
333 333 repo_name = repo_group_name = None
334 334 if repo:
335 335 repo_name = repo.repo_name
336 336 if repo_group:
337 337 repo_group_name = repo_group.group_name
338 338
339 339 org_query = query
340 340 if not query or len(query) < 3 or not searcher:
341 341 return [], False
342 342
343 343 paths_re = re.compile('(?:file:[ ]?)(.+)').findall(query)
344 344 if len(paths_re) != 1:
345 345 return [], False
346 346
347 347 file_path = paths_re[0]
348 348
349 349 search_path = searcher.escape_specials(file_path)
350 350 result = searcher.search(
351 351 'file.raw:*{}*'.format(search_path), 'path', auth_user,
352 352 repo_name, repo_group_name, raise_on_exc=False)
353 353
354 354 files = []
355 355 for entry in result['results']:
356 356 repo_data = {
357 357 'repository_id': entry.get('repository_id'),
358 358 'repository_type': entry.get('repo_type'),
359 359 'repository_name': entry.get('repository'),
360 360 }
361 361
362 362 file_entry = {
363 363 'id': entry['commit_id'],
364 364 'value': org_query,
365 365 'value_display': '`{}` file: {}'.format(
366 366 entry['repository'], entry['file']),
367 367 'type': 'file',
368 368 'repo': entry['repository'],
369 369 'repo_data': repo_data,
370 370
371 371 'url': h.route_path(
372 372 'repo_files',
373 373 repo_name=entry['repository'], commit_id=entry['commit_id'],
374 374 f_path=entry['file'])
375 375 }
376 376
377 377 files.append(file_entry)
378 378 return files, True
379 379
380 380 @LoginRequired()
381 381 @view_config(
382 382 route_name='repo_list_data', request_method='GET',
383 383 renderer='json_ext', xhr=True)
384 384 def repo_list_data(self):
385 385 _ = self.request.translate
386 386 self.load_default_context()
387 387
388 388 query = self.request.GET.get('query')
389 389 repo_type = self.request.GET.get('repo_type')
390 390 log.debug('generating repo list, query:%s, repo_type:%s',
391 391 query, repo_type)
392 392
393 393 res = []
394 394 repos = self._get_repo_list(query, repo_type=repo_type)
395 395 if repos:
396 396 res.append({
397 397 'text': _('Repositories'),
398 398 'children': repos
399 399 })
400 400
401 401 data = {
402 402 'more': False,
403 403 'results': res
404 404 }
405 405 return data
406 406
407 407 @LoginRequired()
408 408 @view_config(
409 409 route_name='repo_group_list_data', request_method='GET',
410 410 renderer='json_ext', xhr=True)
411 411 def repo_group_list_data(self):
412 412 _ = self.request.translate
413 413 self.load_default_context()
414 414
415 415 query = self.request.GET.get('query')
416 416
417 417 log.debug('generating repo group list, query:%s',
418 418 query)
419 419
420 420 res = []
421 421 repo_groups = self._get_repo_group_list(query)
422 422 if repo_groups:
423 423 res.append({
424 424 'text': _('Repository Groups'),
425 425 'children': repo_groups
426 426 })
427 427
428 428 data = {
429 429 'more': False,
430 430 'results': res
431 431 }
432 432 return data
433 433
434 434 def _get_default_search_queries(self, search_context, searcher, query):
435 435 if not searcher:
436 436 return []
437 437
438 438 is_es_6 = searcher.is_es_6
439 439
440 440 queries = []
441 441 repo_group_name, repo_name, repo_context = None, None, None
442 442
443 443 # repo group context
444 444 if search_context.get('search_context[repo_group_name]'):
445 445 repo_group_name = search_context.get('search_context[repo_group_name]')
446 446 if search_context.get('search_context[repo_name]'):
447 447 repo_name = search_context.get('search_context[repo_name]')
448 448 repo_context = search_context.get('search_context[repo_view_type]')
449 449
450 450 if is_es_6 and repo_name:
451 451 # files
452 452 def query_modifier():
453 453 qry = query
454 454 return {'q': qry, 'type': 'content'}
455 455
456 label = u'File search for `{}`'.format(h.escape(query))
456 label = u'File content search for `{}`'.format(h.escape(query))
457 457 file_qry = {
458 458 'id': -10,
459 459 'value': query,
460 460 'value_display': label,
461 461 'value_icon': '<i class="icon-code"></i>',
462 462 'type': 'search',
463 463 'subtype': 'repo',
464 464 'url': h.route_path('search_repo',
465 465 repo_name=repo_name,
466 466 _query=query_modifier())
467 467 }
468 468
469 469 # commits
470 470 def query_modifier():
471 471 qry = query
472 472 return {'q': qry, 'type': 'commit'}
473 473
474 474 label = u'Commit search for `{}`'.format(h.escape(query))
475 475 commit_qry = {
476 476 'id': -20,
477 477 'value': query,
478 478 'value_display': label,
479 479 'value_icon': '<i class="icon-history"></i>',
480 480 'type': 'search',
481 481 'subtype': 'repo',
482 482 'url': h.route_path('search_repo',
483 483 repo_name=repo_name,
484 484 _query=query_modifier())
485 485 }
486 486
487 487 if repo_context in ['commit', 'commits']:
488 488 queries.extend([commit_qry, file_qry])
489 489 elif repo_context in ['files', 'summary']:
490 490 queries.extend([file_qry, commit_qry])
491 491 else:
492 492 queries.extend([commit_qry, file_qry])
493 493
494 494 elif is_es_6 and repo_group_name:
495 495 # files
496 496 def query_modifier():
497 497 qry = query
498 498 return {'q': qry, 'type': 'content'}
499 499
500 label = u'File search for `{}`'.format(query)
500 label = u'File content search for `{}`'.format(query)
501 501 file_qry = {
502 502 'id': -30,
503 503 'value': query,
504 504 'value_display': label,
505 505 'value_icon': '<i class="icon-code"></i>',
506 506 'type': 'search',
507 507 'subtype': 'repo_group',
508 508 'url': h.route_path('search_repo_group',
509 509 repo_group_name=repo_group_name,
510 510 _query=query_modifier())
511 511 }
512 512
513 513 # commits
514 514 def query_modifier():
515 515 qry = query
516 516 return {'q': qry, 'type': 'commit'}
517 517
518 518 label = u'Commit search for `{}`'.format(query)
519 519 commit_qry = {
520 520 'id': -40,
521 521 'value': query,
522 522 'value_display': label,
523 523 'value_icon': '<i class="icon-history"></i>',
524 524 'type': 'search',
525 525 'subtype': 'repo_group',
526 526 'url': h.route_path('search_repo_group',
527 527 repo_group_name=repo_group_name,
528 528 _query=query_modifier())
529 529 }
530 530
531 531 if repo_context in ['commit', 'commits']:
532 532 queries.extend([commit_qry, file_qry])
533 533 elif repo_context in ['files', 'summary']:
534 534 queries.extend([file_qry, commit_qry])
535 535 else:
536 536 queries.extend([commit_qry, file_qry])
537 537
538 538 # Global, not scoped
539 539 if not queries:
540 540 queries.append(
541 541 {
542 542 'id': -1,
543 543 'value': query,
544 'value_display': u'File search for: `{}`'.format(query),
544 'value_display': u'File content search for: `{}`'.format(query),
545 545 'value_icon': '<i class="icon-code"></i>',
546 546 'type': 'search',
547 547 'subtype': 'global',
548 548 'url': h.route_path('search',
549 549 _query={'q': query, 'type': 'content'})
550 550 })
551 551 queries.append(
552 552 {
553 553 'id': -2,
554 554 'value': query,
555 555 'value_display': u'Commit search for: `{}`'.format(query),
556 556 'value_icon': '<i class="icon-history"></i>',
557 557 'type': 'search',
558 558 'subtype': 'global',
559 559 'url': h.route_path('search',
560 560 _query={'q': query, 'type': 'commit'})
561 561 })
562 562
563 563 return queries
564 564
565 565 @LoginRequired()
566 566 @view_config(
567 567 route_name='goto_switcher_data', request_method='GET',
568 568 renderer='json_ext', xhr=True)
569 569 def goto_switcher_data(self):
570 570 c = self.load_default_context()
571 571
572 572 _ = self.request.translate
573 573
574 574 query = self.request.GET.get('query')
575 575 log.debug('generating main filter data, query %s', query)
576 576
577 577 res = []
578 578 if not query:
579 579 return {'suggestions': res}
580 580
581 581 def no_match(name):
582 582 return {
583 583 'id': -1,
584 584 'value': "",
585 585 'value_display': name,
586 586 'type': 'text',
587 587 'url': ""
588 588 }
589 589 searcher = searcher_from_config(self.request.registry.settings)
590 590 has_specialized_search = False
591 591
592 592 # set repo context
593 593 repo = None
594 594 repo_id = safe_int(self.request.GET.get('search_context[repo_id]'))
595 595 if repo_id:
596 596 repo = Repository.get(repo_id)
597 597
598 598 # set group context
599 599 repo_group = None
600 600 repo_group_id = safe_int(self.request.GET.get('search_context[repo_group_id]'))
601 601 if repo_group_id:
602 602 repo_group = RepoGroup.get(repo_group_id)
603 603 prefix_match = False
604 604
605 605 # user: type search
606 606 if not prefix_match:
607 607 users, prefix_match = self._get_user_list(query)
608 608 if users:
609 609 has_specialized_search = True
610 610 for serialized_user in users:
611 611 res.append(serialized_user)
612 612 elif prefix_match:
613 613 has_specialized_search = True
614 614 res.append(no_match('No matching users found'))
615 615
616 616 # user_group: type search
617 617 if not prefix_match:
618 618 user_groups, prefix_match = self._get_user_groups_list(query)
619 619 if user_groups:
620 620 has_specialized_search = True
621 621 for serialized_user_group in user_groups:
622 622 res.append(serialized_user_group)
623 623 elif prefix_match:
624 624 has_specialized_search = True
625 625 res.append(no_match('No matching user groups found'))
626 626
627 627 # FTS commit: type search
628 628 if not prefix_match:
629 629 commits, prefix_match = self._get_hash_commit_list(
630 630 c.auth_user, searcher, query, repo, repo_group)
631 631 if commits:
632 632 has_specialized_search = True
633 633 unique_repos = collections.OrderedDict()
634 634 for commit in commits:
635 635 repo_name = commit['repo']
636 636 unique_repos.setdefault(repo_name, []).append(commit)
637 637
638 638 for _repo, commits in unique_repos.items():
639 639 for commit in commits:
640 640 res.append(commit)
641 641 elif prefix_match:
642 642 has_specialized_search = True
643 643 res.append(no_match('No matching commits found'))
644 644
645 645 # FTS file: type search
646 646 if not prefix_match:
647 647 paths, prefix_match = self._get_path_list(
648 648 c.auth_user, searcher, query, repo, repo_group)
649 649 if paths:
650 650 has_specialized_search = True
651 651 unique_repos = collections.OrderedDict()
652 652 for path in paths:
653 653 repo_name = path['repo']
654 654 unique_repos.setdefault(repo_name, []).append(path)
655 655
656 656 for repo, paths in unique_repos.items():
657 657 for path in paths:
658 658 res.append(path)
659 659 elif prefix_match:
660 660 has_specialized_search = True
661 661 res.append(no_match('No matching files found'))
662 662
663 663 # main suggestions
664 664 if not has_specialized_search:
665 665 repo_group_name = ''
666 666 if repo_group:
667 667 repo_group_name = repo_group.group_name
668 668
669 669 for _q in self._get_default_search_queries(self.request.GET, searcher, query):
670 670 res.append(_q)
671 671
672 672 repo_groups = self._get_repo_group_list(query, repo_group_name=repo_group_name)
673 673 for serialized_repo_group in repo_groups:
674 674 res.append(serialized_repo_group)
675 675
676 676 repos = self._get_repo_list(query, repo_group_name=repo_group_name)
677 677 for serialized_repo in repos:
678 678 res.append(serialized_repo)
679 679
680 680 if not repos and not repo_groups:
681 681 res.append(no_match('No matches found'))
682 682
683 683 return {'suggestions': res}
684 684
685 685 @LoginRequired()
686 686 @view_config(
687 687 route_name='home', request_method='GET',
688 688 renderer='rhodecode:templates/index.mako')
689 689 def main_page(self):
690 690 c = self.load_default_context()
691 691 c.repo_group = None
692 692 return self._get_template_context(c)
693 693
694 694 def _main_page_repo_groups_data(self, repo_group_id):
695 695 column_map = {
696 696 'name': 'group_name_hash',
697 697 'desc': 'group_description',
698 698 'last_change': 'updated_on',
699 699 'owner': 'user_username',
700 700 }
701 701 draw, start, limit = self._extract_chunk(self.request)
702 702 search_q, order_by, order_dir = self._extract_ordering(
703 703 self.request, column_map=column_map)
704 704 return RepoGroupModel().get_repo_groups_data_table(
705 705 draw, start, limit,
706 706 search_q, order_by, order_dir,
707 707 self._rhodecode_user, repo_group_id)
708 708
709 709 def _main_page_repos_data(self, repo_group_id):
710 710 column_map = {
711 711 'name': 'repo_name',
712 712 'desc': 'description',
713 713 'last_change': 'updated_on',
714 714 'owner': 'user_username',
715 715 }
716 716 draw, start, limit = self._extract_chunk(self.request)
717 717 search_q, order_by, order_dir = self._extract_ordering(
718 718 self.request, column_map=column_map)
719 719 return RepoModel().get_repos_data_table(
720 720 draw, start, limit,
721 721 search_q, order_by, order_dir,
722 722 self._rhodecode_user, repo_group_id)
723 723
724 724 @LoginRequired()
725 725 @view_config(
726 726 route_name='main_page_repo_groups_data',
727 727 request_method='GET', renderer='json_ext', xhr=True)
728 728 def main_page_repo_groups_data(self):
729 729 self.load_default_context()
730 730 repo_group_id = safe_int(self.request.GET.get('repo_group_id'))
731 731
732 732 if repo_group_id:
733 733 group = RepoGroup.get_or_404(repo_group_id)
734 734 _perms = AuthUser.repo_group_read_perms
735 735 if not HasRepoGroupPermissionAny(*_perms)(
736 736 group.group_name, 'user is allowed to list repo group children'):
737 737 raise HTTPNotFound()
738 738
739 739 return self._main_page_repo_groups_data(repo_group_id)
740 740
741 741 @LoginRequired()
742 742 @view_config(
743 743 route_name='main_page_repos_data',
744 744 request_method='GET', renderer='json_ext', xhr=True)
745 745 def main_page_repos_data(self):
746 746 self.load_default_context()
747 747 repo_group_id = safe_int(self.request.GET.get('repo_group_id'))
748 748
749 749 if repo_group_id:
750 750 group = RepoGroup.get_or_404(repo_group_id)
751 751 _perms = AuthUser.repo_group_read_perms
752 752 if not HasRepoGroupPermissionAny(*_perms)(
753 753 group.group_name, 'user is allowed to list repo group children'):
754 754 raise HTTPNotFound()
755 755
756 756 return self._main_page_repos_data(repo_group_id)
757 757
758 758 @LoginRequired()
759 759 @HasRepoGroupPermissionAnyDecorator(*AuthUser.repo_group_read_perms)
760 760 @view_config(
761 761 route_name='repo_group_home', request_method='GET',
762 762 renderer='rhodecode:templates/index_repo_group.mako')
763 763 @view_config(
764 764 route_name='repo_group_home_slash', request_method='GET',
765 765 renderer='rhodecode:templates/index_repo_group.mako')
766 766 def repo_group_main_page(self):
767 767 c = self.load_default_context()
768 768 c.repo_group = self.request.db_repo_group
769 769 return self._get_template_context(c)
770 770
771 771 @LoginRequired()
772 772 @CSRFRequired()
773 773 @view_config(
774 774 route_name='markup_preview', request_method='POST',
775 775 renderer='string', xhr=True)
776 776 def markup_preview(self):
777 777 # Technically a CSRF token is not needed as no state changes with this
778 778 # call. However, as this is a POST is better to have it, so automated
779 779 # tools don't flag it as potential CSRF.
780 780 # Post is required because the payload could be bigger than the maximum
781 781 # allowed by GET.
782 782
783 783 text = self.request.POST.get('text')
784 784 renderer = self.request.POST.get('renderer') or 'rst'
785 785 if text:
786 786 return h.render(text, renderer=renderer, mentions=True)
787 787 return ''
788 788
789 789 @LoginRequired()
790 790 @CSRFRequired()
791 791 @view_config(
792 792 route_name='file_preview', request_method='POST',
793 793 renderer='string', xhr=True)
794 794 def file_preview(self):
795 795 # Technically a CSRF token is not needed as no state changes with this
796 796 # call. However, as this is a POST is better to have it, so automated
797 797 # tools don't flag it as potential CSRF.
798 798 # Post is required because the payload could be bigger than the maximum
799 799 # allowed by GET.
800 800
801 801 text = self.request.POST.get('text')
802 802 file_path = self.request.POST.get('file_path')
803 803
804 804 renderer = h.renderer_from_filename(file_path)
805 805
806 806 if renderer:
807 807 return h.render(text, renderer=renderer, mentions=True)
808 808 else:
809 809 self.load_default_context()
810 810 _render = self.request.get_partial_renderer(
811 811 'rhodecode:templates/files/file_content.mako')
812 812
813 813 lines = filenode_as_lines_tokens(FileNode(file_path, text))
814 814
815 815 return _render('render_lines', lines)
816 816
817 817 @LoginRequired()
818 818 @CSRFRequired()
819 819 @view_config(
820 820 route_name='store_user_session_value', request_method='POST',
821 821 renderer='string', xhr=True)
822 822 def store_user_session_attr(self):
823 823 key = self.request.POST.get('key')
824 824 val = self.request.POST.get('val')
825 825
826 826 existing_value = self.request.session.get(key)
827 827 if existing_value != val:
828 828 self.request.session[key] = val
829 829
830 830 return 'stored:{}:{}'.format(key, val)
General Comments 0
You need to be logged in to leave comments. Login now