##// END OF EJS Templates
quick-filter: make sure we always apply IN filter query. Otherwise we can...
marcink -
r2167:23aaeb72 default
parent child Browse files
Show More

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

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