##// END OF EJS Templates
forbid removing yourself as beeing an admin of a group
marcink -
r3332:92dfc033 beta
parent child Browse files
Show More
@@ -1,378 +1,398 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.repos_groups
3 rhodecode.controllers.admin.repos_groups
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Repositories groups controller for RhodeCode
6 Repositories groups controller for RhodeCode
7
7
8 :created_on: Mar 23, 2010
8 :created_on: Mar 23, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import formencode
28 import formencode
29
29
30 from formencode import htmlfill
30 from formencode import htmlfill
31
31
32 from pylons import request, tmpl_context as c, url
32 from pylons import request, tmpl_context as c, url
33 from pylons.controllers.util import abort, redirect
33 from pylons.controllers.util import abort, redirect
34 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
35
35
36 from sqlalchemy.exc import IntegrityError
36 from sqlalchemy.exc import IntegrityError
37
37
38 import rhodecode
38 import rhodecode
39 from rhodecode.lib import helpers as h
39 from rhodecode.lib import helpers as h
40 from rhodecode.lib.ext_json import json
40 from rhodecode.lib.ext_json import json
41 from rhodecode.lib.auth import LoginRequired, HasPermissionAnyDecorator,\
41 from rhodecode.lib.auth import LoginRequired, HasPermissionAnyDecorator,\
42 HasReposGroupPermissionAnyDecorator, HasReposGroupPermissionAll,\
42 HasReposGroupPermissionAnyDecorator, HasReposGroupPermissionAll,\
43 HasPermissionAll
43 HasPermissionAll
44 from rhodecode.lib.base import BaseController, render
44 from rhodecode.lib.base import BaseController, render
45 from rhodecode.model.db import RepoGroup, Repository
45 from rhodecode.model.db import RepoGroup, Repository
46 from rhodecode.model.repos_group import ReposGroupModel
46 from rhodecode.model.repos_group import ReposGroupModel
47 from rhodecode.model.forms import ReposGroupForm
47 from rhodecode.model.forms import ReposGroupForm
48 from rhodecode.model.meta import Session
48 from rhodecode.model.meta import Session
49 from rhodecode.model.repo import RepoModel
49 from rhodecode.model.repo import RepoModel
50 from webob.exc import HTTPInternalServerError, HTTPNotFound
50 from webob.exc import HTTPInternalServerError, HTTPNotFound
51 from rhodecode.lib.utils2 import str2bool, safe_int
51 from rhodecode.lib.utils2 import str2bool, safe_int
52 from sqlalchemy.sql.expression import func
52 from sqlalchemy.sql.expression import func
53 from rhodecode.model.scm import GroupList
53 from rhodecode.model.scm import GroupList
54
54
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57
57
58 class ReposGroupsController(BaseController):
58 class ReposGroupsController(BaseController):
59 """REST Controller styled on the Atom Publishing Protocol"""
59 """REST Controller styled on the Atom Publishing Protocol"""
60 # To properly map this controller, ensure your config/routing.py
60 # To properly map this controller, ensure your config/routing.py
61 # file has a resource setup:
61 # file has a resource setup:
62 # map.resource('repos_group', 'repos_groups')
62 # map.resource('repos_group', 'repos_groups')
63
63
64 @LoginRequired()
64 @LoginRequired()
65 def __before__(self):
65 def __before__(self):
66 super(ReposGroupsController, self).__before__()
66 super(ReposGroupsController, self).__before__()
67
67
68 def __load_defaults(self, allow_empty_group=False, exclude_group_ids=[]):
68 def __load_defaults(self, allow_empty_group=False, exclude_group_ids=[]):
69 if HasPermissionAll('hg.admin')('group edit'):
69 if HasPermissionAll('hg.admin')('group edit'):
70 #we're global admin, we're ok and we can create TOP level groups
70 #we're global admin, we're ok and we can create TOP level groups
71 allow_empty_group = True
71 allow_empty_group = True
72
72
73 #override the choices for this form, we need to filter choices
73 #override the choices for this form, we need to filter choices
74 #and display only those we have ADMIN right
74 #and display only those we have ADMIN right
75 groups_with_admin_rights = GroupList(RepoGroup.query().all(),
75 groups_with_admin_rights = GroupList(RepoGroup.query().all(),
76 perm_set=['group.admin'])
76 perm_set=['group.admin'])
77 c.repo_groups = RepoGroup.groups_choices(groups=groups_with_admin_rights,
77 c.repo_groups = RepoGroup.groups_choices(groups=groups_with_admin_rights,
78 show_empty_group=allow_empty_group)
78 show_empty_group=allow_empty_group)
79 # exclude filtered ids
79 # exclude filtered ids
80 c.repo_groups = filter(lambda x: x[0] not in exclude_group_ids,
80 c.repo_groups = filter(lambda x: x[0] not in exclude_group_ids,
81 c.repo_groups)
81 c.repo_groups)
82 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
82 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
83 repo_model = RepoModel()
83 repo_model = RepoModel()
84 c.users_array = repo_model.get_users_js()
84 c.users_array = repo_model.get_users_js()
85 c.users_groups_array = repo_model.get_users_groups_js()
85 c.users_groups_array = repo_model.get_users_groups_js()
86
86
87 def __load_data(self, group_id):
87 def __load_data(self, group_id):
88 """
88 """
89 Load defaults settings for edit, and update
89 Load defaults settings for edit, and update
90
90
91 :param group_id:
91 :param group_id:
92 """
92 """
93 repo_group = RepoGroup.get_or_404(group_id)
93 repo_group = RepoGroup.get_or_404(group_id)
94 data = repo_group.get_dict()
94 data = repo_group.get_dict()
95 data['group_name'] = repo_group.name
95 data['group_name'] = repo_group.name
96
96
97 # fill repository users
97 # fill repository users
98 for p in repo_group.repo_group_to_perm:
98 for p in repo_group.repo_group_to_perm:
99 data.update({'u_perm_%s' % p.user.username:
99 data.update({'u_perm_%s' % p.user.username:
100 p.permission.permission_name})
100 p.permission.permission_name})
101
101
102 # fill repository groups
102 # fill repository groups
103 for p in repo_group.users_group_to_perm:
103 for p in repo_group.users_group_to_perm:
104 data.update({'g_perm_%s' % p.users_group.users_group_name:
104 data.update({'g_perm_%s' % p.users_group.users_group_name:
105 p.permission.permission_name})
105 p.permission.permission_name})
106
106
107 return data
107 return data
108
108
109 def _revoke_perms_on_yourself(self, form_result):
110 _up = filter(lambda u: c.rhodecode_user.username == u[0],
111 form_result['perms_updates'])
112 _new = filter(lambda u: c.rhodecode_user.username == u[0],
113 form_result['perms_new'])
114 if _new and _new[0][1] != 'group.admin' or _up and _up[0][1] != 'group.admin':
115 return True
116 return False
117
109 def index(self, format='html'):
118 def index(self, format='html'):
110 """GET /repos_groups: All items in the collection"""
119 """GET /repos_groups: All items in the collection"""
111 # url('repos_groups')
120 # url('repos_groups')
112 group_iter = GroupList(RepoGroup.query().all(), perm_set=['group.admin'])
121 group_iter = GroupList(RepoGroup.query().all(), perm_set=['group.admin'])
113 sk = lambda g: g.parents[0].group_name if g.parents else g.group_name
122 sk = lambda g: g.parents[0].group_name if g.parents else g.group_name
114 c.groups = sorted(group_iter, key=sk)
123 c.groups = sorted(group_iter, key=sk)
115 return render('admin/repos_groups/repos_groups_show.html')
124 return render('admin/repos_groups/repos_groups_show.html')
116
125
117 def create(self):
126 def create(self):
118 """POST /repos_groups: Create a new item"""
127 """POST /repos_groups: Create a new item"""
119 # url('repos_groups')
128 # url('repos_groups')
120
129
121 self.__load_defaults()
130 self.__load_defaults()
122
131
123 # permissions for can create group based on parent_id are checked
132 # permissions for can create group based on parent_id are checked
124 # here in the Form
133 # here in the Form
125 repos_group_form = ReposGroupForm(available_groups=
134 repos_group_form = ReposGroupForm(available_groups=
126 map(lambda k: unicode(k[0]), c.repo_groups))()
135 map(lambda k: unicode(k[0]), c.repo_groups))()
127 try:
136 try:
128 form_result = repos_group_form.to_python(dict(request.POST))
137 form_result = repos_group_form.to_python(dict(request.POST))
129 ReposGroupModel().create(
138 ReposGroupModel().create(
130 group_name=form_result['group_name'],
139 group_name=form_result['group_name'],
131 group_description=form_result['group_description'],
140 group_description=form_result['group_description'],
132 parent=form_result['group_parent_id'],
141 parent=form_result['group_parent_id'],
133 owner=self.rhodecode_user.user_id
142 owner=self.rhodecode_user.user_id
134 )
143 )
135 Session().commit()
144 Session().commit()
136 h.flash(_('created repos group %s') \
145 h.flash(_('created repos group %s') \
137 % form_result['group_name'], category='success')
146 % form_result['group_name'], category='success')
138 #TODO: in futureaction_logger(, '', '', '', self.sa)
147 #TODO: in futureaction_logger(, '', '', '', self.sa)
139 except formencode.Invalid, errors:
148 except formencode.Invalid, errors:
140 return htmlfill.render(
149 return htmlfill.render(
141 render('admin/repos_groups/repos_groups_add.html'),
150 render('admin/repos_groups/repos_groups_add.html'),
142 defaults=errors.value,
151 defaults=errors.value,
143 errors=errors.error_dict or {},
152 errors=errors.error_dict or {},
144 prefix_error=False,
153 prefix_error=False,
145 encoding="UTF-8")
154 encoding="UTF-8")
146 except Exception:
155 except Exception:
147 log.error(traceback.format_exc())
156 log.error(traceback.format_exc())
148 h.flash(_('error occurred during creation of repos group %s') \
157 h.flash(_('error occurred during creation of repos group %s') \
149 % request.POST.get('group_name'), category='error')
158 % request.POST.get('group_name'), category='error')
150 parent_group_id = form_result['group_parent_id']
159 parent_group_id = form_result['group_parent_id']
151 #TODO: maybe we should get back to the main view, not the admin one
160 #TODO: maybe we should get back to the main view, not the admin one
152 return redirect(url('repos_groups', parent_group=parent_group_id))
161 return redirect(url('repos_groups', parent_group=parent_group_id))
153
162
154 def new(self, format='html'):
163 def new(self, format='html'):
155 """GET /repos_groups/new: Form to create a new item"""
164 """GET /repos_groups/new: Form to create a new item"""
156 # url('new_repos_group')
165 # url('new_repos_group')
157 if HasPermissionAll('hg.admin')('group create'):
166 if HasPermissionAll('hg.admin')('group create'):
158 #we're global admin, we're ok and we can create TOP level groups
167 #we're global admin, we're ok and we can create TOP level groups
159 pass
168 pass
160 else:
169 else:
161 # we pass in parent group into creation form, thus we know
170 # we pass in parent group into creation form, thus we know
162 # what would be the group, we can check perms here !
171 # what would be the group, we can check perms here !
163 group_id = safe_int(request.GET.get('parent_group'))
172 group_id = safe_int(request.GET.get('parent_group'))
164 group = RepoGroup.get(group_id) if group_id else None
173 group = RepoGroup.get(group_id) if group_id else None
165 group_name = group.group_name if group else None
174 group_name = group.group_name if group else None
166 if HasReposGroupPermissionAll('group.admin')(group_name, 'group create'):
175 if HasReposGroupPermissionAll('group.admin')(group_name, 'group create'):
167 pass
176 pass
168 else:
177 else:
169 return abort(403)
178 return abort(403)
170
179
171 self.__load_defaults()
180 self.__load_defaults()
172 return render('admin/repos_groups/repos_groups_add.html')
181 return render('admin/repos_groups/repos_groups_add.html')
173
182
174 @HasReposGroupPermissionAnyDecorator('group.admin')
183 @HasReposGroupPermissionAnyDecorator('group.admin')
175 def update(self, group_name):
184 def update(self, group_name):
176 """PUT /repos_groups/group_name: Update an existing item"""
185 """PUT /repos_groups/group_name: Update an existing item"""
177 # Forms posted to this method should contain a hidden field:
186 # Forms posted to this method should contain a hidden field:
178 # <input type="hidden" name="_method" value="PUT" />
187 # <input type="hidden" name="_method" value="PUT" />
179 # Or using helpers:
188 # Or using helpers:
180 # h.form(url('repos_group', group_name=GROUP_NAME),
189 # h.form(url('repos_group', group_name=GROUP_NAME),
181 # method='put')
190 # method='put')
182 # url('repos_group', group_name=GROUP_NAME)
191 # url('repos_group', group_name=GROUP_NAME)
183
192
184 c.repos_group = ReposGroupModel()._get_repos_group(group_name)
193 c.repos_group = ReposGroupModel()._get_repos_group(group_name)
185 if HasPermissionAll('hg.admin')('group edit'):
194 if HasPermissionAll('hg.admin')('group edit'):
186 #we're global admin, we're ok and we can create TOP level groups
195 #we're global admin, we're ok and we can create TOP level groups
187 allow_empty_group = True
196 allow_empty_group = True
188 elif not c.repos_group.parent_group:
197 elif not c.repos_group.parent_group:
189 allow_empty_group = True
198 allow_empty_group = True
190 else:
199 else:
191 allow_empty_group = False
200 allow_empty_group = False
192 self.__load_defaults(allow_empty_group=allow_empty_group,
201 self.__load_defaults(allow_empty_group=allow_empty_group,
193 exclude_group_ids=[c.repos_group.group_id])
202 exclude_group_ids=[c.repos_group.group_id])
194
203
195 repos_group_form = ReposGroupForm(
204 repos_group_form = ReposGroupForm(
196 edit=True,
205 edit=True,
197 old_data=c.repos_group.get_dict(),
206 old_data=c.repos_group.get_dict(),
198 available_groups=c.repo_groups_choices,
207 available_groups=c.repo_groups_choices,
199 can_create_in_root=allow_empty_group,
208 can_create_in_root=allow_empty_group,
200 )()
209 )()
201 try:
210 try:
202 form_result = repos_group_form.to_python(dict(request.POST))
211 form_result = repos_group_form.to_python(dict(request.POST))
212 if not c.rhodecode_user.is_admin:
213 if self._revoke_perms_on_yourself(form_result):
214 msg = _('Cannot revoke permission for yourself as admin')
215 h.flash(msg, category='warning')
216 raise Exception('revoke admin permission on self')
217
203 new_gr = ReposGroupModel().update(group_name, form_result)
218 new_gr = ReposGroupModel().update(group_name, form_result)
204 Session().commit()
219 Session().commit()
205 h.flash(_('updated repos group %s') \
220 h.flash(_('updated repos group %s') \
206 % form_result['group_name'], category='success')
221 % form_result['group_name'], category='success')
207 # we now have new name !
222 # we now have new name !
208 group_name = new_gr.group_name
223 group_name = new_gr.group_name
209 #TODO: in future action_logger(, '', '', '', self.sa)
224 #TODO: in future action_logger(, '', '', '', self.sa)
210 except formencode.Invalid, errors:
225 except formencode.Invalid, errors:
211
226
212 return htmlfill.render(
227 return htmlfill.render(
213 render('admin/repos_groups/repos_groups_edit.html'),
228 render('admin/repos_groups/repos_groups_edit.html'),
214 defaults=errors.value,
229 defaults=errors.value,
215 errors=errors.error_dict or {},
230 errors=errors.error_dict or {},
216 prefix_error=False,
231 prefix_error=False,
217 encoding="UTF-8")
232 encoding="UTF-8")
218 except Exception:
233 except Exception:
219 log.error(traceback.format_exc())
234 log.error(traceback.format_exc())
220 h.flash(_('error occurred during update of repos group %s') \
235 h.flash(_('error occurred during update of repos group %s') \
221 % request.POST.get('group_name'), category='error')
236 % request.POST.get('group_name'), category='error')
222
237
223 return redirect(url('edit_repos_group', group_name=group_name))
238 return redirect(url('edit_repos_group', group_name=group_name))
224
239
225 @HasReposGroupPermissionAnyDecorator('group.admin')
240 @HasReposGroupPermissionAnyDecorator('group.admin')
226 def delete(self, group_name):
241 def delete(self, group_name):
227 """DELETE /repos_groups/group_name: Delete an existing item"""
242 """DELETE /repos_groups/group_name: Delete an existing item"""
228 # Forms posted to this method should contain a hidden field:
243 # Forms posted to this method should contain a hidden field:
229 # <input type="hidden" name="_method" value="DELETE" />
244 # <input type="hidden" name="_method" value="DELETE" />
230 # Or using helpers:
245 # Or using helpers:
231 # h.form(url('repos_group', group_name=GROUP_NAME),
246 # h.form(url('repos_group', group_name=GROUP_NAME),
232 # method='delete')
247 # method='delete')
233 # url('repos_group', group_name=GROUP_NAME)
248 # url('repos_group', group_name=GROUP_NAME)
234
249
235 gr = c.repos_group = ReposGroupModel()._get_repos_group(group_name)
250 gr = c.repos_group = ReposGroupModel()._get_repos_group(group_name)
236 repos = gr.repositories.all()
251 repos = gr.repositories.all()
237 if repos:
252 if repos:
238 h.flash(_('This group contains %s repositores and cannot be '
253 h.flash(_('This group contains %s repositores and cannot be '
239 'deleted') % len(repos),
254 'deleted') % len(repos),
240 category='error')
255 category='error')
241 return redirect(url('repos_groups'))
256 return redirect(url('repos_groups'))
242
257
243 try:
258 try:
244 ReposGroupModel().delete(group_name)
259 ReposGroupModel().delete(group_name)
245 Session().commit()
260 Session().commit()
246 h.flash(_('removed repos group %s') % gr.group_name,
261 h.flash(_('removed repos group %s') % gr.group_name,
247 category='success')
262 category='success')
248 #TODO: in future action_logger(, '', '', '', self.sa)
263 #TODO: in future action_logger(, '', '', '', self.sa)
249 except IntegrityError, e:
264 except IntegrityError, e:
250 if str(e.message).find('groups_group_parent_id_fkey') != -1:
265 if str(e.message).find('groups_group_parent_id_fkey') != -1:
251 log.error(traceback.format_exc())
266 log.error(traceback.format_exc())
252 h.flash(_('Cannot delete this group it still contains '
267 h.flash(_('Cannot delete this group it still contains '
253 'subgroups'),
268 'subgroups'),
254 category='warning')
269 category='warning')
255 else:
270 else:
256 log.error(traceback.format_exc())
271 log.error(traceback.format_exc())
257 h.flash(_('error occurred during deletion of repos '
272 h.flash(_('error occurred during deletion of repos '
258 'group %s') % gr.group_name, category='error')
273 'group %s') % gr.group_name, category='error')
259
274
260 except Exception:
275 except Exception:
261 log.error(traceback.format_exc())
276 log.error(traceback.format_exc())
262 h.flash(_('error occurred during deletion of repos '
277 h.flash(_('error occurred during deletion of repos '
263 'group %s') % gr.group_name, category='error')
278 'group %s') % gr.group_name, category='error')
264
279
265 return redirect(url('repos_groups'))
280 return redirect(url('repos_groups'))
266
281
267 @HasReposGroupPermissionAnyDecorator('group.admin')
282 @HasReposGroupPermissionAnyDecorator('group.admin')
268 def delete_repos_group_user_perm(self, group_name):
283 def delete_repos_group_user_perm(self, group_name):
269 """
284 """
270 DELETE an existing repositories group permission user
285 DELETE an existing repositories group permission user
271
286
272 :param group_name:
287 :param group_name:
273 """
288 """
274 try:
289 try:
290 if not c.rhodecode_user.is_admin:
291 if c.rhodecode_user.user_id == safe_int(request.POST['user_id']):
292 msg = _('Cannot revoke permission for yourself as admin')
293 h.flash(msg, category='warning')
294 raise Exception('revoke admin permission on self')
275 recursive = str2bool(request.POST.get('recursive', False))
295 recursive = str2bool(request.POST.get('recursive', False))
276 ReposGroupModel().delete_permission(
296 ReposGroupModel().delete_permission(
277 repos_group=group_name, obj=request.POST['user_id'],
297 repos_group=group_name, obj=request.POST['user_id'],
278 obj_type='user', recursive=recursive
298 obj_type='user', recursive=recursive
279 )
299 )
280 Session().commit()
300 Session().commit()
281 except Exception:
301 except Exception:
282 log.error(traceback.format_exc())
302 log.error(traceback.format_exc())
283 h.flash(_('An error occurred during deletion of group user'),
303 h.flash(_('An error occurred during deletion of group user'),
284 category='error')
304 category='error')
285 raise HTTPInternalServerError()
305 raise HTTPInternalServerError()
286
306
287 @HasReposGroupPermissionAnyDecorator('group.admin')
307 @HasReposGroupPermissionAnyDecorator('group.admin')
288 def delete_repos_group_users_group_perm(self, group_name):
308 def delete_repos_group_users_group_perm(self, group_name):
289 """
309 """
290 DELETE an existing repositories group permission users group
310 DELETE an existing repositories group permission users group
291
311
292 :param group_name:
312 :param group_name:
293 """
313 """
294
314
295 try:
315 try:
296 recursive = str2bool(request.POST.get('recursive', False))
316 recursive = str2bool(request.POST.get('recursive', False))
297 ReposGroupModel().delete_permission(
317 ReposGroupModel().delete_permission(
298 repos_group=group_name, obj=request.POST['users_group_id'],
318 repos_group=group_name, obj=request.POST['users_group_id'],
299 obj_type='users_group', recursive=recursive
319 obj_type='users_group', recursive=recursive
300 )
320 )
301 Session().commit()
321 Session().commit()
302 except Exception:
322 except Exception:
303 log.error(traceback.format_exc())
323 log.error(traceback.format_exc())
304 h.flash(_('An error occurred during deletion of group'
324 h.flash(_('An error occurred during deletion of group'
305 ' users groups'),
325 ' users groups'),
306 category='error')
326 category='error')
307 raise HTTPInternalServerError()
327 raise HTTPInternalServerError()
308
328
309 def show_by_name(self, group_name):
329 def show_by_name(self, group_name):
310 """
330 """
311 This is a proxy that does a lookup group_name -> id, and shows
331 This is a proxy that does a lookup group_name -> id, and shows
312 the group by id view instead
332 the group by id view instead
313 """
333 """
314 group_name = group_name.rstrip('/')
334 group_name = group_name.rstrip('/')
315 id_ = RepoGroup.get_by_group_name(group_name)
335 id_ = RepoGroup.get_by_group_name(group_name)
316 if id_:
336 if id_:
317 return self.show(id_.group_id)
337 return self.show(id_.group_id)
318 raise HTTPNotFound
338 raise HTTPNotFound
319
339
320 @HasReposGroupPermissionAnyDecorator('group.read', 'group.write',
340 @HasReposGroupPermissionAnyDecorator('group.read', 'group.write',
321 'group.admin')
341 'group.admin')
322 def show(self, group_name, format='html'):
342 def show(self, group_name, format='html'):
323 """GET /repos_groups/group_name: Show a specific item"""
343 """GET /repos_groups/group_name: Show a specific item"""
324 # url('repos_group', group_name=GROUP_NAME)
344 # url('repos_group', group_name=GROUP_NAME)
325
345
326 c.group = c.repos_group = ReposGroupModel()._get_repos_group(group_name)
346 c.group = c.repos_group = ReposGroupModel()._get_repos_group(group_name)
327 c.group_repos = c.group.repositories.all()
347 c.group_repos = c.group.repositories.all()
328
348
329 #overwrite our cached list with current filter
349 #overwrite our cached list with current filter
330 gr_filter = c.group_repos
350 gr_filter = c.group_repos
331 c.repo_cnt = 0
351 c.repo_cnt = 0
332
352
333 groups = RepoGroup.query().order_by(RepoGroup.group_name)\
353 groups = RepoGroup.query().order_by(RepoGroup.group_name)\
334 .filter(RepoGroup.group_parent_id == c.group.group_id).all()
354 .filter(RepoGroup.group_parent_id == c.group.group_id).all()
335 c.groups = self.scm_model.get_repos_groups(groups)
355 c.groups = self.scm_model.get_repos_groups(groups)
336
356
337 if c.visual.lightweight_dashboard is False:
357 if c.visual.lightweight_dashboard is False:
338 c.repos_list = self.scm_model.get_repos(all_repos=gr_filter)
358 c.repos_list = self.scm_model.get_repos(all_repos=gr_filter)
339 ## lightweight version of dashboard
359 ## lightweight version of dashboard
340 else:
360 else:
341 c.repos_list = Repository.query()\
361 c.repos_list = Repository.query()\
342 .filter(Repository.group_id == c.group.group_id)\
362 .filter(Repository.group_id == c.group.group_id)\
343 .order_by(func.lower(Repository.repo_name))\
363 .order_by(func.lower(Repository.repo_name))\
344 .all()
364 .all()
345
365
346 repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list,
366 repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list,
347 admin=False)
367 admin=False)
348 #json used to render the grid
368 #json used to render the grid
349 c.data = json.dumps(repos_data)
369 c.data = json.dumps(repos_data)
350
370
351 return render('admin/repos_groups/repos_groups.html')
371 return render('admin/repos_groups/repos_groups.html')
352
372
353 @HasReposGroupPermissionAnyDecorator('group.admin')
373 @HasReposGroupPermissionAnyDecorator('group.admin')
354 def edit(self, group_name, format='html'):
374 def edit(self, group_name, format='html'):
355 """GET /repos_groups/group_name/edit: Form to edit an existing item"""
375 """GET /repos_groups/group_name/edit: Form to edit an existing item"""
356 # url('edit_repos_group', group_name=GROUP_NAME)
376 # url('edit_repos_group', group_name=GROUP_NAME)
357
377
358 c.repos_group = ReposGroupModel()._get_repos_group(group_name)
378 c.repos_group = ReposGroupModel()._get_repos_group(group_name)
359 #we can only allow moving empty group if it's already a top-level
379 #we can only allow moving empty group if it's already a top-level
360 #group, ie has no parents, or we're admin
380 #group, ie has no parents, or we're admin
361 if HasPermissionAll('hg.admin')('group edit'):
381 if HasPermissionAll('hg.admin')('group edit'):
362 #we're global admin, we're ok and we can create TOP level groups
382 #we're global admin, we're ok and we can create TOP level groups
363 allow_empty_group = True
383 allow_empty_group = True
364 elif not c.repos_group.parent_group:
384 elif not c.repos_group.parent_group:
365 allow_empty_group = True
385 allow_empty_group = True
366 else:
386 else:
367 allow_empty_group = False
387 allow_empty_group = False
368
388
369 self.__load_defaults(allow_empty_group=allow_empty_group,
389 self.__load_defaults(allow_empty_group=allow_empty_group,
370 exclude_group_ids=[c.repos_group.group_id])
390 exclude_group_ids=[c.repos_group.group_id])
371 defaults = self.__load_data(c.repos_group.group_id)
391 defaults = self.__load_data(c.repos_group.group_id)
372
392
373 return htmlfill.render(
393 return htmlfill.render(
374 render('admin/repos_groups/repos_groups_edit.html'),
394 render('admin/repos_groups/repos_groups_edit.html'),
375 defaults=defaults,
395 defaults=defaults,
376 encoding="UTF-8",
396 encoding="UTF-8",
377 force_defaults=False
397 force_defaults=False
378 )
398 )
@@ -1,120 +1,133 b''
1 <table id="permissions_manage" class="noborder">
1 <table id="permissions_manage" class="noborder">
2 <tr>
2 <tr>
3 <td>${_('none')}</td>
3 <td>${_('none')}</td>
4 <td>${_('read')}</td>
4 <td>${_('read')}</td>
5 <td>${_('write')}</td>
5 <td>${_('write')}</td>
6 <td>${_('admin')}</td>
6 <td>${_('admin')}</td>
7 <td>${_('member')}</td>
7 <td>${_('member')}</td>
8 <td></td>
8 <td></td>
9 </tr>
9 </tr>
10 ## USERS
10 ## USERS
11 %for r2p in c.repos_group.repo_group_to_perm:
11 %for r2p in c.repos_group.repo_group_to_perm:
12 ##forbid revoking permission from yourself
12 <tr id="id${id(r2p.user.username)}">
13 <tr id="id${id(r2p.user.username)}">
14 %if c.rhodecode_user.user_id != r2p.user.user_id or c.rhodecode_user.is_admin:
13 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.none')}</td>
15 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.none')}</td>
14 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.read')}</td>
16 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.read')}</td>
15 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.write')}</td>
17 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.write')}</td>
16 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.admin')}</td>
18 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.admin')}</td>
17 <td style="white-space: nowrap;">
19 <td style="white-space: nowrap;">
18 <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>${r2p.user.username if r2p.user.username != 'default' else _('default')}
20 <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>${r2p.user.username if r2p.user.username != 'default' else _('default')}
19 </td>
21 </td>
20 <td>
22 <td>
21 %if r2p.user.username !='default':
23 %if r2p.user.username !='default':
22 <span class="delete_icon action_button" onclick="ajaxActionUser(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
24 <span class="delete_icon action_button" onclick="ajaxActionUser(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
23 ${_('revoke')}
25 ${_('revoke')}
24 </span>
26 </span>
25 %endif
27 %endif
26 </td>
28 </td>
29 %else:
30 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.none', disabled="disabled")}</td>
31 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.read', disabled="disabled")}</td>
32 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.write', disabled="disabled")}</td>
33 <td>${h.radio('u_perm_%s' % r2p.user.username,'group.admin', disabled="disabled")}</td>
34 <td style="white-space: nowrap;">
35 <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>${r2p.user.username if r2p.user.username != 'default' else _('default')}
36 </td>
37 <td>
38 </td>
39 %endif
27 </tr>
40 </tr>
28 %endfor
41 %endfor
29
42
30 ## USERS GROUPS
43 ## USERS GROUPS
31 %for g2p in c.repos_group.users_group_to_perm:
44 %for g2p in c.repos_group.users_group_to_perm:
32 <tr id="id${id(g2p.users_group.users_group_name)}">
45 <tr id="id${id(g2p.users_group.users_group_name)}">
33 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.none')}</td>
46 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.none')}</td>
34 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.read')}</td>
47 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.read')}</td>
35 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.write')}</td>
48 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.write')}</td>
36 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.admin')}</td>
49 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.admin')}</td>
37 <td style="white-space: nowrap;">
50 <td style="white-space: nowrap;">
38 <img class="perm-gravatar" src="${h.url('/images/icons/group.png')}"/>${g2p.users_group.users_group_name}
51 <img class="perm-gravatar" src="${h.url('/images/icons/group.png')}"/>${g2p.users_group.users_group_name}
39 </td>
52 </td>
40 <td>
53 <td>
41 <span class="delete_icon action_button" onclick="ajaxActionUsersGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
54 <span class="delete_icon action_button" onclick="ajaxActionUsersGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
42 ${_('revoke')}
55 ${_('revoke')}
43 </span>
56 </span>
44 </td>
57 </td>
45 </tr>
58 </tr>
46 %endfor
59 %endfor
47 <%
60 <%
48 _tmpl = h.literal("""' \
61 _tmpl = h.literal("""' \
49 <td><input type="radio" value="group.none" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
62 <td><input type="radio" value="group.none" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
50 <td><input type="radio" value="group.read" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
63 <td><input type="radio" value="group.read" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
51 <td><input type="radio" value="group.write" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
64 <td><input type="radio" value="group.write" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
52 <td><input type="radio" value="group.admin" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
65 <td><input type="radio" value="group.admin" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
53 <td class="ac"> \
66 <td class="ac"> \
54 <div class="perm_ac" id="perm_ac_{0}"> \
67 <div class="perm_ac" id="perm_ac_{0}"> \
55 <input class="yui-ac-input" id="perm_new_member_name_{0}" name="perm_new_member_name_{0}" value="" type="text"> \
68 <input class="yui-ac-input" id="perm_new_member_name_{0}" name="perm_new_member_name_{0}" value="" type="text"> \
56 <input id="perm_new_member_type_{0}" name="perm_new_member_type_{0}" value="" type="hidden"> \
69 <input id="perm_new_member_type_{0}" name="perm_new_member_type_{0}" value="" type="hidden"> \
57 <div id="perm_container_{0}"></div> \
70 <div id="perm_container_{0}"></div> \
58 </div> \
71 </div> \
59 </td> \
72 </td> \
60 <td></td>'""")
73 <td></td>'""")
61 %>
74 %>
62 ## ADD HERE DYNAMICALLY NEW INPUTS FROM THE '_tmpl'
75 ## ADD HERE DYNAMICALLY NEW INPUTS FROM THE '_tmpl'
63 <tr class="new_members last_new_member" id="add_perm_input"></tr>
76 <tr class="new_members last_new_member" id="add_perm_input"></tr>
64 <tr>
77 <tr>
65 <td colspan="6">
78 <td colspan="6">
66 <span id="add_perm" class="add_icon" style="cursor: pointer;">
79 <span id="add_perm" class="add_icon" style="cursor: pointer;">
67 ${_('Add another member')}
80 ${_('Add another member')}
68 </span>
81 </span>
69 </td>
82 </td>
70 </tr>
83 </tr>
71 <tr>
84 <tr>
72 <td colspan="6">
85 <td colspan="6">
73 ${h.checkbox('recursive',value="True", label=_('apply to children'))}
86 ${h.checkbox('recursive',value="True", label=_('apply to children'))}
74 <span class="help-block">${_('Set or revoke permission to all children of that group, including non-private repositories and other groups')}</span>
87 <span class="help-block">${_('Set or revoke permission to all children of that group, including non-private repositories and other groups')}</span>
75 </td>
88 </td>
76 </tr>
89 </tr>
77 </table>
90 </table>
78 <script type="text/javascript">
91 <script type="text/javascript">
79 function ajaxActionUser(user_id, field_id) {
92 function ajaxActionUser(user_id, field_id) {
80 var sUrl = "${h.url('delete_repos_group_user_perm',group_name=c.repos_group.group_name)}";
93 var sUrl = "${h.url('delete_repos_group_user_perm',group_name=c.repos_group.group_name)}";
81 var callback = {
94 var callback = {
82 success: function (o) {
95 success: function (o) {
83 var tr = YUD.get(String(field_id));
96 var tr = YUD.get(String(field_id));
84 tr.parentNode.removeChild(tr);
97 tr.parentNode.removeChild(tr);
85 },
98 },
86 failure: function (o) {
99 failure: function (o) {
87 alert("${_('Failed to remove user')}");
100 alert("${_('Failed to remove user')}");
88 },
101 },
89 };
102 };
90 var recursive = YUD.get('recursive').checked;
103 var recursive = YUD.get('recursive').checked;
91 var postData = '_method=delete&recursive={0}&user_id={1}'.format(recursive,user_id);
104 var postData = '_method=delete&recursive={0}&user_id={1}'.format(recursive,user_id);
92 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
105 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
93 };
106 };
94
107
95 function ajaxActionUsersGroup(users_group_id,field_id){
108 function ajaxActionUsersGroup(users_group_id,field_id){
96 var sUrl = "${h.url('delete_repos_group_users_group_perm',group_name=c.repos_group.group_name)}";
109 var sUrl = "${h.url('delete_repos_group_users_group_perm',group_name=c.repos_group.group_name)}";
97 var callback = {
110 var callback = {
98 success:function(o){
111 success:function(o){
99 var tr = YUD.get(String(field_id));
112 var tr = YUD.get(String(field_id));
100 tr.parentNode.removeChild(tr);
113 tr.parentNode.removeChild(tr);
101 },
114 },
102 failure:function(o){
115 failure:function(o){
103 alert("${_('Failed to remove users group')}");
116 alert("${_('Failed to remove users group')}");
104 },
117 },
105 };
118 };
106 var recursive = YUD.get('recursive').checked;
119 var recursive = YUD.get('recursive').checked;
107 var postData = '_method=delete&recursive={0}&users_group_id={1}'.format(recursive,users_group_id);
120 var postData = '_method=delete&recursive={0}&users_group_id={1}'.format(recursive,users_group_id);
108 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
121 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
109 };
122 };
110
123
111 YUE.onDOMReady(function () {
124 YUE.onDOMReady(function () {
112 if (!YUD.hasClass('perm_new_member_name', 'error')) {
125 if (!YUD.hasClass('perm_new_member_name', 'error')) {
113 YUD.setStyle('add_perm_input', 'display', 'none');
126 YUD.setStyle('add_perm_input', 'display', 'none');
114 }
127 }
115 YAHOO.util.Event.addListener('add_perm', 'click', function () {
128 YAHOO.util.Event.addListener('add_perm', 'click', function () {
116 addPermAction(${_tmpl}, ${c.users_array|n}, ${c.users_groups_array|n});
129 addPermAction(${_tmpl}, ${c.users_array|n}, ${c.users_groups_array|n});
117 });
130 });
118 });
131 });
119
132
120 </script>
133 </script>
General Comments 0
You need to be logged in to leave comments. Login now