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