##// END OF EJS Templates
Group management delegation:...
marcink -
r3222:b4daef4c beta
parent child Browse files
Show More
@@ -54,7 +54,6 b' def make_map(config):'
54 54 :param match_dict:
55 55 """
56 56 repos_group_name = match_dict.get('group_name')
57
58 57 return is_valid_repos_group(repos_group_name, config['base_path'])
59 58
60 59 def check_int(environ, match_dict):
@@ -158,33 +157,33 b' def make_map(config):'
158 157 action="new", conditions=dict(method=["GET"]))
159 158 m.connect("formatted_new_repos_group", "/repos_groups/new.{format}",
160 159 action="new", conditions=dict(method=["GET"]))
161 m.connect("update_repos_group", "/repos_groups/{id}",
160 m.connect("update_repos_group", "/repos_groups/{group_name:.*?}",
162 161 action="update", conditions=dict(method=["PUT"],
163 function=check_int))
164 m.connect("delete_repos_group", "/repos_groups/{id}",
162 function=check_group))
163 m.connect("delete_repos_group", "/repos_groups/{group_name:.*?}",
165 164 action="delete", conditions=dict(method=["DELETE"],
166 function=check_int))
167 m.connect("edit_repos_group", "/repos_groups/{id:.*?}/edit",
165 function=check_group))
166 m.connect("edit_repos_group", "/repos_groups/{group_name:.*?}/edit",
168 167 action="edit", conditions=dict(method=["GET"],))
169 168 m.connect("formatted_edit_repos_group",
170 "/repos_groups/{id}.{format}/edit",
169 "/repos_groups/{group_name:.*?}.{format}/edit",
171 170 action="edit", conditions=dict(method=["GET"],
172 function=check_int))
173 m.connect("repos_group", "/repos_groups/{id}",
171 function=check_group))
172 m.connect("repos_group", "/repos_groups/{group_name:.*?}",
174 173 action="show", conditions=dict(method=["GET"],
175 function=check_int))
176 m.connect("formatted_repos_group", "/repos_groups/{id}.{format}",
174 function=check_group))
175 m.connect("formatted_repos_group", "/repos_groups/{group_name:.*?}.{format}",
177 176 action="show", conditions=dict(method=["GET"],
178 function=check_int))
177 function=check_group))
179 178 # ajax delete repos group perm user
180 179 m.connect('delete_repos_group_user_perm',
181 "/delete_repos_group_user_perm/{group_name:.*}",
180 "/delete_repos_group_user_perm/{group_name:.*?}",
182 181 action="delete_repos_group_user_perm",
183 182 conditions=dict(method=["DELETE"], function=check_group))
184 183
185 184 # ajax delete repos group perm users_group
186 185 m.connect('delete_repos_group_users_group_perm',
187 "/delete_repos_group_users_group_perm/{group_name:.*}",
186 "/delete_repos_group_users_group_perm/{group_name:.*?}",
188 187 action="delete_repos_group_users_group_perm",
189 188 conditions=dict(method=["DELETE"], function=check_group))
190 189
@@ -30,7 +30,7 b' import formencode'
30 30 from formencode import htmlfill
31 31
32 32 from pylons import request, tmpl_context as c, url
33 from pylons.controllers.util import redirect
33 from pylons.controllers.util import abort, redirect
34 34 from pylons.i18n.translation import _
35 35
36 36 from sqlalchemy.exc import IntegrityError
@@ -39,7 +39,8 b' import rhodecode'
39 39 from rhodecode.lib import helpers as h
40 40 from rhodecode.lib.ext_json import json
41 41 from rhodecode.lib.auth import LoginRequired, HasPermissionAnyDecorator,\
42 HasReposGroupPermissionAnyDecorator
42 HasReposGroupPermissionAnyDecorator, HasReposGroupPermissionAll,\
43 HasPermissionAll
43 44 from rhodecode.lib.base import BaseController, render
44 45 from rhodecode.model.db import RepoGroup, Repository
45 46 from rhodecode.model.repos_group import ReposGroupModel
@@ -47,8 +48,9 b' from rhodecode.model.forms import ReposG'
47 48 from rhodecode.model.meta import Session
48 49 from rhodecode.model.repo import RepoModel
49 50 from webob.exc import HTTPInternalServerError, HTTPNotFound
50 from rhodecode.lib.utils2 import str2bool
51 from rhodecode.lib.utils2 import str2bool, safe_int
51 52 from sqlalchemy.sql.expression import func
53 from rhodecode.model.scm import GroupList
52 54
53 55 log = logging.getLogger(__name__)
54 56
@@ -63,10 +65,21 b' class ReposGroupsController(BaseControll'
63 65 def __before__(self):
64 66 super(ReposGroupsController, self).__before__()
65 67
66 def __load_defaults(self):
67 c.repo_groups = RepoGroup.groups_choices()
68 def __load_defaults(self, allow_empty_group=False, exclude_group_ids=[]):
69 if HasPermissionAll('hg.admin')('group edit'):
70 #we're global admin, we're ok and we can create TOP level groups
71 allow_empty_group = True
72
73 #override the choices for this form, we need to filter choices
74 #and display only those we have ADMIN right
75 groups_with_admin_rights = GroupList(RepoGroup.query().all(),
76 perm_set=['group.admin'])
77 c.repo_groups = RepoGroup.groups_choices(groups=groups_with_admin_rights,
78 show_empty_group=allow_empty_group)
79 # exclude filtered ids
80 c.repo_groups = filter(lambda x: x[0] not in exclude_group_ids,
81 c.repo_groups)
68 82 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
69
70 83 repo_model = RepoModel()
71 84 c.users_array = repo_model.get_users_js()
72 85 c.users_groups_array = repo_model.get_users_groups_js()
@@ -77,7 +90,6 b' class ReposGroupsController(BaseControll'
77 90
78 91 :param group_id:
79 92 """
80 self.__load_defaults()
81 93 repo_group = RepoGroup.get_or_404(group_id)
82 94 data = repo_group.get_dict()
83 95 data['group_name'] = repo_group.name
@@ -94,34 +106,37 b' class ReposGroupsController(BaseControll'
94 106
95 107 return data
96 108
97 @HasPermissionAnyDecorator('hg.admin')
98 109 def index(self, format='html'):
99 110 """GET /repos_groups: All items in the collection"""
100 111 # url('repos_groups')
112 group_iter = GroupList(RepoGroup.query().all(), perm_set=['group.admin'])
101 113 sk = lambda g: g.parents[0].group_name if g.parents else g.group_name
102 c.groups = sorted(RepoGroup.query().all(), key=sk)
114 c.groups = sorted(group_iter, key=sk)
103 115 return render('admin/repos_groups/repos_groups_show.html')
104 116
105 @HasPermissionAnyDecorator('hg.admin')
106 117 def create(self):
107 118 """POST /repos_groups: Create a new item"""
108 119 # url('repos_groups')
120
109 121 self.__load_defaults()
122
123 # permissions for can create group based on parent_id are checked
124 # here in the Form
110 125 repos_group_form = ReposGroupForm(available_groups =
111 c.repo_groups_choices)()
126 map(lambda k: unicode(k[0]), c.repo_groups))()
112 127 try:
113 128 form_result = repos_group_form.to_python(dict(request.POST))
114 129 ReposGroupModel().create(
115 130 group_name=form_result['group_name'],
116 131 group_description=form_result['group_description'],
117 parent=form_result['group_parent_id']
132 parent=form_result['group_parent_id'],
133 owner=self.rhodecode_user.user_id
118 134 )
119 135 Session().commit()
120 136 h.flash(_('created repos group %s') \
121 137 % form_result['group_name'], category='success')
122 138 #TODO: in futureaction_logger(, '', '', '', self.sa)
123 139 except formencode.Invalid, errors:
124
125 140 return htmlfill.render(
126 141 render('admin/repos_groups/repos_groups_add.html'),
127 142 defaults=errors.value,
@@ -132,40 +147,65 b' class ReposGroupsController(BaseControll'
132 147 log.error(traceback.format_exc())
133 148 h.flash(_('error occurred during creation of repos group %s') \
134 149 % request.POST.get('group_name'), category='error')
150 parent_group_id = form_result['group_parent_id']
151 #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))
135 153
136 return redirect(url('repos_groups'))
137
138 @HasPermissionAnyDecorator('hg.admin')
139 154 def new(self, format='html'):
140 155 """GET /repos_groups/new: Form to create a new item"""
141 156 # url('new_repos_group')
157 if HasPermissionAll('hg.admin')('group create'):
158 #we're global admin, we're ok and we can create TOP level groups
159 pass
160 else:
161 # we pass in parent group into creation form, thus we know
162 # what would be the group, we can check perms here !
163 group_id = safe_int(request.GET.get('parent_group'))
164 group = RepoGroup.get(group_id) if group_id else None
165 group_name = group.group_name if group else None
166 if HasReposGroupPermissionAll('group.admin')(group_name, 'group create'):
167 pass
168 else:
169 return abort(403)
170
142 171 self.__load_defaults()
143 172 return render('admin/repos_groups/repos_groups_add.html')
144 173
145 @HasPermissionAnyDecorator('hg.admin')
146 def update(self, id):
147 """PUT /repos_groups/id: Update an existing item"""
174 @HasReposGroupPermissionAnyDecorator('group.admin')
175 def update(self, group_name):
176 """PUT /repos_groups/group_name: Update an existing item"""
148 177 # Forms posted to this method should contain a hidden field:
149 178 # <input type="hidden" name="_method" value="PUT" />
150 179 # Or using helpers:
151 # h.form(url('repos_group', id=ID),
180 # h.form(url('repos_group', group_name=GROUP_NAME),
152 181 # method='put')
153 # url('repos_group', id=ID)
182 # url('repos_group', group_name=GROUP_NAME)
154 183
155 self.__load_defaults()
156 c.repos_group = RepoGroup.get(id)
184 c.repos_group = ReposGroupModel()._get_repos_group(group_name)
185 if HasPermissionAll('hg.admin')('group edit'):
186 #we're global admin, we're ok and we can create TOP level groups
187 allow_empty_group = True
188 elif not c.repos_group.parent_group:
189 allow_empty_group = True
190 else:
191 allow_empty_group = False
192 self.__load_defaults(allow_empty_group=allow_empty_group,
193 exclude_group_ids=[c.repos_group.group_id])
157 194
158 195 repos_group_form = ReposGroupForm(
159 196 edit=True,
160 197 old_data=c.repos_group.get_dict(),
161 available_groups=c.repo_groups_choices
198 available_groups=c.repo_groups_choices,
199 can_create_in_root=allow_empty_group,
162 200 )()
163 201 try:
164 202 form_result = repos_group_form.to_python(dict(request.POST))
165 ReposGroupModel().update(id, form_result)
203 new_gr = ReposGroupModel().update(group_name, form_result)
166 204 Session().commit()
167 205 h.flash(_('updated repos group %s') \
168 206 % form_result['group_name'], category='success')
207 # we now have new name !
208 group_name = new_gr.group_name
169 209 #TODO: in future action_logger(, '', '', '', self.sa)
170 210 except formencode.Invalid, errors:
171 211
@@ -180,19 +220,19 b' class ReposGroupsController(BaseControll'
180 220 h.flash(_('error occurred during update of repos group %s') \
181 221 % request.POST.get('group_name'), category='error')
182 222
183 return redirect(url('edit_repos_group', id=id))
223 return redirect(url('edit_repos_group', group_name=group_name))
184 224
185 @HasPermissionAnyDecorator('hg.admin')
186 def delete(self, id):
187 """DELETE /repos_groups/id: Delete an existing item"""
225 @HasReposGroupPermissionAnyDecorator('group.admin')
226 def delete(self, group_name):
227 """DELETE /repos_groups/group_name: Delete an existing item"""
188 228 # Forms posted to this method should contain a hidden field:
189 229 # <input type="hidden" name="_method" value="DELETE" />
190 230 # Or using helpers:
191 # h.form(url('repos_group', id=ID),
231 # h.form(url('repos_group', group_name=GROUP_NAME),
192 232 # method='delete')
193 # url('repos_group', id=ID)
233 # url('repos_group', group_name=GROUP_NAME)
194 234
195 gr = RepoGroup.get(id)
235 gr = c.repos_group = ReposGroupModel()._get_repos_group(group_name)
196 236 repos = gr.repositories.all()
197 237 if repos:
198 238 h.flash(_('This group contains %s repositores and cannot be '
@@ -201,7 +241,7 b' class ReposGroupsController(BaseControll'
201 241 return redirect(url('repos_groups'))
202 242
203 243 try:
204 ReposGroupModel().delete(id)
244 ReposGroupModel().delete(group_name)
205 245 Session().commit()
206 246 h.flash(_('removed repos group %s') % gr.group_name,
207 247 category='success')
@@ -279,11 +319,11 b' class ReposGroupsController(BaseControll'
279 319
280 320 @HasReposGroupPermissionAnyDecorator('group.read', 'group.write',
281 321 'group.admin')
282 def show(self, id, format='html'):
283 """GET /repos_groups/id: Show a specific item"""
284 # url('repos_group', id=ID)
322 def show(self, group_name, format='html'):
323 """GET /repos_groups/group_name: Show a specific item"""
324 # url('repos_group', group_name=GROUP_NAME)
285 325
286 c.group = RepoGroup.get_or_404(id)
326 c.group = c.repos_group = ReposGroupModel()._get_repos_group(group_name)
287 327 c.group_repos = c.group.repositories.all()
288 328
289 329 #overwrite our cached list with current filter
@@ -291,7 +331,7 b' class ReposGroupsController(BaseControll'
291 331 c.repo_cnt = 0
292 332
293 333 groups = RepoGroup.query().order_by(RepoGroup.group_name)\
294 .filter(RepoGroup.group_parent_id == id).all()
334 .filter(RepoGroup.group_parent_id == c.group.group_id).all()
295 335 c.groups = self.scm_model.get_repos_groups(groups)
296 336
297 337 if c.visual.lightweight_dashboard is False:
@@ -299,7 +339,7 b' class ReposGroupsController(BaseControll'
299 339 ## lightweight version of dashboard
300 340 else:
301 341 c.repos_list = Repository.query()\
302 .filter(Repository.group_id == id)\
342 .filter(Repository.group_id == c.group.group_id)\
303 343 .order_by(func.lower(Repository.repo_name))\
304 344 .all()
305 345
@@ -310,17 +350,25 b' class ReposGroupsController(BaseControll'
310 350
311 351 return render('admin/repos_groups/repos_groups.html')
312 352
313 @HasPermissionAnyDecorator('hg.admin')
314 def edit(self, id, format='html'):
315 """GET /repos_groups/id/edit: Form to edit an existing item"""
316 # url('edit_repos_group', id=ID)
353 @HasReposGroupPermissionAnyDecorator('group.admin')
354 def edit(self, group_name, format='html'):
355 """GET /repos_groups/group_name/edit: Form to edit an existing item"""
356 # url('edit_repos_group', group_name=GROUP_NAME)
317 357
318 c.repos_group = ReposGroupModel()._get_repos_group(id)
319 defaults = self.__load_data(c.repos_group.group_id)
358 c.repos_group = ReposGroupModel()._get_repos_group(group_name)
359 #we can only allow moving empty group if it's already a top-level
360 #group, ie has no parents, or we're admin
361 if HasPermissionAll('hg.admin')('group edit'):
362 #we're global admin, we're ok and we can create TOP level groups
363 allow_empty_group = True
364 elif not c.repos_group.parent_group:
365 allow_empty_group = True
366 else:
367 allow_empty_group = False
320 368
321 # we need to exclude this group from the group list for editing
322 c.repo_groups = filter(lambda x: x[0] != c.repos_group.group_id,
323 c.repo_groups)
369 self.__load_defaults(allow_empty_group=allow_empty_group,
370 exclude_group_ids=[c.repos_group.group_id])
371 defaults = self.__load_data(c.repos_group.group_id)
324 372
325 373 return htmlfill.render(
326 374 render('admin/repos_groups/repos_groups_edit.html'),
@@ -659,7 +659,6 b' class HasRepoPermissionAnyDecorator(Perm'
659 659
660 660 def check_permissions(self):
661 661 repo_name = get_repo_slug(request)
662
663 662 try:
664 663 user_perms = set([self.user_perms['repositories'][repo_name]])
665 664 except KeyError:
@@ -682,6 +681,7 b' class HasReposGroupPermissionAllDecorato'
682 681 user_perms = set([self.user_perms['repositories_groups'][group_name]])
683 682 except KeyError:
684 683 return False
684
685 685 if self.required_perms.issubset(user_perms):
686 686 return True
687 687 return False
@@ -695,11 +695,11 b' class HasReposGroupPermissionAnyDecorato'
695 695
696 696 def check_permissions(self):
697 697 group_name = get_repos_group_slug(request)
698
699 698 try:
700 699 user_perms = set([self.user_perms['repositories_groups'][group_name]])
701 700 except KeyError:
702 701 return False
702
703 703 if self.required_perms.intersection(user_perms):
704 704 return True
705 705 return False
@@ -741,7 +741,8 b' def action_parser(user_log, feed=False, '
741 741 # PERMS
742 742 #==============================================================================
743 743 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
744 HasRepoPermissionAny, HasRepoPermissionAll
744 HasRepoPermissionAny, HasRepoPermissionAll, HasReposGroupPermissionAll, \
745 HasReposGroupPermissionAny
745 746
746 747
747 748 #==============================================================================
@@ -1172,15 +1172,18 b' class RepoGroup(Base, BaseModel):'
1172 1172 self.group_name)
1173 1173
1174 1174 @classmethod
1175 def groups_choices(cls, check_perms=False):
1175 def groups_choices(cls, groups=None, check_perms=False, show_empty_group=True):
1176 1176 from webhelpers.html import literal as _literal
1177 1177 from rhodecode.model.scm import ScmModel
1178 if not groups:
1178 1179 groups = cls.query().all()
1179 1180 if check_perms:
1180 1181 #filter group user have access to, it's done
1181 1182 #magically inside ScmModel based on current user
1182 1183 groups = ScmModel().get_repos_groups(groups)
1183 repo_groups = [('', '')]
1184 repo_groups = []
1185 if show_empty_group:
1186 repo_groups = [('-1', '-- no parent --')]
1184 1187 sep = ' &raquo; '
1185 1188 _name = lambda k: _literal(sep.join(k))
1186 1189
@@ -115,7 +115,8 b' def UsersGroupForm(edit=False, old_data='
115 115 return _UsersGroupForm
116 116
117 117
118 def ReposGroupForm(edit=False, old_data={}, available_groups=[]):
118 def ReposGroupForm(edit=False, old_data={}, available_groups=[],
119 can_create_in_root=False):
119 120 class _ReposGroupForm(formencode.Schema):
120 121 allow_extra_fields = True
121 122 filter_extra_fields = False
@@ -123,10 +124,15 b' def ReposGroupForm(edit=False, old_data='
123 124 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
124 125 v.SlugifyName())
125 126 group_description = v.UnicodeString(strip=True, min=1,
126 not_empty=True)
127 group_parent_id = v.OneOf(available_groups, hideList=False,
127 not_empty=False)
128 if edit:
129 #FIXME: do a special check that we cannot move a group to one of
130 #it's children
131 pass
132 group_parent_id = All(v.CanCreateGroup(can_create_in_root),
133 v.OneOf(available_groups, hideList=False,
128 134 testValueList=True,
129 if_missing=None, not_empty=False)
135 if_missing=None, not_empty=True))
130 136 enable_locking = v.StringBoolean(if_missing=False)
131 137 recursive = v.StringBoolean(if_missing=False)
132 138 chained_validators = [v.ValidReposGroup(edit, old_data),
@@ -140,16 +140,21 b' class ReposGroupModel(BaseModel):'
140 140 group.name)
141 141 shutil.move(rm_path, os.path.join(self.repos_path, _d))
142 142
143 def create(self, group_name, group_description, parent=None, just_db=False):
143 def create(self, group_name, group_description, owner, parent=None, just_db=False):
144 144 try:
145 145 new_repos_group = RepoGroup()
146 new_repos_group.group_description = group_description
146 new_repos_group.group_description = group_description or group_name
147 147 new_repos_group.parent_group = self._get_repos_group(parent)
148 148 new_repos_group.group_name = new_repos_group.get_new_name(group_name)
149 149
150 150 self.sa.add(new_repos_group)
151 151 self._create_default_perms(new_repos_group)
152 152
153 #create an ADMIN permission for owner, later owner should go into
154 #the owner field of groups
155 self.grant_user_permission(repos_group=new_repos_group,
156 user=owner, perm='group.admin')
157
153 158 if not just_db:
154 159 # we need to flush here, in order to check if database won't
155 160 # throw any exceptions, create filesystem dirs at the very end
@@ -229,10 +234,10 b' class ReposGroupModel(BaseModel):'
229 234 break
230 235 return updates
231 236
232 def update(self, repos_group_id, form_data):
237 def update(self, repos_group, form_data):
233 238
234 239 try:
235 repos_group = RepoGroup.get(repos_group_id)
240 repos_group = self._get_repos_group(repos_group)
236 241 recursive = form_data['recursive']
237 242 # iterate over all members(if in recursive mode) of this groups and
238 243 # set the permissions !
@@ -77,11 +77,15 b' class CachedRepoList(object):'
77 77 super fast
78 78 """
79 79
80 def __init__(self, db_repo_list, repos_path, order_by=None):
80 def __init__(self, db_repo_list, repos_path, order_by=None, perm_set=None):
81 81 self.db_repo_list = db_repo_list
82 82 self.repos_path = repos_path
83 83 self.order_by = order_by
84 84 self.reversed = (order_by or '').startswith('-')
85 if not perm_set:
86 perm_set = ['repository.read', 'repository.write',
87 'repository.admin']
88 self.perm_set = perm_set
85 89
86 90 def __len__(self):
87 91 return len(self.db_repo_list)
@@ -98,7 +102,7 b' class CachedRepoList(object):'
98 102 scmr = dbr.scm_instance_cached(cache_map)
99 103 # check permission at this level
100 104 if not HasRepoPermissionAny(
101 'repository.read', 'repository.write', 'repository.admin'
105 *self.perm_set
102 106 )(dbr.repo_name, 'get repo check'):
103 107 continue
104 108
@@ -143,7 +147,7 b' class SimpleCachedRepoList(CachedRepoLis'
143 147 for dbr in self.db_repo_list:
144 148 # check permission at this level
145 149 if not HasRepoPermissionAny(
146 'repository.read', 'repository.write', 'repository.admin'
150 *self.perm_set
147 151 )(dbr.repo_name, 'get repo check'):
148 152 continue
149 153
@@ -160,8 +164,18 b' class SimpleCachedRepoList(CachedRepoLis'
160 164
161 165 class GroupList(object):
162 166
163 def __init__(self, db_repo_group_list):
167 def __init__(self, db_repo_group_list, perm_set=None):
168 """
169 Creates iterator from given list of group objects, additionally
170 checking permission for them from perm_set var
171
172 :param db_repo_group_list:
173 :param perm_set: list of permissons to check
174 """
164 175 self.db_repo_group_list = db_repo_group_list
176 if not perm_set:
177 perm_set = ['group.read', 'group.write', 'group.admin']
178 self.perm_set = perm_set
165 179
166 180 def __len__(self):
167 181 return len(self.db_repo_group_list)
@@ -173,7 +187,7 b' class GroupList(object):'
173 187 for dbgr in self.db_repo_group_list:
174 188 # check permission at this level
175 189 if not HasReposGroupPermissionAny(
176 'group.read', 'group.write', 'group.admin'
190 *self.perm_set
177 191 )(dbgr.group_name, 'get group repo check'):
178 192 continue
179 193
@@ -475,11 +475,19 b' def CanWriteGroup():'
475 475 "to create repository in this group")
476 476 }
477 477
478 def to_python(self, value, state):
479 #root location
480 if value in [-1, "-1"]:
481 return None
482 return value
483
478 484 def validate_python(self, value, state):
479 485 gr = RepoGroup.get(value)
480 if not HasReposGroupPermissionAny(
481 'group.write', 'group.admin'
482 )(gr.group_name, 'get group of repo form'):
486 gr_name = gr.group_name if gr else None # None means ROOT location
487 val = HasReposGroupPermissionAny('group.write', 'group.admin')
488 forbidden = not val(gr_name, 'can write into group validator')
489 #parent group need to be existing
490 if gr and forbidden:
483 491 msg = M(self, 'permission_denied', state)
484 492 raise formencode.Invalid(msg, value, state,
485 493 error_dict=dict(repo_type=msg)
@@ -487,6 +495,46 b' def CanWriteGroup():'
487 495 return _validator
488 496
489 497
498 def CanCreateGroup(can_create_in_root=False):
499 class _validator(formencode.validators.FancyValidator):
500 messages = {
501 'permission_denied': _(u"You don't have permissions "
502 "to create a group in this location")
503 }
504
505 def to_python(self, value, state):
506 #root location
507 if value in [-1, "-1"]:
508 return None
509 return value
510
511 def validate_python(self, value, state):
512 #TODO: REMOVE THIS !!
513 ################################
514 import ipdb;ipdb.set_trace()
515 print 'setting ipdb debuggin for rhodecode.model.validators._validator.validate_python'
516 ################################
517
518
519 gr = RepoGroup.get(value)
520 gr_name = gr.group_name if gr else None # None means ROOT location
521
522 if can_create_in_root and gr is None:
523 #we can create in root, we're fine no validations required
524 return
525
526 forbidden_in_root = gr is None and can_create_in_root is False
527 val = HasReposGroupPermissionAny('group.admin')
528 forbidden = not val(gr_name, 'can create group validator')
529 if forbidden_in_root or forbidden:
530 msg = M(self, 'permission_denied', state)
531 raise formencode.Invalid(msg, value, state,
532 error_dict=dict(group_parent_id=msg)
533 )
534
535 return _validator
536
537
490 538 def ValidPerms(type_='repo'):
491 539 if type_ == 'group':
492 540 EMPTY_PERM = 'group.none'
@@ -4631,7 +4631,7 b' PULL REQUESTS'
4631 4631 }
4632 4632
4633 4633 #perms .perm_tag.write{
4634 background-color: #B94A48;
4634 background-color: #DB7525;
4635 4635 color: #ffffff;
4636 4636 }
4637 4637
@@ -148,7 +148,7 b''
148 148 %if section == 'repositories':
149 149 <a href="${h.url('edit_repo',repo_name=k,anchor='permissions_manage')}">${_('edit')}</a>
150 150 %elif section == 'repositories_groups':
151 <a href="${h.url('edit_repos_group',id=k,anchor='permissions_manage')}">${_('edit')}</a>
151 <a href="${h.url('edit_repos_group',group_name=k,anchor='permissions_manage')}">${_('edit')}</a>
152 152 %else:
153 153 --
154 154 %endif
@@ -28,7 +28,7 b''
28 28 </ul>
29 29 </div>
30 30 <!-- end box / title -->
31 ${h.form(url('repos_group',id=c.repos_group.group_id),method='put')}
31 ${h.form(url('repos_group',group_name=c.repos_group.group_name),method='put')}
32 32 <div class="form">
33 33 <!-- fields -->
34 34 <div class="fields">
@@ -51,12 +51,12 b''
51 51 <td>${gr.group_description}</td>
52 52 <td><b>${gr_cn}</b></td>
53 53 <td>
54 <a href="${h.url('edit_repos_group',id=gr.group_id)}" title="${_('edit')}">
54 <a href="${h.url('edit_repos_group',group_name=gr.group_name)}" title="${_('edit')}">
55 55 ${h.submit('edit_%s' % gr.group_name,_('edit'),class_="edit_icon action_button")}
56 56 </a>
57 57 </td>
58 58 <td>
59 ${h.form(url('repos_group', id=gr.group_id),method='delete')}
59 ${h.form(url('repos_group', group_name=gr.group_name),method='delete')}
60 60 ${h.submit('remove_%s' % gr.name,_('delete'),class_="delete_icon action_button",onclick="return confirm('"+ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_cn) % (gr.name,gr_cn)+"');")}
61 61 ${h.end_form()}
62 62 </td>
@@ -231,7 +231,7 b''
231 231 %if section == 'repositories':
232 232 <a href="${h.url('edit_repo',repo_name=k,anchor='permissions_manage')}">${_('edit')}</a>
233 233 %elif section == 'repositories_groups':
234 <a href="${h.url('edit_repos_group',id=k,anchor='permissions_manage')}">${_('edit')}</a>
234 <a href="${h.url('edit_repos_group',group_name=k,anchor='permissions_manage')}">${_('edit')}</a>
235 235 %else:
236 236 --
237 237 %endif
@@ -206,7 +206,7 b''
206 206 %if section == 'repositories':
207 207 <a href="${h.url('edit_repo',repo_name=k,anchor='permissions_manage')}">${_('edit')}</a>
208 208 %elif section == 'repositories_groups':
209 <a href="${h.url('edit_repos_group',id=k,anchor='permissions_manage')}">${_('edit')}</a>
209 <a href="${h.url('edit_repos_group',group_name=k,anchor='permissions_manage')}">${_('edit')}</a>
210 210 %else:
211 211 --
212 212 %endif
@@ -6,8 +6,8 b''
6 6 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/> ${parent.breadcrumbs()} <span id="repo_count">0</span> ${_('repositories')}
7 7 </h5>
8 8 %if c.rhodecode_user.username != 'default':
9 <ul class="links">
9 10 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
10 <ul class="links">
11 11 <li>
12 12 %if c.group:
13 13 <span>${h.link_to(_('Add repository'),h.url('admin_settings_create_repository',parent_group=c.group.group_id))}</span>
@@ -15,9 +15,14 b''
15 15 <span>${h.link_to(_('Add repository'),h.url('admin_settings_create_repository'))}</span>
16 16 %endif
17 17 </li>
18 %endif
19 %if c.group and h.HasReposGroupPermissionAny('group.admin')(c.group.group_name):
20 <li>
21 <span>${h.link_to(_('Edit group'),h.url('edit_repos_group',group_name=c.group.group_name), title=_('You have admin right to this group, and can edit it'))}</span>
22 </li>
23 %endif
18 24 </ul>
19 25 %endif
20 %endif
21 26 </div>
22 27 <!-- end box / title -->
23 28 <div class="table">
@@ -90,7 +90,8 b' class TestAdminReposController(TestContr'
90 90 ## create GROUP
91 91 group_name = 'sometest'
92 92 gr = ReposGroupModel().create(group_name=group_name,
93 group_description='test',)
93 group_description='test',
94 owner=TEST_USER_ADMIN_LOGIN)
94 95 self.Session().commit()
95 96
96 97 repo_name = 'ingroup'
@@ -1,43 +1,51 b''
1 1 from rhodecode.tests import *
2 2
3
3 4 class TestReposGroupsController(TestController):
4 5
5 6 def test_index(self):
7 self.log_user()
6 8 response = self.app.get(url('repos_groups'))
7 # Test response...
9 response.mustcontain('There are no repositories groups yet')
8 10
9 def test_index_as_xml(self):
10 response = self.app.get(url('formatted_repos_groups', format='xml'))
11
12 def test_create(self):
13 response = self.app.post(url('repos_groups'))
11 # def test_index_as_xml(self):
12 # response = self.app.get(url('formatted_repos_groups', format='xml'))
13 #
14 # def test_create(self):
15 # response = self.app.post(url('repos_groups'))
14 16
15 17 def test_new(self):
18 self.log_user()
16 19 response = self.app.get(url('new_repos_group'))
17 20
18 def test_new_as_xml(self):
19 response = self.app.get(url('formatted_new_repos_group', format='xml'))
20
21 def test_update(self):
22 response = self.app.put(url('repos_group', id=1))
23
24 def test_update_browser_fakeout(self):
25 response = self.app.post(url('repos_group', id=1), params=dict(_method='put'))
26
27 def test_delete(self):
28 response = self.app.delete(url('repos_group', id=1))
29
30 def test_delete_browser_fakeout(self):
31 response = self.app.post(url('repos_group', id=1), params=dict(_method='delete'))
32
33 def test_show(self):
34 response = self.app.get(url('repos_group', id=1))
35
36 def test_show_as_xml(self):
37 response = self.app.get(url('formatted_repos_group', id=1, format='xml'))
38
39 def test_edit(self):
40 response = self.app.get(url('edit_repos_group', id=1))
41
42 def test_edit_as_xml(self):
43 response = self.app.get(url('formatted_edit_repos_group', id=1, format='xml'))
21 def test_new_by_regular_user(self):
22 self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
23 response = self.app.get(url('new_repos_group'), status=403)
24 #
25 # def test_new_as_xml(self):
26 # response = self.app.get(url('formatted_new_repos_group', format='xml'))
27 #
28 # def test_update(self):
29 # response = self.app.put(url('repos_group', group_name=1))
30 #
31 # def test_update_browser_fakeout(self):
32 # response = self.app.post(url('repos_group', group_name=1), params=dict(_method='put'))
33 #
34 # def test_delete(self):
35 # self.log_user()
36 # response = self.app.delete(url('repos_group', group_name=1))
37 #
38 # def test_delete_browser_fakeout(self):
39 # response = self.app.post(url('repos_group', group_name=1), params=dict(_method='delete'))
40 #
41 # def test_show(self):
42 # response = self.app.get(url('repos_group', group_name=1))
43 #
44 # def test_show_as_xml(self):
45 # response = self.app.get(url('formatted_repos_group', group_name=1, format='xml'))
46 #
47 # def test_edit(self):
48 # response = self.app.get(url('edit_repos_group', group_name=1))
49 #
50 # def test_edit_as_xml(self):
51 # response = self.app.get(url('formatted_edit_repos_group', group_name=1, format='xml'))
@@ -21,7 +21,7 b" def _make_group(path, desc='desc', paren"
21 21 return gr
22 22 if isinstance(parent_id, RepoGroup):
23 23 parent_id = parent_id.group_id
24 gr = ReposGroupModel().create(path, desc, parent_id)
24 gr = ReposGroupModel().create(path, desc, TEST_USER_ADMIN_LOGIN, parent_id)
25 25 return gr
26 26
27 27
@@ -17,7 +17,7 b" def _make_group(path, desc='desc', paren"
17 17 return gr
18 18 if isinstance(parent_id, RepoGroup):
19 19 parent_id = parent_id.group_id
20 gr = ReposGroupModel().create(path, desc, parent_id)
20 gr = ReposGroupModel().create(path, desc, TEST_USER_ADMIN_LOGIN, parent_id)
21 21 return gr
22 22
23 23
@@ -79,7 +79,8 b' class TestReposGroups(unittest.TestCase)'
79 79 {'group_name': HG_REPO, })
80 80 gr = model.create(group_name='test_gr', group_description='desc',
81 81 parent=None,
82 just_db=True)
82 just_db=True,
83 owner=TEST_USER_ADMIN_LOGIN)
83 84 self.assertRaises(formencode.Invalid,
84 85 validator.to_python, {'group_name': gr.group_name, })
85 86
@@ -150,7 +151,8 b' class TestReposGroups(unittest.TestCase)'
150 151
151 152 gr = ReposGroupModel().create(group_name='group_test',
152 153 group_description='desc',
153 parent=None,)
154 parent=None,
155 owner=TEST_USER_ADMIN_LOGIN)
154 156 self.assertRaises(formencode.Invalid,
155 157 validator.to_python, {'repo_name': gr.group_name})
156 158
General Comments 0
You need to be logged in to leave comments. Login now