##// END OF EJS Templates
db: prevent empty IN queries that generally are performance problem, and triggers sql warnings.
marcink -
r2176:d21fb0df default
parent child Browse files
Show More
@@ -1,247 +1,247 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 logging
21 import logging
22
22
23 import formencode
23 import formencode
24 import formencode.htmlfill
24 import formencode.htmlfill
25
25
26 from pyramid.httpexceptions import HTTPFound
26 from pyramid.httpexceptions import HTTPFound
27 from pyramid.view import view_config
27 from pyramid.view import view_config
28 from pyramid.response import Response
28 from pyramid.response import Response
29 from pyramid.renderers import render
29 from pyramid.renderers import render
30
30
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
32 from rhodecode.lib.auth import (
32 from rhodecode.lib.auth import (
33 LoginRequired, NotAnonymous, CSRFRequired, HasPermissionAnyDecorator)
33 LoginRequired, NotAnonymous, CSRFRequired, HasPermissionAnyDecorator)
34 from rhodecode.lib import helpers as h, audit_logger
34 from rhodecode.lib import helpers as h, audit_logger
35 from rhodecode.lib.utils2 import safe_unicode
35 from rhodecode.lib.utils2 import safe_unicode
36
36
37 from rhodecode.model.forms import UserGroupForm
37 from rhodecode.model.forms import UserGroupForm
38 from rhodecode.model.permission import PermissionModel
38 from rhodecode.model.permission import PermissionModel
39 from rhodecode.model.scm import UserGroupList
39 from rhodecode.model.scm import UserGroupList
40 from rhodecode.model.db import (
40 from rhodecode.model.db import (
41 or_, count, User, UserGroup, UserGroupMember)
41 or_, count, User, UserGroup, UserGroupMember)
42 from rhodecode.model.meta import Session
42 from rhodecode.model.meta import Session
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 AdminUserGroupsView(BaseAppView, DataGridAppView):
48 class AdminUserGroupsView(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
52
53 PermissionModel().set_global_permission_choices(
53 PermissionModel().set_global_permission_choices(
54 c, gettext_translator=self.request.translate)
54 c, gettext_translator=self.request.translate)
55
55
56 self._register_global_c(c)
56 self._register_global_c(c)
57 return c
57 return c
58
58
59 # permission check in data loading of
59 # permission check in data loading of
60 # `user_groups_list_data` via UserGroupList
60 # `user_groups_list_data` via UserGroupList
61 @LoginRequired()
61 @LoginRequired()
62 @NotAnonymous()
62 @NotAnonymous()
63 @view_config(
63 @view_config(
64 route_name='user_groups', request_method='GET',
64 route_name='user_groups', request_method='GET',
65 renderer='rhodecode:templates/admin/user_groups/user_groups.mako')
65 renderer='rhodecode:templates/admin/user_groups/user_groups.mako')
66 def user_groups_list(self):
66 def user_groups_list(self):
67 c = self.load_default_context()
67 c = self.load_default_context()
68 return self._get_template_context(c)
68 return self._get_template_context(c)
69
69
70 # permission check inside
70 # permission check inside
71 @LoginRequired()
71 @LoginRequired()
72 @NotAnonymous()
72 @NotAnonymous()
73 @view_config(
73 @view_config(
74 route_name='user_groups_data', request_method='GET',
74 route_name='user_groups_data', request_method='GET',
75 renderer='json_ext', xhr=True)
75 renderer='json_ext', xhr=True)
76 def user_groups_list_data(self):
76 def user_groups_list_data(self):
77 column_map = {
77 column_map = {
78 'active': 'users_group_active',
78 'active': 'users_group_active',
79 'description': 'user_group_description',
79 'description': 'user_group_description',
80 'members': 'members_total',
80 'members': 'members_total',
81 'owner': 'user_username',
81 'owner': 'user_username',
82 'sync': 'group_data'
82 'sync': 'group_data'
83 }
83 }
84 draw, start, limit = self._extract_chunk(self.request)
84 draw, start, limit = self._extract_chunk(self.request)
85 search_q, order_by, order_dir = self._extract_ordering(
85 search_q, order_by, order_dir = self._extract_ordering(
86 self.request, column_map=column_map)
86 self.request, column_map=column_map)
87
87
88 _render = self.request.get_partial_renderer(
88 _render = self.request.get_partial_renderer(
89 'data_table/_dt_elements.mako')
89 'data_table/_dt_elements.mako')
90
90
91 def user_group_name(user_group_id, user_group_name):
91 def user_group_name(user_group_id, user_group_name):
92 return _render("user_group_name", user_group_id, user_group_name)
92 return _render("user_group_name", user_group_id, user_group_name)
93
93
94 def user_group_actions(user_group_id, user_group_name):
94 def user_group_actions(user_group_id, user_group_name):
95 return _render("user_group_actions", user_group_id, user_group_name)
95 return _render("user_group_actions", user_group_id, user_group_name)
96
96
97 def user_profile(username):
97 def user_profile(username):
98 return _render('user_profile', username)
98 return _render('user_profile', username)
99
99
100 auth_user_group_list = UserGroupList(
100 auth_user_group_list = UserGroupList(
101 UserGroup.query().all(), perm_set=['usergroup.admin'])
101 UserGroup.query().all(), perm_set=['usergroup.admin'])
102
102
103 allowed_ids = []
103 allowed_ids = [-1]
104 for user_group in auth_user_group_list:
104 for user_group in auth_user_group_list:
105 allowed_ids.append(user_group.users_group_id)
105 allowed_ids.append(user_group.users_group_id)
106
106
107 user_groups_data_total_count = UserGroup.query()\
107 user_groups_data_total_count = UserGroup.query()\
108 .filter(UserGroup.users_group_id.in_(allowed_ids))\
108 .filter(UserGroup.users_group_id.in_(allowed_ids))\
109 .count()
109 .count()
110
110
111 member_count = count(UserGroupMember.user_id)
111 member_count = count(UserGroupMember.user_id)
112 base_q = Session.query(
112 base_q = Session.query(
113 UserGroup.users_group_name,
113 UserGroup.users_group_name,
114 UserGroup.user_group_description,
114 UserGroup.user_group_description,
115 UserGroup.users_group_active,
115 UserGroup.users_group_active,
116 UserGroup.users_group_id,
116 UserGroup.users_group_id,
117 UserGroup.group_data,
117 UserGroup.group_data,
118 User,
118 User,
119 member_count.label('member_count')
119 member_count.label('member_count')
120 ) \
120 ) \
121 .filter(UserGroup.users_group_id.in_(allowed_ids)) \
121 .filter(UserGroup.users_group_id.in_(allowed_ids)) \
122 .outerjoin(UserGroupMember) \
122 .outerjoin(UserGroupMember) \
123 .join(User, User.user_id == UserGroup.user_id) \
123 .join(User, User.user_id == UserGroup.user_id) \
124 .group_by(UserGroup, User)
124 .group_by(UserGroup, User)
125
125
126 if search_q:
126 if search_q:
127 like_expression = u'%{}%'.format(safe_unicode(search_q))
127 like_expression = u'%{}%'.format(safe_unicode(search_q))
128 base_q = base_q.filter(or_(
128 base_q = base_q.filter(or_(
129 UserGroup.users_group_name.ilike(like_expression),
129 UserGroup.users_group_name.ilike(like_expression),
130 ))
130 ))
131
131
132 user_groups_data_total_filtered_count = base_q.count()
132 user_groups_data_total_filtered_count = base_q.count()
133
133
134 if order_by == 'members_total':
134 if order_by == 'members_total':
135 sort_col = member_count
135 sort_col = member_count
136 elif order_by == 'user_username':
136 elif order_by == 'user_username':
137 sort_col = User.username
137 sort_col = User.username
138 else:
138 else:
139 sort_col = getattr(UserGroup, order_by, None)
139 sort_col = getattr(UserGroup, order_by, None)
140
140
141 if isinstance(sort_col, count) or sort_col:
141 if isinstance(sort_col, count) or sort_col:
142 if order_dir == 'asc':
142 if order_dir == 'asc':
143 sort_col = sort_col.asc()
143 sort_col = sort_col.asc()
144 else:
144 else:
145 sort_col = sort_col.desc()
145 sort_col = sort_col.desc()
146
146
147 base_q = base_q.order_by(sort_col)
147 base_q = base_q.order_by(sort_col)
148 base_q = base_q.offset(start).limit(limit)
148 base_q = base_q.offset(start).limit(limit)
149
149
150 # authenticated access to user groups
150 # authenticated access to user groups
151 auth_user_group_list = base_q.all()
151 auth_user_group_list = base_q.all()
152
152
153 user_groups_data = []
153 user_groups_data = []
154 for user_gr in auth_user_group_list:
154 for user_gr in auth_user_group_list:
155 user_groups_data.append({
155 user_groups_data.append({
156 "users_group_name": user_group_name(
156 "users_group_name": user_group_name(
157 user_gr.users_group_id, h.escape(user_gr.users_group_name)),
157 user_gr.users_group_id, h.escape(user_gr.users_group_name)),
158 "name_raw": h.escape(user_gr.users_group_name),
158 "name_raw": h.escape(user_gr.users_group_name),
159 "description": h.escape(user_gr.user_group_description),
159 "description": h.escape(user_gr.user_group_description),
160 "members": user_gr.member_count,
160 "members": user_gr.member_count,
161 # NOTE(marcink): because of advanced query we
161 # NOTE(marcink): because of advanced query we
162 # need to load it like that
162 # need to load it like that
163 "sync": UserGroup._load_group_data(
163 "sync": UserGroup._load_group_data(
164 user_gr.group_data).get('extern_type'),
164 user_gr.group_data).get('extern_type'),
165 "active": h.bool2icon(user_gr.users_group_active),
165 "active": h.bool2icon(user_gr.users_group_active),
166 "owner": user_profile(user_gr.User.username),
166 "owner": user_profile(user_gr.User.username),
167 "action": user_group_actions(
167 "action": user_group_actions(
168 user_gr.users_group_id, user_gr.users_group_name)
168 user_gr.users_group_id, user_gr.users_group_name)
169 })
169 })
170
170
171 data = ({
171 data = ({
172 'draw': draw,
172 'draw': draw,
173 'data': user_groups_data,
173 'data': user_groups_data,
174 'recordsTotal': user_groups_data_total_count,
174 'recordsTotal': user_groups_data_total_count,
175 'recordsFiltered': user_groups_data_total_filtered_count,
175 'recordsFiltered': user_groups_data_total_filtered_count,
176 })
176 })
177
177
178 return data
178 return data
179
179
180 @LoginRequired()
180 @LoginRequired()
181 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
181 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
182 @view_config(
182 @view_config(
183 route_name='user_groups_new', request_method='GET',
183 route_name='user_groups_new', request_method='GET',
184 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
184 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
185 def user_groups_new(self):
185 def user_groups_new(self):
186 c = self.load_default_context()
186 c = self.load_default_context()
187 return self._get_template_context(c)
187 return self._get_template_context(c)
188
188
189 @LoginRequired()
189 @LoginRequired()
190 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
190 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
191 @CSRFRequired()
191 @CSRFRequired()
192 @view_config(
192 @view_config(
193 route_name='user_groups_create', request_method='POST',
193 route_name='user_groups_create', request_method='POST',
194 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
194 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
195 def user_groups_create(self):
195 def user_groups_create(self):
196 _ = self.request.translate
196 _ = self.request.translate
197 c = self.load_default_context()
197 c = self.load_default_context()
198 users_group_form = UserGroupForm()()
198 users_group_form = UserGroupForm()()
199
199
200 user_group_name = self.request.POST.get('users_group_name')
200 user_group_name = self.request.POST.get('users_group_name')
201 try:
201 try:
202 form_result = users_group_form.to_python(dict(self.request.POST))
202 form_result = users_group_form.to_python(dict(self.request.POST))
203 user_group = UserGroupModel().create(
203 user_group = UserGroupModel().create(
204 name=form_result['users_group_name'],
204 name=form_result['users_group_name'],
205 description=form_result['user_group_description'],
205 description=form_result['user_group_description'],
206 owner=self._rhodecode_user.user_id,
206 owner=self._rhodecode_user.user_id,
207 active=form_result['users_group_active'])
207 active=form_result['users_group_active'])
208 Session().flush()
208 Session().flush()
209 creation_data = user_group.get_api_data()
209 creation_data = user_group.get_api_data()
210 user_group_name = form_result['users_group_name']
210 user_group_name = form_result['users_group_name']
211
211
212 audit_logger.store_web(
212 audit_logger.store_web(
213 'user_group.create', action_data={'data': creation_data},
213 'user_group.create', action_data={'data': creation_data},
214 user=self._rhodecode_user)
214 user=self._rhodecode_user)
215
215
216 user_group_link = h.link_to(
216 user_group_link = h.link_to(
217 h.escape(user_group_name),
217 h.escape(user_group_name),
218 h.route_path(
218 h.route_path(
219 'edit_user_group', user_group_id=user_group.users_group_id))
219 'edit_user_group', user_group_id=user_group.users_group_id))
220 h.flash(h.literal(_('Created user group %(user_group_link)s')
220 h.flash(h.literal(_('Created user group %(user_group_link)s')
221 % {'user_group_link': user_group_link}),
221 % {'user_group_link': user_group_link}),
222 category='success')
222 category='success')
223 Session().commit()
223 Session().commit()
224 user_group_id = user_group.users_group_id
224 user_group_id = user_group.users_group_id
225 except formencode.Invalid as errors:
225 except formencode.Invalid as errors:
226
226
227 data = render(
227 data = render(
228 'rhodecode:templates/admin/user_groups/user_group_add.mako',
228 'rhodecode:templates/admin/user_groups/user_group_add.mako',
229 self._get_template_context(c), self.request)
229 self._get_template_context(c), self.request)
230 html = formencode.htmlfill.render(
230 html = formencode.htmlfill.render(
231 data,
231 data,
232 defaults=errors.value,
232 defaults=errors.value,
233 errors=errors.error_dict or {},
233 errors=errors.error_dict or {},
234 prefix_error=False,
234 prefix_error=False,
235 encoding="UTF-8",
235 encoding="UTF-8",
236 force_defaults=False
236 force_defaults=False
237 )
237 )
238 return Response(html)
238 return Response(html)
239
239
240 except Exception:
240 except Exception:
241 log.exception("Exception creating user group")
241 log.exception("Exception creating user group")
242 h.flash(_('Error occurred during creation of user group %s') \
242 h.flash(_('Error occurred during creation of user group %s') \
243 % user_group_name, category='error')
243 % user_group_name, category='error')
244 raise HTTPFound(h.route_path('user_groups_new'))
244 raise HTTPFound(h.route_path('user_groups_new'))
245
245
246 raise HTTPFound(
246 raise HTTPFound(
247 h.route_path('edit_user_group', user_group_id=user_group_id))
247 h.route_path('edit_user_group', user_group_id=user_group_id))
@@ -1,258 +1,258 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2017 RhodeCode GmbH
3 # Copyright (C) 2011-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 logging
21 import logging
22 import datetime
22 import datetime
23 import formencode
23 import formencode
24 import formencode.htmlfill
24 import formencode.htmlfill
25
25
26 from pyramid.httpexceptions import HTTPFound
26 from pyramid.httpexceptions import HTTPFound
27 from pyramid.view import view_config
27 from pyramid.view import view_config
28 from pyramid.renderers import render
28 from pyramid.renderers import render
29 from pyramid.response import Response
29 from pyramid.response import Response
30
30
31 from rhodecode.apps._base import RepoAppView, DataGridAppView
31 from rhodecode.apps._base import RepoAppView, DataGridAppView
32 from rhodecode.lib.auth import (
32 from rhodecode.lib.auth import (
33 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous,
33 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous,
34 HasRepoPermissionAny, HasPermissionAnyDecorator, CSRFRequired)
34 HasRepoPermissionAny, HasPermissionAnyDecorator, CSRFRequired)
35 import rhodecode.lib.helpers as h
35 import rhodecode.lib.helpers as h
36 from rhodecode.model.db import coalesce, or_, Repository, RepoGroup
36 from rhodecode.model.db import coalesce, or_, Repository, RepoGroup
37 from rhodecode.model.repo import RepoModel
37 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.forms import RepoForkForm
38 from rhodecode.model.forms import RepoForkForm
39 from rhodecode.model.scm import ScmModel, RepoGroupList
39 from rhodecode.model.scm import ScmModel, RepoGroupList
40 from rhodecode.lib.utils2 import safe_int, safe_unicode
40 from rhodecode.lib.utils2 import safe_int, safe_unicode
41
41
42 log = logging.getLogger(__name__)
42 log = logging.getLogger(__name__)
43
43
44
44
45 class RepoForksView(RepoAppView, DataGridAppView):
45 class RepoForksView(RepoAppView, DataGridAppView):
46
46
47 def load_default_context(self):
47 def load_default_context(self):
48 c = self._get_local_tmpl_context(include_app_defaults=True)
48 c = self._get_local_tmpl_context(include_app_defaults=True)
49 c.rhodecode_repo = self.rhodecode_vcs_repo
49 c.rhodecode_repo = self.rhodecode_vcs_repo
50
50
51 acl_groups = RepoGroupList(
51 acl_groups = RepoGroupList(
52 RepoGroup.query().all(),
52 RepoGroup.query().all(),
53 perm_set=['group.write', 'group.admin'])
53 perm_set=['group.write', 'group.admin'])
54 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
54 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
55 c.repo_groups_choices = map(lambda k: safe_unicode(k[0]), c.repo_groups)
55 c.repo_groups_choices = map(lambda k: safe_unicode(k[0]), c.repo_groups)
56 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
56 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
57 c.landing_revs_choices = choices
57 c.landing_revs_choices = choices
58 c.personal_repo_group = c.rhodecode_user.personal_repo_group
58 c.personal_repo_group = c.rhodecode_user.personal_repo_group
59
59
60 self._register_global_c(c)
60 self._register_global_c(c)
61 return c
61 return c
62
62
63 @LoginRequired()
63 @LoginRequired()
64 @HasRepoPermissionAnyDecorator(
64 @HasRepoPermissionAnyDecorator(
65 'repository.read', 'repository.write', 'repository.admin')
65 'repository.read', 'repository.write', 'repository.admin')
66 @view_config(
66 @view_config(
67 route_name='repo_forks_show_all', request_method='GET',
67 route_name='repo_forks_show_all', request_method='GET',
68 renderer='rhodecode:templates/forks/forks.mako')
68 renderer='rhodecode:templates/forks/forks.mako')
69 def repo_forks_show_all(self):
69 def repo_forks_show_all(self):
70 c = self.load_default_context()
70 c = self.load_default_context()
71 return self._get_template_context(c)
71 return self._get_template_context(c)
72
72
73 @LoginRequired()
73 @LoginRequired()
74 @HasRepoPermissionAnyDecorator(
74 @HasRepoPermissionAnyDecorator(
75 'repository.read', 'repository.write', 'repository.admin')
75 'repository.read', 'repository.write', 'repository.admin')
76 @view_config(
76 @view_config(
77 route_name='repo_forks_data', request_method='GET',
77 route_name='repo_forks_data', request_method='GET',
78 renderer='json_ext', xhr=True)
78 renderer='json_ext', xhr=True)
79 def repo_forks_data(self):
79 def repo_forks_data(self):
80 _ = self.request.translate
80 _ = self.request.translate
81 column_map = {
81 column_map = {
82 'fork_name': 'repo_name',
82 'fork_name': 'repo_name',
83 'fork_date': 'created_on',
83 'fork_date': 'created_on',
84 'last_activity': 'updated_on'
84 'last_activity': 'updated_on'
85 }
85 }
86 draw, start, limit = self._extract_chunk(self.request)
86 draw, start, limit = self._extract_chunk(self.request)
87 search_q, order_by, order_dir = self._extract_ordering(
87 search_q, order_by, order_dir = self._extract_ordering(
88 self.request, column_map=column_map)
88 self.request, column_map=column_map)
89
89
90 acl_check = HasRepoPermissionAny(
90 acl_check = HasRepoPermissionAny(
91 'repository.read', 'repository.write', 'repository.admin')
91 'repository.read', 'repository.write', 'repository.admin')
92 repo_id = self.db_repo.repo_id
92 repo_id = self.db_repo.repo_id
93 allowed_ids = []
93 allowed_ids = [-1]
94 for f in Repository.query().filter(Repository.fork_id == repo_id):
94 for f in Repository.query().filter(Repository.fork_id == repo_id):
95 if acl_check(f.repo_name, 'get forks check'):
95 if acl_check(f.repo_name, 'get forks check'):
96 allowed_ids.append(f.repo_id)
96 allowed_ids.append(f.repo_id)
97
97
98 forks_data_total_count = Repository.query()\
98 forks_data_total_count = Repository.query()\
99 .filter(Repository.fork_id == repo_id)\
99 .filter(Repository.fork_id == repo_id)\
100 .filter(Repository.repo_id.in_(allowed_ids))\
100 .filter(Repository.repo_id.in_(allowed_ids))\
101 .count()
101 .count()
102
102
103 # json generate
103 # json generate
104 base_q = Repository.query()\
104 base_q = Repository.query()\
105 .filter(Repository.fork_id == repo_id)\
105 .filter(Repository.fork_id == repo_id)\
106 .filter(Repository.repo_id.in_(allowed_ids))\
106 .filter(Repository.repo_id.in_(allowed_ids))\
107
107
108 if search_q:
108 if search_q:
109 like_expression = u'%{}%'.format(safe_unicode(search_q))
109 like_expression = u'%{}%'.format(safe_unicode(search_q))
110 base_q = base_q.filter(or_(
110 base_q = base_q.filter(or_(
111 Repository.repo_name.ilike(like_expression),
111 Repository.repo_name.ilike(like_expression),
112 Repository.description.ilike(like_expression),
112 Repository.description.ilike(like_expression),
113 ))
113 ))
114
114
115 forks_data_total_filtered_count = base_q.count()
115 forks_data_total_filtered_count = base_q.count()
116
116
117 sort_col = getattr(Repository, order_by, None)
117 sort_col = getattr(Repository, order_by, None)
118 if sort_col:
118 if sort_col:
119 if order_dir == 'asc':
119 if order_dir == 'asc':
120 # handle null values properly to order by NULL last
120 # handle null values properly to order by NULL last
121 if order_by in ['last_activity']:
121 if order_by in ['last_activity']:
122 sort_col = coalesce(sort_col, datetime.date.max)
122 sort_col = coalesce(sort_col, datetime.date.max)
123 sort_col = sort_col.asc()
123 sort_col = sort_col.asc()
124 else:
124 else:
125 # handle null values properly to order by NULL last
125 # handle null values properly to order by NULL last
126 if order_by in ['last_activity']:
126 if order_by in ['last_activity']:
127 sort_col = coalesce(sort_col, datetime.date.min)
127 sort_col = coalesce(sort_col, datetime.date.min)
128 sort_col = sort_col.desc()
128 sort_col = sort_col.desc()
129
129
130 base_q = base_q.order_by(sort_col)
130 base_q = base_q.order_by(sort_col)
131 base_q = base_q.offset(start).limit(limit)
131 base_q = base_q.offset(start).limit(limit)
132
132
133 fork_list = base_q.all()
133 fork_list = base_q.all()
134
134
135 def fork_actions(fork):
135 def fork_actions(fork):
136 url_link = h.route_path(
136 url_link = h.route_path(
137 'repo_compare',
137 'repo_compare',
138 repo_name=fork.repo_name,
138 repo_name=fork.repo_name,
139 source_ref_type=self.db_repo.landing_rev[0],
139 source_ref_type=self.db_repo.landing_rev[0],
140 source_ref=self.db_repo.landing_rev[1],
140 source_ref=self.db_repo.landing_rev[1],
141 target_ref_type=self.db_repo.landing_rev[0],
141 target_ref_type=self.db_repo.landing_rev[0],
142 target_ref=self.db_repo.landing_rev[1],
142 target_ref=self.db_repo.landing_rev[1],
143 _query=dict(merge=1, target_repo=f.repo_name))
143 _query=dict(merge=1, target_repo=f.repo_name))
144 return h.link_to(_('Compare fork'), url_link, class_='btn-link')
144 return h.link_to(_('Compare fork'), url_link, class_='btn-link')
145
145
146 def fork_name(fork):
146 def fork_name(fork):
147 return h.link_to(fork.repo_name,
147 return h.link_to(fork.repo_name,
148 h.route_path('repo_summary', repo_name=fork.repo_name))
148 h.route_path('repo_summary', repo_name=fork.repo_name))
149
149
150 forks_data = []
150 forks_data = []
151 for fork in fork_list:
151 for fork in fork_list:
152 forks_data.append({
152 forks_data.append({
153 "username": h.gravatar_with_user(self.request, fork.user.username),
153 "username": h.gravatar_with_user(self.request, fork.user.username),
154 "fork_name": fork_name(fork),
154 "fork_name": fork_name(fork),
155 "description": fork.description,
155 "description": fork.description,
156 "fork_date": h.age_component(fork.created_on, time_is_local=True),
156 "fork_date": h.age_component(fork.created_on, time_is_local=True),
157 "last_activity": h.format_date(fork.updated_on),
157 "last_activity": h.format_date(fork.updated_on),
158 "action": fork_actions(fork),
158 "action": fork_actions(fork),
159 })
159 })
160
160
161 data = ({
161 data = ({
162 'draw': draw,
162 'draw': draw,
163 'data': forks_data,
163 'data': forks_data,
164 'recordsTotal': forks_data_total_count,
164 'recordsTotal': forks_data_total_count,
165 'recordsFiltered': forks_data_total_filtered_count,
165 'recordsFiltered': forks_data_total_filtered_count,
166 })
166 })
167
167
168 return data
168 return data
169
169
170 @LoginRequired()
170 @LoginRequired()
171 @NotAnonymous()
171 @NotAnonymous()
172 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
172 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
173 @HasRepoPermissionAnyDecorator(
173 @HasRepoPermissionAnyDecorator(
174 'repository.read', 'repository.write', 'repository.admin')
174 'repository.read', 'repository.write', 'repository.admin')
175 @view_config(
175 @view_config(
176 route_name='repo_fork_new', request_method='GET',
176 route_name='repo_fork_new', request_method='GET',
177 renderer='rhodecode:templates/forks/forks.mako')
177 renderer='rhodecode:templates/forks/forks.mako')
178 def repo_fork_new(self):
178 def repo_fork_new(self):
179 c = self.load_default_context()
179 c = self.load_default_context()
180
180
181 defaults = RepoModel()._get_defaults(self.db_repo_name)
181 defaults = RepoModel()._get_defaults(self.db_repo_name)
182 # alter the description to indicate a fork
182 # alter the description to indicate a fork
183 defaults['description'] = (
183 defaults['description'] = (
184 'fork of repository: %s \n%s' % (
184 'fork of repository: %s \n%s' % (
185 defaults['repo_name'], defaults['description']))
185 defaults['repo_name'], defaults['description']))
186 # add suffix to fork
186 # add suffix to fork
187 defaults['repo_name'] = '%s-fork' % defaults['repo_name']
187 defaults['repo_name'] = '%s-fork' % defaults['repo_name']
188
188
189 data = render('rhodecode:templates/forks/fork.mako',
189 data = render('rhodecode:templates/forks/fork.mako',
190 self._get_template_context(c), self.request)
190 self._get_template_context(c), self.request)
191 html = formencode.htmlfill.render(
191 html = formencode.htmlfill.render(
192 data,
192 data,
193 defaults=defaults,
193 defaults=defaults,
194 encoding="UTF-8",
194 encoding="UTF-8",
195 force_defaults=False
195 force_defaults=False
196 )
196 )
197 return Response(html)
197 return Response(html)
198
198
199 @LoginRequired()
199 @LoginRequired()
200 @NotAnonymous()
200 @NotAnonymous()
201 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
201 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
202 @HasRepoPermissionAnyDecorator(
202 @HasRepoPermissionAnyDecorator(
203 'repository.read', 'repository.write', 'repository.admin')
203 'repository.read', 'repository.write', 'repository.admin')
204 @CSRFRequired()
204 @CSRFRequired()
205 @view_config(
205 @view_config(
206 route_name='repo_fork_create', request_method='POST',
206 route_name='repo_fork_create', request_method='POST',
207 renderer='rhodecode:templates/forks/fork.mako')
207 renderer='rhodecode:templates/forks/fork.mako')
208 def repo_fork_create(self):
208 def repo_fork_create(self):
209 _ = self.request.translate
209 _ = self.request.translate
210 c = self.load_default_context()
210 c = self.load_default_context()
211
211
212 _form = RepoForkForm(old_data={'repo_type': self.db_repo.repo_type},
212 _form = RepoForkForm(old_data={'repo_type': self.db_repo.repo_type},
213 repo_groups=c.repo_groups_choices,
213 repo_groups=c.repo_groups_choices,
214 landing_revs=c.landing_revs_choices)()
214 landing_revs=c.landing_revs_choices)()
215 post_data = dict(self.request.POST)
215 post_data = dict(self.request.POST)
216
216
217 # forbid injecting other repo by forging a request
217 # forbid injecting other repo by forging a request
218 post_data['fork_parent_id'] = self.db_repo.repo_id
218 post_data['fork_parent_id'] = self.db_repo.repo_id
219
219
220 form_result = {}
220 form_result = {}
221 task_id = None
221 task_id = None
222 try:
222 try:
223 form_result = _form.to_python(post_data)
223 form_result = _form.to_python(post_data)
224 # create fork is done sometimes async on celery, db transaction
224 # create fork is done sometimes async on celery, db transaction
225 # management is handled there.
225 # management is handled there.
226 task = RepoModel().create_fork(
226 task = RepoModel().create_fork(
227 form_result, c.rhodecode_user.user_id)
227 form_result, c.rhodecode_user.user_id)
228 from celery.result import BaseAsyncResult
228 from celery.result import BaseAsyncResult
229 if isinstance(task, BaseAsyncResult):
229 if isinstance(task, BaseAsyncResult):
230 task_id = task.task_id
230 task_id = task.task_id
231 except formencode.Invalid as errors:
231 except formencode.Invalid as errors:
232 c.rhodecode_db_repo = self.db_repo
232 c.rhodecode_db_repo = self.db_repo
233
233
234 data = render('rhodecode:templates/forks/fork.mako',
234 data = render('rhodecode:templates/forks/fork.mako',
235 self._get_template_context(c), self.request)
235 self._get_template_context(c), self.request)
236 html = formencode.htmlfill.render(
236 html = formencode.htmlfill.render(
237 data,
237 data,
238 defaults=errors.value,
238 defaults=errors.value,
239 errors=errors.error_dict or {},
239 errors=errors.error_dict or {},
240 prefix_error=False,
240 prefix_error=False,
241 encoding="UTF-8",
241 encoding="UTF-8",
242 force_defaults=False
242 force_defaults=False
243 )
243 )
244 return Response(html)
244 return Response(html)
245 except Exception:
245 except Exception:
246 log.exception(
246 log.exception(
247 u'Exception while trying to fork the repository %s',
247 u'Exception while trying to fork the repository %s',
248 self.db_repo_name)
248 self.db_repo_name)
249 msg = (
249 msg = (
250 _('An error occurred during repository forking %s') % (
250 _('An error occurred during repository forking %s') % (
251 self.db_repo_name, ))
251 self.db_repo_name, ))
252 h.flash(msg, category='error')
252 h.flash(msg, category='error')
253
253
254 repo_name = form_result.get('repo_name_full', self.db_repo_name)
254 repo_name = form_result.get('repo_name_full', self.db_repo_name)
255 raise HTTPFound(
255 raise HTTPFound(
256 h.route_path('repo_creating',
256 h.route_path('repo_creating',
257 repo_name=repo_name,
257 repo_name=repo_name,
258 _query=dict(task_id=task_id)))
258 _query=dict(task_id=task_id)))
General Comments 0
You need to be logged in to leave comments. Login now