##// END OF EJS Templates
#227 Initial version of repository groups permissions system...
marcink -
r1982:87f0800a beta
parent child Browse files
Show More
@@ -0,0 +1,270 b''
1 <table id="permissions_manage" class="noborder">
2 <tr>
3 <td>${_('none')}</td>
4 <td>${_('read')}</td>
5 <td>${_('write')}</td>
6 <td>${_('admin')}</td>
7 <td>${_('member')}</td>
8 <td></td>
9 </tr>
10 ## USERS
11 %for r2p in c.repos_group.repo_group_to_perm:
12 <tr id="id${id(r2p.user.username)}">
13 <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>
15 <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>
17 <td style="white-space: nowrap;">
18 <img style="vertical-align:bottom" src="${h.url('/images/icons/user.png')}"/>${r2p.user.username}
19 </td>
20 <td>
21 %if r2p.user.username !='default':
22 <span class="delete_icon action_button" onclick="ajaxActionUser(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
23 ${_('revoke')}
24 </span>
25 %endif
26 </td>
27 </tr>
28 %endfor
29
30 ## USERS GROUPS
31 %for g2p in c.repos_group.users_group_to_perm:
32 <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>
34 <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>
36 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.admin')}</td>
37 <td style="white-space: nowrap;">
38 <img style="vertical-align:bottom" src="${h.url('/images/icons/group.png')}"/>${g2p.users_group.users_group_name}
39 </td>
40 <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)}')">
42 ${_('revoke')}
43 </span>
44 </td>
45 </tr>
46 %endfor
47 <tr id="add_perm_input">
48 <td>${h.radio('perm_new_member','group.none')}</td>
49 <td>${h.radio('perm_new_member','group.read')}</td>
50 <td>${h.radio('perm_new_member','group.write')}</td>
51 <td>${h.radio('perm_new_member','group.admin')}</td>
52 <td class='ac'>
53 <div class="perm_ac" id="perm_ac">
54 ${h.text('perm_new_member_name',class_='yui-ac-input')}
55 ${h.hidden('perm_new_member_type')}
56 <div id="perm_container"></div>
57 </div>
58 </td>
59 <td></td>
60 </tr>
61 <tr>
62 <td colspan="6">
63 <span id="add_perm" class="add_icon" style="cursor: pointer;">
64 ${_('Add another member')}
65 </span>
66 </td>
67 </tr>
68 </table>
69 <script type="text/javascript">
70 function ajaxActionUser(user_id, field_id) {
71 var sUrl = "${h.url('delete_repos_group_user_perm',group_name=c.repos_group.name)}";
72 var callback = {
73 success: function (o) {
74 var tr = YUD.get(String(field_id));
75 tr.parentNode.removeChild(tr);
76 },
77 failure: function (o) {
78 alert("${_('Failed to remove user')}");
79 },
80 };
81 var postData = '_method=delete&user_id=' + user_id;
82 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
83 };
84
85 function ajaxActionUsersGroup(users_group_id,field_id){
86 var sUrl = "${h.url('delete_repos_group_users_group_perm',group_name=c.repos_group.name)}";
87 var callback = {
88 success:function(o){
89 var tr = YUD.get(String(field_id));
90 tr.parentNode.removeChild(tr);
91 },
92 failure:function(o){
93 alert("${_('Failed to remove users group')}");
94 },
95 };
96 var postData = '_method=delete&users_group_id='+users_group_id;
97 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
98 };
99
100 YUE.onDOMReady(function () {
101 if (!YUD.hasClass('perm_new_member_name', 'error')) {
102 YUD.setStyle('add_perm_input', 'display', 'none');
103 }
104 YAHOO.util.Event.addListener('add_perm', 'click', function () {
105 YUD.setStyle('add_perm_input', 'display', '');
106 YUD.setStyle('add_perm', 'opacity', '0.6');
107 YUD.setStyle('add_perm', 'cursor', 'default');
108 });
109 });
110
111 YAHOO.example.FnMultipleFields = function () {
112 var myUsers = ${c.users_array|n};
113 var myGroups = ${c.users_groups_array|n};
114
115 // Define a custom search function for the DataSource of users
116 var matchUsers = function (sQuery) {
117 // Case insensitive matching
118 var query = sQuery.toLowerCase();
119 var i = 0;
120 var l = myUsers.length;
121 var matches = [];
122
123 // Match against each name of each contact
124 for (; i < l; i++) {
125 contact = myUsers[i];
126 if ((contact.fname.toLowerCase().indexOf(query) > -1) || (contact.lname.toLowerCase().indexOf(query) > -1) || (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
127 matches[matches.length] = contact;
128 }
129 }
130 return matches;
131 };
132
133 // Define a custom search function for the DataSource of usersGroups
134 var matchGroups = function (sQuery) {
135 // Case insensitive matching
136 var query = sQuery.toLowerCase();
137 var i = 0;
138 var l = myGroups.length;
139 var matches = [];
140
141 // Match against each name of each contact
142 for (; i < l; i++) {
143 matched_group = myGroups[i];
144 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
145 matches[matches.length] = matched_group;
146 }
147 }
148 return matches;
149 };
150
151 //match all
152 var matchAll = function (sQuery) {
153 u = matchUsers(sQuery);
154 g = matchGroups(sQuery);
155 return u.concat(g);
156 };
157
158 // DataScheme for members
159 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
160 memberDS.responseSchema = {
161 fields: ["id", "fname", "lname", "nname", "grname", "grmembers"]
162 };
163
164 // DataScheme for owner
165 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
166 ownerDS.responseSchema = {
167 fields: ["id", "fname", "lname", "nname"]
168 };
169
170 // Instantiate AutoComplete for perms
171 var membersAC = new YAHOO.widget.AutoComplete("perm_new_member_name", "perm_container", memberDS);
172 membersAC.useShadow = false;
173 membersAC.resultTypeList = false;
174
175 // Instantiate AutoComplete for owner
176 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
177 ownerAC.useShadow = false;
178 ownerAC.resultTypeList = false;
179
180
181 // Helper highlight function for the formatter
182 var highlightMatch = function (full, snippet, matchindex) {
183 return full.substring(0, matchindex) + "<span class='match'>" + full.substr(matchindex, snippet.length) + "</span>" + full.substring(matchindex + snippet.length);
184 };
185
186 // Custom formatter to highlight the matching letters
187 var custom_formatter = function (oResultData, sQuery, sResultMatch) {
188 var query = sQuery.toLowerCase();
189
190 if (oResultData.grname != undefined) {
191 var grname = oResultData.grname;
192 var grmembers = oResultData.grmembers;
193 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
194 var grprefix = "${_('Group')}: ";
195 var grsuffix = " (" + grmembers + " ${_('members')})";
196
197 if (grnameMatchIndex > -1) {
198 return grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix;
199 }
200
201 return grprefix + oResultData.grname + grsuffix;
202 } else if (oResultData.fname != undefined) {
203
204 var fname = oResultData.fname,
205 lname = oResultData.lname,
206 nname = oResultData.nname || "",
207 // Guard against null value
208 fnameMatchIndex = fname.toLowerCase().indexOf(query),
209 lnameMatchIndex = lname.toLowerCase().indexOf(query),
210 nnameMatchIndex = nname.toLowerCase().indexOf(query),
211 displayfname, displaylname, displaynname;
212
213 if (fnameMatchIndex > -1) {
214 displayfname = highlightMatch(fname, query, fnameMatchIndex);
215 } else {
216 displayfname = fname;
217 }
218
219 if (lnameMatchIndex > -1) {
220 displaylname = highlightMatch(lname, query, lnameMatchIndex);
221 } else {
222 displaylname = lname;
223 }
224
225 if (nnameMatchIndex > -1) {
226 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
227 } else {
228 displaynname = nname ? "(" + nname + ")" : "";
229 }
230
231 return displayfname + " " + displaylname + " " + displaynname;
232 } else {
233 return '';
234 }
235 };
236 membersAC.formatResult = custom_formatter;
237 ownerAC.formatResult = custom_formatter;
238
239 var myHandler = function (sType, aArgs) {
240
241 var myAC = aArgs[0]; // reference back to the AC instance
242 var elLI = aArgs[1]; // reference to the selected LI element
243 var oData = aArgs[2]; // object literal of selected item's result data
244 //fill the autocomplete with value
245 if (oData.nname != undefined) {
246 //users
247 myAC.getInputEl().value = oData.nname;
248 YUD.get('perm_new_member_type').value = 'user';
249 } else {
250 //groups
251 myAC.getInputEl().value = oData.grname;
252 YUD.get('perm_new_member_type').value = 'users_group';
253 }
254
255 };
256
257 membersAC.itemSelectEvent.subscribe(myHandler);
258 if(ownerAC.itemSelectEvent){
259 ownerAC.itemSelectEvent.subscribe(myHandler);
260 }
261
262 return {
263 memberDS: memberDS,
264 ownerDS: ownerDS,
265 membersAC: membersAC,
266 ownerAC: ownerAC,
267 };
268 }();
269
270 </script>
@@ -3,9 +3,9 b' RhodeCode documentation!'
3 3 ========================
4 4
5 5 ``RhodeCode`` is a fast and powerful management tool for Mercurial_ and GIT_
6 with a built in push/pull server and full text search.
6 with a built in push/pull server and full text search and code-review.
7 7 It works on http/https and has a built in permission/authentication system with
8 the ability to authenticate via LDAP or ActiveDirectory. RhodeCode also supports
8 the ability to authenticate via LDAP or ActiveDirectory. RhodeCode also provides
9 9 simple API so it's easy integrable with existing external systems.
10 10
11 11 RhodeCode is similar in some respects to github or bitbucket_,
@@ -91,6 +91,7 b" Get's an user by username, Returns empty"
91 91 This command can be executed only using api_key belonging to user with admin
92 92 rights.
93 93
94
94 95 INPUT::
95 96
96 97 api_key : "<api_key>"
@@ -122,6 +123,7 b' get_users'
122 123 Lists all existing users. This command can be executed only using api_key
123 124 belonging to user with admin rights.
124 125
126
125 127 INPUT::
126 128
127 129 api_key : "<api_key>"
@@ -145,12 +147,14 b' OUTPUT::'
145 147 ]
146 148 error: null
147 149
150
148 151 create_user
149 152 -----------
150 153
151 154 Creates new user or updates current one if such user exists. This command can
152 155 be executed only using api_key belonging to user with admin rights.
153 156
157
154 158 INPUT::
155 159
156 160 api_key : "<api_key>"
@@ -174,12 +178,14 b' OUTPUT::'
174 178 }
175 179 error: null
176 180
181
177 182 get_users_group
178 183 ---------------
179 184
180 185 Gets an existing users group. This command can be executed only using api_key
181 186 belonging to user with admin rights.
182 187
188
183 189 INPUT::
184 190
185 191 api_key : "<api_key>"
@@ -210,12 +216,14 b' OUTPUT::'
210 216 }
211 217 error : null
212 218
219
213 220 get_users_groups
214 221 ----------------
215 222
216 223 Lists all existing users groups. This command can be executed only using
217 224 api_key belonging to user with admin rights.
218 225
226
219 227 INPUT::
220 228
221 229 api_key : "<api_key>"
@@ -253,6 +261,7 b' create_users_group'
253 261 Creates new users group. This command can be executed only using api_key
254 262 belonging to user with admin rights
255 263
264
256 265 INPUT::
257 266
258 267 api_key : "<api_key>"
@@ -270,12 +279,14 b' OUTPUT::'
270 279 }
271 280 error: null
272 281
282
273 283 add_user_to_users_group
274 284 -----------------------
275 285
276 286 Adds a user to a users group. This command can be executed only using api_key
277 287 belonging to user with admin rights
278 288
289
279 290 INPUT::
280 291
281 292 api_key : "<api_key>"
@@ -293,12 +304,14 b' OUTPUT::'
293 304 }
294 305 error: null
295 306
307
296 308 get_repo
297 309 --------
298 310
299 311 Gets an existing repository. This command can be executed only using api_key
300 312 belonging to user with admin rights
301 313
314
302 315 INPUT::
303 316
304 317 api_key : "<api_key>"
@@ -338,12 +351,14 b' OUTPUT::'
338 351 }
339 352 error: null
340 353
354
341 355 get_repos
342 356 ---------
343 357
344 358 Lists all existing repositories. This command can be executed only using api_key
345 359 belonging to user with admin rights
346 360
361
347 362 INPUT::
348 363
349 364 api_key : "<api_key>"
@@ -372,6 +387,7 b" at given revision. It's possible to spec"
372 387 `dirs`. This command can be executed only using api_key belonging to user
373 388 with admin rights
374 389
390
375 391 INPUT::
376 392
377 393 api_key : "<api_key>"
@@ -395,7 +411,6 b' OUTPUT::'
395 411 error: null
396 412
397 413
398
399 414 create_repo
400 415 -----------
401 416
@@ -405,6 +420,7 b' If repository name contains "/", all nee'
405 420 For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
406 421 and create "baz" repository with "bar" as group.
407 422
423
408 424 INPUT::
409 425
410 426 api_key : "<api_key>"
@@ -420,54 +436,106 b' INPUT::'
420 436 OUTPUT::
421 437
422 438 result: {
423 "id": "<newrepoid>",
424 "msg": "Created new repository <reponame>",
439 "id": "<newrepoid>",
440 "msg": "Created new repository <reponame>",
425 441 }
426 442 error: null
427 443
428 add_user_to_repo
429 ----------------
444
445 grant_user_permission
446 ---------------------
430 447
431 Add a user to a repository. This command can be executed only using api_key
432 belonging to user with admin rights.
433 If "perm" is None, user will be removed from the repository.
448 Grant permission for user on given repository, or update existing one
449 if found. This command can be executed only using api_key belonging to user
450 with admin rights.
451
434 452
435 453 INPUT::
436 454
437 455 api_key : "<api_key>"
438 method : "add_user_to_repo"
456 method : "grant_user_permission"
439 457 args: {
440 458 "repo_name" : "<reponame>",
441 459 "username" : "<username>",
442 "perm" : "(None|repository.(read|write|admin))",
460 "perm" : "(repository.(none|read|write|admin))",
461 }
462
463 OUTPUT::
464
465 result: {
466 "msg" : "Granted perm: <perm> for user: <username> in repo: <reponame>"
467 }
468 error: null
469
470
471 revoke_user_permission
472 ----------------------
473
474 Revoke permission for user on given repository. This command can be executed
475 only using api_key belonging to user with admin rights.
476
477
478 INPUT::
479
480 api_key : "<api_key>"
481 method : "revoke_user_permission"
482 args: {
483 "repo_name" : "<reponame>",
484 "username" : "<username>",
443 485 }
444 486
445 487 OUTPUT::
446 488
447 489 result: {
448 "msg" : "Added perm: <perm> for <username> in repo: <reponame>"
490 "msg" : "Revoked perm for user: <suername> in repo: <reponame>"
449 491 }
450 492 error: null
451 493
452 add_users_group_to_repo
453 -----------------------
494
495 grant_users_group_permission
496 ----------------------------
454 497
455 Add a users group to a repository. This command can be executed only using
456 api_key belonging to user with admin rights. If "perm" is None, group will
457 be removed from the repository.
498 Grant permission for users group on given repository, or update
499 existing one if found. This command can be executed only using
500 api_key belonging to user with admin rights.
501
458 502
459 503 INPUT::
460 504
461 505 api_key : "<api_key>"
462 method : "add_users_group_to_repo"
506 method : "grant_users_group_permission"
507 args: {
508 "repo_name" : "<reponame>",
509 "group_name" : "<usersgroupname>",
510 "perm" : "(repository.(none|read|write|admin))",
511 }
512
513 OUTPUT::
514
515 result: {
516 "msg" : "Granted perm: <perm> for group: <usersgroupname> in repo: <reponame>"
517 }
518 error: null
519
520
521 revoke_users_group_permission
522 -----------------------------
523
524 Revoke permission for users group on given repository.This command can be
525 executed only using api_key belonging to user with admin rights.
526
527 INPUT::
528
529 api_key : "<api_key>"
530 method : "revoke_users_group_permission"
463 531 args: {
464 532 "repo_name" : "<reponame>",
465 "group_name" : "<groupname>",
466 "perm" : "(None|repository.(read|write|admin))",
533 "users_group" : "<usersgroupname>",
467 534 }
535
468 536 OUTPUT::
469
537
470 538 result: {
471 "msg" : Added perm: <perm> for <groupname> in repo: <reponame>"
539 "msg" : "Revoked perm for group: <usersgroupname> in repo: <reponame>"
472 540 }
473
541 error: null No newline at end of file
@@ -51,8 +51,8 b' def make_app(global_conf, full_stack=Tru'
51 51 from rhodecode.lib.profiler import ProfilingMiddleware
52 52 app = ProfilingMiddleware(app)
53 53
54 if asbool(full_stack):
54 55
55 if asbool(full_stack):
56 56 # Handle Python exceptions
57 57 app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
58 58
@@ -80,7 +80,6 b' def make_app(global_conf, full_stack=Tru'
80 80 app = Cascade([static_app, app])
81 81 app = make_gzip_middleware(app, global_conf, compress_level=1)
82 82
83
84 83 app.config = config
85 84
86 85 return app
@@ -113,8 +113,9 b' def make_map(config):'
113 113 function=check_repo))
114 114 #ajax delete repo perm user
115 115 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
116 action="delete_perm_user", conditions=dict(method=["DELETE"],
117 function=check_repo))
116 action="delete_perm_user",
117 conditions=dict(method=["DELETE"], function=check_repo))
118
118 119 #ajax delete repo perm users_group
119 120 m.connect('delete_repo_users_group',
120 121 "/repos_delete_users_group/{repo_name:.*}",
@@ -128,7 +129,7 b' def make_map(config):'
128 129 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
129 130 action="repo_cache", conditions=dict(method=["DELETE"],
130 131 function=check_repo))
131 m.connect('repo_public_journal',"/repos_public_journal/{repo_name:.*}",
132 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*}",
132 133 action="repo_public_journal", conditions=dict(method=["PUT"],
133 134 function=check_repo))
134 135 m.connect('repo_pull', "/repo_pull/{repo_name:.*}",
@@ -169,6 +170,17 b' def make_map(config):'
169 170 m.connect("formatted_repos_group", "/repos_groups/{id}.{format}",
170 171 action="show", conditions=dict(method=["GET"],
171 172 function=check_int))
173 # ajax delete repos group perm user
174 m.connect('delete_repos_group_user_perm',
175 "/delete_repos_group_user_perm/{group_name:.*}",
176 action="delete_repos_group_user_perm",
177 conditions=dict(method=["DELETE"], function=check_group))
178
179 # ajax delete repos group perm users_group
180 m.connect('delete_repos_group_users_group_perm',
181 "/delete_repos_group_users_group_perm/{group_name:.*}",
182 action="delete_repos_group_users_group_perm",
183 conditions=dict(method=["DELETE"], function=check_group))
172 184
173 185 #ADMIN USER REST ROUTES
174 186 with rmap.submapper(path_prefix=ADMIN_PREFIX,
@@ -310,8 +322,6 b' def make_map(config):'
310 322 m.connect("formatted_notification", "/notifications/{notification_id}.{format}",
311 323 action="show", conditions=dict(method=["GET"]))
312 324
313
314
315 325 #ADMIN MAIN PAGES
316 326 with rmap.submapper(path_prefix=ADMIN_PREFIX,
317 327 controller='admin/admin') as m:
@@ -320,13 +330,12 b' def make_map(config):'
320 330 action='add_repo')
321 331
322 332 #==========================================================================
323 # API V1
333 # API V2
324 334 #==========================================================================
325 335 with rmap.submapper(path_prefix=ADMIN_PREFIX,
326 336 controller='api/api') as m:
327 337 m.connect('api', '/api')
328 338
329
330 339 #USER JOURNAL
331 340 rmap.connect('journal', '%s/journal' % ADMIN_PREFIX, controller='journal')
332 341
@@ -388,11 +397,13 b' def make_map(config):'
388 397 controller='changeset', revision='tip',
389 398 conditions=dict(function=check_repo))
390 399
391 rmap.connect('changeset_comment', '/{repo_name:.*}/changeset/{revision}/comment',
400 rmap.connect('changeset_comment',
401 '/{repo_name:.*}/changeset/{revision}/comment',
392 402 controller='changeset', revision='tip', action='comment',
393 403 conditions=dict(function=check_repo))
394 404
395 rmap.connect('changeset_comment_delete', '/{repo_name:.*}/changeset/comment/{comment_id}/delete',
405 rmap.connect('changeset_comment_delete',
406 '/{repo_name:.*}/changeset/comment/{comment_id}/delete',
396 407 controller='changeset', action='delete_comment',
397 408 conditions=dict(function=check_repo, method=["DELETE"]))
398 409
@@ -493,5 +504,4 b' def make_map(config):'
493 504 controller='followers', action='followers',
494 505 conditions=dict(function=check_repo))
495 506
496
497 507 return rmap
@@ -3,7 +3,7 b''
3 3 rhodecode.controllers.admin.repos
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 Admin controller for RhodeCode
6 Repositories controller for RhodeCode
7 7
8 8 :created_on: Apr 7, 2010
9 9 :author: marcink
@@ -277,7 +277,6 b' class ReposController(BaseController):'
277 277
278 278 return redirect(url('repos'))
279 279
280
281 280 @HasRepoPermissionAllDecorator('repository.admin')
282 281 def delete_perm_user(self, repo_name):
283 282 """
@@ -287,10 +286,11 b' class ReposController(BaseController):'
287 286 """
288 287
289 288 try:
290 repo_model = RepoModel()
291 repo_model.delete_perm_user(request.POST, repo_name)
289 RepoModel().revoke_user_permission(repo=repo_name,
290 user=request.POST['user_id'])
292 291 Session.commit()
293 except Exception, e:
292 except Exception:
293 log.error(traceback.format_exc())
294 294 h.flash(_('An error occurred during deletion of repository user'),
295 295 category='error')
296 296 raise HTTPInternalServerError()
@@ -302,11 +302,14 b' class ReposController(BaseController):'
302 302
303 303 :param repo_name:
304 304 """
305
305 306 try:
306 repo_model = RepoModel()
307 repo_model.delete_perm_users_group(request.POST, repo_name)
307 RepoModel().revoke_users_group_permission(
308 repo=repo_name, group_name=request.POST['users_group_id']
309 )
308 310 Session.commit()
309 except Exception, e:
311 except Exception:
312 log.error(traceback.format_exc())
310 313 h.flash(_('An error occurred during deletion of repository'
311 314 ' users groups'),
312 315 category='error')
@@ -321,8 +324,7 b' class ReposController(BaseController):'
321 324 """
322 325
323 326 try:
324 repo_model = RepoModel()
325 repo_model.delete_stats(repo_name)
327 RepoModel().delete_stats(repo_name)
326 328 Session.commit()
327 329 except Exception, e:
328 330 h.flash(_('An error occurred during deletion of repository stats'),
@@ -3,7 +3,7 b''
3 3 rhodecode.controllers.admin.repos_groups
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 repos groups controller for RhodeCode
6 Repositories groups controller for RhodeCode
7 7
8 8 :created_on: Mar 23, 2010
9 9 :author: marcink
@@ -29,19 +29,22 b' import formencode'
29 29
30 30 from formencode import htmlfill
31 31
32 from pylons import request, response, session, tmpl_context as c, url
33 from pylons.controllers.util import abort, redirect
32 from pylons import request, tmpl_context as c, url
33 from pylons.controllers.util import redirect
34 34 from pylons.i18n.translation import _
35 35
36 36 from sqlalchemy.exc import IntegrityError
37 37
38 38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAnyDecorator
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAnyDecorator,\
40 HasReposGroupPermissionAnyDecorator
40 41 from rhodecode.lib.base import BaseController, render
41 42 from rhodecode.model.db import RepoGroup
42 43 from rhodecode.model.repos_group import ReposGroupModel
43 44 from rhodecode.model.forms import ReposGroupForm
44 45 from rhodecode.model.meta import Session
46 from rhodecode.model.repo import RepoModel
47 from webob.exc import HTTPInternalServerError
45 48
46 49 log = logging.getLogger(__name__)
47 50
@@ -60,6 +63,10 b' class ReposGroupsController(BaseControll'
60 63 c.repo_groups = RepoGroup.groups_choices()
61 64 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
62 65
66 repo_model = RepoModel()
67 c.users_array = repo_model.get_users_js()
68 c.users_groups_array = repo_model.get_users_groups_js()
69
63 70 def __load_data(self, group_id):
64 71 """
65 72 Load defaults settings for edit, and update
@@ -74,13 +81,22 b' class ReposGroupsController(BaseControll'
74 81
75 82 data['group_name'] = repo_group.name
76 83
84 # fill repository users
85 for p in repo_group.repo_group_to_perm:
86 data.update({'u_perm_%s' % p.user.username:
87 p.permission.permission_name})
88
89 # fill repository groups
90 for p in repo_group.users_group_to_perm:
91 data.update({'g_perm_%s' % p.users_group.users_group_name:
92 p.permission.permission_name})
93
77 94 return data
78 95
79 96 @HasPermissionAnyDecorator('hg.admin')
80 97 def index(self, format='html'):
81 98 """GET /repos_groups: All items in the collection"""
82 99 # url('repos_groups')
83
84 100 sk = lambda g: g.parents[0].group_name if g.parents else g.group_name
85 101 c.groups = sorted(RepoGroup.query().all(), key=sk)
86 102 return render('admin/repos_groups/repos_groups_show.html')
@@ -94,7 +110,11 b' class ReposGroupsController(BaseControll'
94 110 c.repo_groups_choices)()
95 111 try:
96 112 form_result = repos_group_form.to_python(dict(request.POST))
97 ReposGroupModel().create(form_result)
113 ReposGroupModel().create(
114 group_name=form_result['group_name'],
115 group_description=form_result['group_description'],
116 parent=form_result['group_parent_id']
117 )
98 118 Session.commit()
99 119 h.flash(_('created repos group %s') \
100 120 % form_result['group_name'], category='success')
@@ -134,10 +154,11 b' class ReposGroupsController(BaseControll'
134 154 self.__load_defaults()
135 155 c.repos_group = RepoGroup.get(id)
136 156
137 repos_group_form = ReposGroupForm(edit=True,
138 old_data=c.repos_group.get_dict(),
139 available_groups=
140 c.repo_groups_choices)()
157 repos_group_form = ReposGroupForm(
158 edit=True,
159 old_data=c.repos_group.get_dict(),
160 available_groups=c.repo_groups_choices
161 )()
141 162 try:
142 163 form_result = repos_group_form.to_python(dict(request.POST))
143 164 ReposGroupModel().update(id, form_result)
@@ -201,10 +222,52 b' class ReposGroupsController(BaseControll'
201 222
202 223 return redirect(url('repos_groups'))
203 224
225 @HasReposGroupPermissionAnyDecorator('group.admin')
226 def delete_repos_group_user_perm(self, group_name):
227 """
228 DELETE an existing repositories group permission user
229
230 :param group_name:
231 """
232
233 try:
234 ReposGroupModel().revoke_user_permission(
235 repos_group=group_name, user=request.POST['user_id']
236 )
237 Session.commit()
238 except Exception:
239 log.error(traceback.format_exc())
240 h.flash(_('An error occurred during deletion of group user'),
241 category='error')
242 raise HTTPInternalServerError()
243
244 @HasReposGroupPermissionAnyDecorator('group.admin')
245 def delete_repos_group_users_group_perm(self, group_name):
246 """
247 DELETE an existing repositories group permission users group
248
249 :param group_name:
250 """
251
252 try:
253 ReposGroupModel().revoke_users_group_permission(
254 repos_group=group_name,
255 group_name=request.POST['users_group_id']
256 )
257 Session.commit()
258 except Exception:
259 log.error(traceback.format_exc())
260 h.flash(_('An error occurred during deletion of group'
261 ' users groups'),
262 category='error')
263 raise HTTPInternalServerError()
264
204 265 def show_by_name(self, group_name):
205 266 id_ = RepoGroup.get_by_group_name(group_name).group_id
206 267 return self.show(id_)
207 268
269 @HasReposGroupPermissionAnyDecorator('group.read', 'group.write',
270 'group.admin')
208 271 def show(self, id, format='html'):
209 272 """GET /repos_groups/id: Show a specific item"""
210 273 # url('repos_group', id=ID)
@@ -240,7 +303,7 b' class ReposGroupsController(BaseControll'
240 303 defaults = self.__load_data(id_)
241 304
242 305 # we need to exclude this group from the group list for editing
243 c.repo_groups = filter(lambda x:x[0] != id_, c.repo_groups)
306 c.repo_groups = filter(lambda x: x[0] != id_, c.repo_groups)
244 307
245 308 return htmlfill.render(
246 309 render('admin/repos_groups/repos_groups_edit.html'),
@@ -401,13 +401,7 b' class ApiController(JSONRPCController):'
401 401 for g in groups:
402 402 group = RepoGroup.get_by_group_name(g)
403 403 if not group:
404 group = ReposGroupModel().create(
405 dict(
406 group_name=g,
407 group_description='',
408 group_parent_id=parent_id
409 )
410 )
404 group = ReposGroupModel().create(g, '', parent_id)
411 405 parent_id = group.group_id
412 406
413 407 repo = RepoModel().create(
@@ -434,11 +428,11 b' class ApiController(JSONRPCController):'
434 428 raise JSONRPCError('failed to create repository %s' % repo_name)
435 429
436 430 @HasPermissionAnyDecorator('hg.admin')
437 def add_user_to_repo(self, apiuser, repo_name, username, perm):
431 def grant_user_permission(self, repo_name, username, perm):
438 432 """
439 Add permission for a user to a repository
433 Grant permission for user on given repository, or update existing one
434 if found
440 435
441 :param apiuser:
442 436 :param repo_name:
443 437 :param username:
444 438 :param perm:
@@ -449,17 +443,15 b' class ApiController(JSONRPCController):'
449 443 if repo is None:
450 444 raise JSONRPCError('unknown repository %s' % repo)
451 445
452 try:
453 user = User.get_by_username(username)
454 except NoResultFound:
455 raise JSONRPCError('unknown user %s' % user)
446 user = User.get_by_username(username)
447 if user is None:
448 raise JSONRPCError('unknown user %s' % username)
456 449
457 RepositoryPermissionModel()\
458 .update_or_delete_user_permission(repo, user, perm)
450 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
451
459 452 Session.commit()
460
461 453 return dict(
462 msg='Added perm: %s for %s in repo: %s' % (
454 msg='Granted perm: %s for user: %s in repo: %s' % (
463 455 perm, username, repo_name
464 456 )
465 457 )
@@ -472,11 +464,45 b' class ApiController(JSONRPCController):'
472 464 )
473 465
474 466 @HasPermissionAnyDecorator('hg.admin')
475 def add_users_group_to_repo(self, apiuser, repo_name, group_name, perm):
467 def revoke_user_permission(self, repo_name, username):
468 """
469 Revoke permission for user on given repository
470
471 :param repo_name:
472 :param username:
476 473 """
477 Add permission for a users group to a repository
474
475 try:
476 repo = Repository.get_by_repo_name(repo_name)
477 if repo is None:
478 raise JSONRPCError('unknown repository %s' % repo)
479
480 user = User.get_by_username(username)
481 if user is None:
482 raise JSONRPCError('unknown user %s' % username)
483
484 RepoModel().revoke_user_permission(repo=repo_name, user=username)
478 485
479 :param apiuser:
486 Session.commit()
487 return dict(
488 msg='Revoked perm for user: %s in repo: %s' % (
489 username, repo_name
490 )
491 )
492 except Exception:
493 log.error(traceback.format_exc())
494 raise JSONRPCError(
495 'failed to edit permission %(repo)s for %(user)s' % dict(
496 user=username, repo=repo_name
497 )
498 )
499
500 @HasPermissionAnyDecorator('hg.admin')
501 def grant_users_group_permission(self, repo_name, group_name, perm):
502 """
503 Grant permission for users group on given repository, or update
504 existing one if found
505
480 506 :param repo_name:
481 507 :param group_name:
482 508 :param perm:
@@ -487,24 +513,59 b' class ApiController(JSONRPCController):'
487 513 if repo is None:
488 514 raise JSONRPCError('unknown repository %s' % repo)
489 515
490 try:
491 user_group = UsersGroup.get_by_group_name(group_name)
492 except NoResultFound:
516 user_group = UsersGroup.get_by_group_name(group_name)
517 if user_group is None:
493 518 raise JSONRPCError('unknown users group %s' % user_group)
494 519
495 RepositoryPermissionModel()\
496 .update_or_delete_users_group_permission(repo, user_group,
497 perm)
520 RepoModel().grant_users_group_permission(repo=repo_name,
521 group_name=group_name,
522 perm=perm)
523
498 524 Session.commit()
499 525 return dict(
500 msg='Added perm: %s for %s in repo: %s' % (
526 msg='Granted perm: %s for group: %s in repo: %s' % (
501 527 perm, group_name, repo_name
502 528 )
503 529 )
504 530 except Exception:
505 531 log.error(traceback.format_exc())
506 532 raise JSONRPCError(
507 'failed to edit permission %(repo)s for %(usergr)s' % dict(
508 usergr=group_name, repo=repo_name
533 'failed to edit permission %(repo)s for %(usersgr)s' % dict(
534 usersgr=group_name, repo=repo_name
509 535 )
510 536 )
537
538 @HasPermissionAnyDecorator('hg.admin')
539 def revoke_users_group_permission(self, repo_name, group_name):
540 """
541 Revoke permission for users group on given repository
542
543 :param repo_name:
544 :param group_name:
545 """
546
547 try:
548 repo = Repository.get_by_repo_name(repo_name)
549 if repo is None:
550 raise JSONRPCError('unknown repository %s' % repo)
551
552 user_group = UsersGroup.get_by_group_name(group_name)
553 if user_group is None:
554 raise JSONRPCError('unknown users group %s' % user_group)
555
556 RepoModel().revoke_users_group_permission(repo=repo_name,
557 group_name=group_name)
558
559 Session.commit()
560 return dict(
561 msg='Revoked perm for group: %s in repo: %s' % (
562 group_name, repo_name
563 )
564 )
565 except Exception:
566 log.error(traceback.format_exc())
567 raise JSONRPCError(
568 'failed to edit permission %(repo)s for %(usersgr)s' % dict(
569 usersgr=group_name, repo=repo_name
570 )
571 )
@@ -30,7 +30,7 b' from paste.httpexceptions import HTTPBad'
30 30
31 31 from rhodecode.lib.auth import LoginRequired
32 32 from rhodecode.lib.base import BaseController, render
33 from rhodecode.model.db import RepoGroup, Repository
33 from rhodecode.model.db import Repository
34 34
35 35 log = logging.getLogger(__name__)
36 36
@@ -42,11 +42,8 b' class HomeController(BaseController):'
42 42 super(HomeController, self).__before__()
43 43
44 44 def index(self):
45
46 45 c.repos_list = self.scm_model.get_repos()
47
48 c.groups = RepoGroup.query()\
49 .filter(RepoGroup.group_parent_id == None).all()
46 c.groups = self.scm_model.get_repos_groups()
50 47
51 48 return render('/index.html')
52 49
@@ -25,6 +25,8 b''
25 25
26 26 import os
27 27 import re
28 from vcs.utils.lazy import LazyProperty
29
28 30
29 31 def __get_lem():
30 32 from pygments import lexers
@@ -213,6 +215,7 b" def safe_unicode(str_, from_encoding='ut"
213 215 except (ImportError, UnicodeDecodeError, Exception):
214 216 return unicode(str_, from_encoding, 'replace')
215 217
218
216 219 def safe_str(unicode_, to_encoding='utf8'):
217 220 """
218 221 safe str function. Does few trick to turn unicode_ into string
@@ -250,7 +253,6 b" def safe_str(unicode_, to_encoding='utf8"
250 253 return safe_str
251 254
252 255
253
254 256 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
255 257 """
256 258 Custom engine_from_config functions that makes sure we use NullPool for
@@ -393,6 +395,7 b' def credentials_filter(uri):'
393 395
394 396 return ''.join(uri)
395 397
398
396 399 def get_changeset_safe(repo, rev):
397 400 """
398 401 Safe version of get_changeset if this changeset doesn't exists for a
@@ -437,6 +440,7 b' def get_current_revision(quiet=False):'
437 440 "was: %s" % err)
438 441 return None
439 442
443
440 444 def extract_mentioned_users(s):
441 445 """
442 446 Returns unique usernames from given string s that have @mention
@@ -31,7 +31,7 b' import hashlib'
31 31 from tempfile import _RandomNameSequence
32 32 from decorator import decorator
33 33
34 from pylons import config, session, url, request
34 from pylons import config, url, request
35 35 from pylons.controllers.util import abort, redirect
36 36 from pylons.i18n.translation import _
37 37
@@ -45,7 +45,7 b' if __platform__ in PLATFORM_OTHERS:'
45 45
46 46 from rhodecode.lib import str2bool, safe_unicode
47 47 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
48 from rhodecode.lib.utils import get_repo_slug
48 from rhodecode.lib.utils import get_repo_slug, get_repos_group_slug
49 49 from rhodecode.lib.auth_ldap import AuthLdap
50 50
51 51 from rhodecode.model import meta
@@ -80,8 +80,8 b' class PasswordGenerator(object):'
80 80 def __init__(self, passwd=''):
81 81 self.passwd = passwd
82 82
83 def gen_password(self, len, type):
84 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
83 def gen_password(self, length, type_):
84 self.passwd = ''.join([random.choice(type_) for _ in xrange(length)])
85 85 return self.passwd
86 86
87 87
@@ -575,6 +575,41 b' class HasRepoPermissionAnyDecorator(Perm'
575 575 return False
576 576
577 577
578 class HasReposGroupPermissionAllDecorator(PermsDecorator):
579 """
580 Checks for access permission for all given predicates for specific
581 repository. All of them have to be meet in order to fulfill the request
582 """
583
584 def check_permissions(self):
585 group_name = get_repos_group_slug(request)
586 try:
587 user_perms = set([self.user_perms['repositories_groups'][group_name]])
588 except KeyError:
589 return False
590 if self.required_perms.issubset(user_perms):
591 return True
592 return False
593
594
595 class HasReposGroupPermissionAnyDecorator(PermsDecorator):
596 """
597 Checks for access permission for any of given predicates for specific
598 repository. In order to fulfill the request any of predicates must be meet
599 """
600
601 def check_permissions(self):
602 group_name = get_repos_group_slug(request)
603
604 try:
605 user_perms = set([self.user_perms['repositories_groups'][group_name]])
606 except KeyError:
607 return False
608 if self.required_perms.intersection(user_perms):
609 return True
610 return False
611
612
578 613 #==============================================================================
579 614 # CHECK FUNCTIONS
580 615 #==============================================================================
@@ -641,8 +676,9 b' class HasRepoPermissionAll(PermsFunction'
641 676 self.repo_name = get_repo_slug(request)
642 677
643 678 try:
644 self.user_perms = set([self.user_perms['reposit'
645 'ories'][self.repo_name]])
679 self.user_perms = set(
680 [self.user_perms['repositories'][self.repo_name]]
681 )
646 682 except KeyError:
647 683 return False
648 684 self.granted_for = self.repo_name
@@ -662,8 +698,9 b' class HasRepoPermissionAny(PermsFunction'
662 698 self.repo_name = get_repo_slug(request)
663 699
664 700 try:
665 self.user_perms = set([self.user_perms['reposi'
666 'tories'][self.repo_name]])
701 self.user_perms = set(
702 [self.user_perms['repositories'][self.repo_name]]
703 )
667 704 except KeyError:
668 705 return False
669 706 self.granted_for = self.repo_name
@@ -672,6 +709,42 b' class HasRepoPermissionAny(PermsFunction'
672 709 return False
673 710
674 711
712 class HasReposGroupPermissionAny(PermsFunction):
713 def __call__(self, group_name=None, check_Location=''):
714 self.group_name = group_name
715 return super(HasReposGroupPermissionAny, self).__call__(check_Location)
716
717 def check_permissions(self):
718 try:
719 self.user_perms = set(
720 [self.user_perms['repositories_groups'][self.group_name]]
721 )
722 except KeyError:
723 return False
724 self.granted_for = self.repo_name
725 if self.required_perms.intersection(self.user_perms):
726 return True
727 return False
728
729
730 class HasReposGroupPermissionAll(PermsFunction):
731 def __call__(self, group_name=None, check_Location=''):
732 self.group_name = group_name
733 return super(HasReposGroupPermissionAny, self).__call__(check_Location)
734
735 def check_permissions(self):
736 try:
737 self.user_perms = set(
738 [self.user_perms['repositories_groups'][self.group_name]]
739 )
740 except KeyError:
741 return False
742 self.granted_for = self.repo_name
743 if self.required_perms.issubset(self.user_perms):
744 return True
745 return False
746
747
675 748 #==============================================================================
676 749 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
677 750 #==============================================================================
@@ -442,23 +442,28 b' class DbManage(object):'
442 442
443 443 def create_permissions(self):
444 444 # module.(access|create|change|delete)_[name]
445 # module.(read|write|owner)
446 perms = [('repository.none', 'Repository no access'),
447 ('repository.read', 'Repository read access'),
448 ('repository.write', 'Repository write access'),
449 ('repository.admin', 'Repository admin access'),
450 ('hg.admin', 'Hg Administrator'),
451 ('hg.create.repository', 'Repository create'),
452 ('hg.create.none', 'Repository creation disabled'),
453 ('hg.register.none', 'Register disabled'),
454 ('hg.register.manual_activate', 'Register new user with '
455 'RhodeCode without manual'
456 'activation'),
445 # module.(none|read|write|admin)
446 perms = [
447 ('repository.none', 'Repository no access'),
448 ('repository.read', 'Repository read access'),
449 ('repository.write', 'Repository write access'),
450 ('repository.admin', 'Repository admin access'),
457 451
458 ('hg.register.auto_activate', 'Register new user with '
459 'RhodeCode without auto '
460 'activation'),
461 ]
452 ('group.none', 'Repositories Group no access'),
453 ('group.read', 'Repositories Group read access'),
454 ('group.write', 'Repositories Group write access'),
455 ('group.admin', 'Repositories Group admin access'),
456
457 ('hg.admin', 'Hg Administrator'),
458 ('hg.create.repository', 'Repository create'),
459 ('hg.create.none', 'Repository creation disabled'),
460 ('hg.register.none', 'Register disabled'),
461 ('hg.register.manual_activate', 'Register new user with RhodeCode '
462 'without manual activation'),
463
464 ('hg.register.auto_activate', 'Register new user with RhodeCode '
465 'without auto activation'),
466 ]
462 467
463 468 for p in perms:
464 469 new_perm = Permission()
@@ -130,7 +130,7 b' def log_create_repository(repository_dic'
130 130 Post create repository Hook. This is a dummy function for admins to re-use
131 131 if needed
132 132
133 :param repository: dict dump of repository object
133 :param repository: dict dump of repository object
134 134 :param created_by: username who created repository
135 135 :param created_date: date of creation
136 136
@@ -152,4 +152,4 b' def log_create_repository(repository_dic'
152 152 """
153 153
154 154
155 return 0 No newline at end of file
155 return 0
@@ -52,6 +52,7 b' from rhodecode.model import meta'
52 52 from rhodecode.model.db import Repository, User, RhodeCodeUi, \
53 53 UserLog, RepoGroup, RhodeCodeSetting
54 54 from rhodecode.model.meta import Session
55 from rhodecode.model.repos_group import ReposGroupModel
55 56
56 57 log = logging.getLogger(__name__)
57 58
@@ -94,6 +95,10 b' def get_repo_slug(request):'
94 95 return request.environ['pylons.routes_dict'].get('repo_name')
95 96
96 97
98 def get_repos_group_slug(request):
99 return request.environ['pylons.routes_dict'].get('group_name')
100
101
97 102 def action_logger(user, action, repo, ipaddr='', sa=None, commit=False):
98 103 """
99 104 Action logger for various actions made by users
@@ -197,6 +202,7 b' def is_valid_repo(repo_name, base_path):'
197 202 except VCSError:
198 203 return False
199 204
205
200 206 def is_valid_repos_group(repos_group_name, base_path):
201 207 """
202 208 Returns True if given path is a repos group False otherwise
@@ -216,6 +222,7 b' def is_valid_repos_group(repos_group_nam'
216 222
217 223 return False
218 224
225
219 226 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
220 227 while True:
221 228 ok = raw_input(prompt)
@@ -317,7 +324,8 b' class EmptyChangeset(BaseChangeset):'
317 324 an EmptyChangeset
318 325 """
319 326
320 def __init__(self, cs='0' * 40, repo=None, requested_revision=None, alias=None):
327 def __init__(self, cs='0' * 40, repo=None, requested_revision=None,
328 alias=None):
321 329 self._empty_cs = cs
322 330 self.revision = -1
323 331 self.message = ''
@@ -368,14 +376,23 b' def map_groups(groups):'
368 376
369 377 # last element is repo in nested groups structure
370 378 groups = groups[:-1]
371
379 rgm = ReposGroupModel(sa)
372 380 for lvl, group_name in enumerate(groups):
381 log.debug('creating group level: %s group_name: %s' % (lvl, group_name))
373 382 group_name = '/'.join(groups[:lvl] + [group_name])
374 group = sa.query(RepoGroup).filter(RepoGroup.group_name == group_name).scalar()
383 group = RepoGroup.get_by_group_name(group_name)
384 desc = '%s group' % group_name
385
386 # # WTF that doesn't work !?
387 # if group is None:
388 # group = rgm.create(group_name, desc, parent, just_db=True)
389 # sa.commit()
375 390
376 391 if group is None:
377 392 group = RepoGroup(group_name, parent)
393 group.group_description = desc
378 394 sa.add(group)
395 rgm._create_default_perms(group)
379 396 sa.commit()
380 397 parent = group
381 398 return group
@@ -404,15 +421,14 b' def repo2db_mapper(initial_repo_list, re'
404 421 log.info('repository %s not found creating default' % name)
405 422 added.append(name)
406 423 form_data = {
407 'repo_name': name,
408 'repo_name_full': name,
409 'repo_type': repo.alias,
410 'description': repo.description \
411 if repo.description != 'unknown' else \
412 '%s repository' % name,
413 'private': False,
414 'group_id': getattr(group, 'group_id', None)
415 }
424 'repo_name': name,
425 'repo_name_full': name,
426 'repo_type': repo.alias,
427 'description': repo.description \
428 if repo.description != 'unknown' else '%s repository' % name,
429 'private': False,
430 'group_id': getattr(group, 'group_id', None)
431 }
416 432 rm.create(form_data, user, just_db=True)
417 433 sa.commit()
418 434 removed = []
@@ -426,6 +442,7 b' def repo2db_mapper(initial_repo_list, re'
426 442
427 443 return added, removed
428 444
445
429 446 # set cache regions for beaker so celery can utilise it
430 447 def add_cache(settings):
431 448 cache_settings = {'regions': None}
@@ -74,12 +74,13 b' class BaseModel(object):'
74 74 else:
75 75 self.sa = meta.Session
76 76
77 def _get_instance(self, cls, instance):
77 def _get_instance(self, cls, instance, callback=None):
78 78 """
79 Get's instance of given cls using some simple lookup mechanism
79 Get's instance of given cls using some simple lookup mechanism.
80 80
81 81 :param cls: class to fetch
82 82 :param instance: int or Instance
83 :param callback: callback to call if all lookups failed
83 84 """
84 85
85 86 if isinstance(instance, cls):
@@ -88,5 +89,10 b' class BaseModel(object):'
88 89 return cls.get(instance)
89 90 else:
90 91 if instance:
91 raise Exception('given object must be int or Instance'
92 ' of %s got %s' % (type(cls), type(instance)))
92 if callback is None:
93 raise Exception(
94 'given object must be int or Instance of %s got %s, '
95 'no callback provided' % (cls, type(instance))
96 )
97 else:
98 return callback(instance)
@@ -717,6 +717,9 b' class RepoGroup(Base, BaseModel):'
717 717 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
718 718 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
719 719
720 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
721 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
722
720 723 parent_group = relationship('RepoGroup', remote_side=group_id)
721 724
722 725 def __init__(self, group_name='', parent_group=None):
@@ -833,8 +836,9 b' class Permission(Base, BaseModel):'
833 836 permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
834 837
835 838 def __repr__(self):
836 return "<%s('%s:%s')>" % (self.__class__.__name__,
837 self.permission_id, self.permission_name)
839 return "<%s('%s:%s')>" % (
840 self.__class__.__name__, self.permission_id, self.permission_name
841 )
838 842
839 843 @classmethod
840 844 def get_by_key(cls, key):
@@ -843,9 +847,18 b' class Permission(Base, BaseModel):'
843 847 @classmethod
844 848 def get_default_perms(cls, default_user_id):
845 849 q = Session.query(UserRepoToPerm, Repository, cls)\
846 .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
847 .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
848 .filter(UserRepoToPerm.user_id == default_user_id)
850 .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
851 .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
852 .filter(UserRepoToPerm.user_id == default_user_id)
853
854 return q.all()
855
856 @classmethod
857 def get_default_group_perms(cls, default_user_id):
858 q = Session.query(UserRepoGroupToPerm, RepoGroup, cls)\
859 .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
860 .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
861 .filter(UserRepoGroupToPerm.user_id == default_user_id)
849 862
850 863 return q.all()
851 864
@@ -388,57 +388,66 b' def ValidForkType(old_data):'
388 388 return _ValidForkType
389 389
390 390
391 class ValidPerms(formencode.validators.FancyValidator):
392 messages = {'perm_new_member_name': _('This username or users group name'
393 ' is not valid')}
391 def ValidPerms(type_='repo'):
392 if type_ == 'group':
393 EMPTY_PERM = 'group.none'
394 elif type_ == 'repo':
395 EMPTY_PERM = 'repository.none'
394 396
395 def to_python(self, value, state):
396 perms_update = []
397 perms_new = []
398 #build a list of permission to update and new permission to create
399 for k, v in value.items():
400 #means new added member to permissions
401 if k.startswith('perm_new_member'):
402 new_perm = value.get('perm_new_member', False)
403 new_member = value.get('perm_new_member_name', False)
404 new_type = value.get('perm_new_member_type')
397 class _ValidPerms(formencode.validators.FancyValidator):
398 messages = {
399 'perm_new_member_name':
400 _('This username or users group name is not valid')
401 }
402
403 def to_python(self, value, state):
404 perms_update = []
405 perms_new = []
406 # build a list of permission to update and new permission to create
407 for k, v in value.items():
408 # means new added member to permissions
409 if k.startswith('perm_new_member'):
410 new_perm = value.get('perm_new_member', False)
411 new_member = value.get('perm_new_member_name', False)
412 new_type = value.get('perm_new_member_type')
405 413
406 if new_member and new_perm:
407 if (new_member, new_perm, new_type) not in perms_new:
408 perms_new.append((new_member, new_perm, new_type))
409 elif k.startswith('u_perm_') or k.startswith('g_perm_'):
410 member = k[7:]
411 t = {'u': 'user',
412 'g': 'users_group'
413 }[k[0]]
414 if member == 'default':
415 if value['private']:
416 #set none for default when updating to private repo
417 v = 'repository.none'
418 perms_update.append((member, v, t))
414 if new_member and new_perm:
415 if (new_member, new_perm, new_type) not in perms_new:
416 perms_new.append((new_member, new_perm, new_type))
417 elif k.startswith('u_perm_') or k.startswith('g_perm_'):
418 member = k[7:]
419 t = {'u': 'user',
420 'g': 'users_group'
421 }[k[0]]
422 if member == 'default':
423 if value.get('private'):
424 # set none for default when updating to private repo
425 v = EMPTY_PERM
426 perms_update.append((member, v, t))
419 427
420 value['perms_updates'] = perms_update
421 value['perms_new'] = perms_new
428 value['perms_updates'] = perms_update
429 value['perms_new'] = perms_new
422 430
423 #update permissions
424 for k, v, t in perms_new:
425 try:
426 if t is 'user':
427 self.user_db = User.query()\
428 .filter(User.active == True)\
429 .filter(User.username == k).one()
430 if t is 'users_group':
431 self.user_db = UsersGroup.query()\
432 .filter(UsersGroup.users_group_active == True)\
433 .filter(UsersGroup.users_group_name == k).one()
431 # update permissions
432 for k, v, t in perms_new:
433 try:
434 if t is 'user':
435 self.user_db = User.query()\
436 .filter(User.active == True)\
437 .filter(User.username == k).one()
438 if t is 'users_group':
439 self.user_db = UsersGroup.query()\
440 .filter(UsersGroup.users_group_active == True)\
441 .filter(UsersGroup.users_group_name == k).one()
434 442
435 except Exception:
436 msg = self.message('perm_new_member_name',
437 state=State_obj)
438 raise formencode.Invalid(
439 msg, value, state, error_dict={'perm_new_member_name': msg}
440 )
441 return value
443 except Exception:
444 msg = self.message('perm_new_member_name',
445 state=State_obj)
446 raise formencode.Invalid(
447 msg, value, state, error_dict={'perm_new_member_name': msg}
448 )
449 return value
450 return _ValidPerms
442 451
443 452
444 453 class ValidSettings(formencode.validators.FancyValidator):
@@ -588,7 +597,7 b' def UsersGroupForm(edit=False, old_data='
588 597 def ReposGroupForm(edit=False, old_data={}, available_groups=[]):
589 598 class _ReposGroupForm(formencode.Schema):
590 599 allow_extra_fields = True
591 filter_extra_fields = True
600 filter_extra_fields = False
592 601
593 602 group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
594 603 SlugifyName())
@@ -598,7 +607,7 b' def ReposGroupForm(edit=False, old_data='
598 607 testValueList=True,
599 608 if_missing=None, not_empty=False)
600 609
601 chained_validators = [ValidReposGroup(edit, old_data)]
610 chained_validators = [ValidReposGroup(edit, old_data), ValidPerms('group')]
602 611
603 612 return _ReposGroupForm
604 613
@@ -649,7 +658,7 b' def RepoForm(edit=False, old_data={}, su'
649 658 #this is repo owner
650 659 user = All(UnicodeString(not_empty=True), ValidRepoUser)
651 660
652 chained_validators = [ValidRepoName(edit, old_data), ValidPerms]
661 chained_validators = [ValidRepoName(edit, old_data), ValidPerms()]
653 662 return _RepoForm
654 663
655 664
@@ -683,7 +692,7 b' def RepoSettingsForm(edit=False, old_dat'
683 692 repo_group = OneOf(repo_groups, hideList=True)
684 693 private = StringBoolean(if_missing=False)
685 694
686 chained_validators = [ValidRepoName(edit, old_data), ValidPerms,
695 chained_validators = [ValidRepoName(edit, old_data), ValidPerms(),
687 696 ValidSettings]
688 697 return _RepoForm
689 698
@@ -42,10 +42,7 b' log = logging.getLogger(__name__)'
42 42 class NotificationModel(BaseModel):
43 43
44 44 def __get_user(self, user):
45 if isinstance(user, basestring):
46 return User.get_by_username(username=user)
47 else:
48 return self._get_instance(User, user)
45 return self._get_instance(User, user, callback=User.get_by_username)
49 46
50 47 def __get_notification(self, notification):
51 48 if isinstance(notification, Notification):
@@ -28,9 +28,9 b' import logging'
28 28 import traceback
29 29 from datetime import datetime
30 30
31 from vcs.utils.lazy import LazyProperty
32 31 from vcs.backends import get_backend
33 32
33 from rhodecode.lib import LazyProperty
34 34 from rhodecode.lib import safe_str, safe_unicode
35 35 from rhodecode.lib.caching_query import FromCache
36 36 from rhodecode.lib.hooks import log_create_repository
@@ -39,11 +39,31 b' from rhodecode.model import BaseModel'
39 39 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
40 40 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup
41 41
42
42 43 log = logging.getLogger(__name__)
43 44
44 45
45 46 class RepoModel(BaseModel):
46 47
48 def __get_user(self, user):
49 return self._get_instance(User, user, callback=User.get_by_username)
50
51 def __get_users_group(self, users_group):
52 return self._get_instance(UsersGroup, users_group,
53 callback=UsersGroup.get_by_group_name)
54
55 def __get_repos_group(self, repos_group):
56 return self._get_instance(RepoGroup, repos_group,
57 callback=RepoGroup.get_by_group_name)
58
59 def __get_repo(self, repository):
60 return self._get_instance(Repository, repository,
61 callback=Repository.get_by_repo_name)
62
63 def __get_perm(self, permission):
64 return self._get_instance(Permission, permission,
65 callback=Permission.get_by_key)
66
47 67 @LazyProperty
48 68 def repos_path(self):
49 69 """
@@ -138,49 +158,24 b' class RepoModel(BaseModel):'
138 158 # update permissions
139 159 for member, perm, member_type in form_data['perms_updates']:
140 160 if member_type == 'user':
141 _member = User.get_by_username(member)
142 r2p = self.sa.query(UserRepoToPerm)\
143 .filter(UserRepoToPerm.user == _member)\
144 .filter(UserRepoToPerm.repository == cur_repo)\
145 .one()
146
147 r2p.permission = self.sa.query(Permission)\
148 .filter(Permission.permission_name ==
149 perm).scalar()
150 self.sa.add(r2p)
161 # this updates existing one
162 RepoModel().grant_user_permission(
163 repo=cur_repo, user=member, perm=perm
164 )
151 165 else:
152 g2p = self.sa.query(UsersGroupRepoToPerm)\
153 .filter(UsersGroupRepoToPerm.users_group ==
154 UsersGroup.get_by_group_name(member))\
155 .filter(UsersGroupRepoToPerm.repository ==
156 cur_repo).one()
157
158 g2p.permission = self.sa.query(Permission)\
159 .filter(Permission.permission_name ==
160 perm).scalar()
161 self.sa.add(g2p)
162
166 RepoModel().grant_users_group_permission(
167 repo=cur_repo, group_name=member, perm=perm
168 )
163 169 # set new permissions
164 170 for member, perm, member_type in form_data['perms_new']:
165 171 if member_type == 'user':
166 r2p = UserRepoToPerm()
167 r2p.repository = cur_repo
168 r2p.user = User.get_by_username(member)
169
170 r2p.permission = self.sa.query(Permission)\
171 .filter(Permission.
172 permission_name == perm)\
173 .scalar()
174 self.sa.add(r2p)
172 RepoModel().grant_user_permission(
173 repo=cur_repo, user=member, perm=perm
174 )
175 175 else:
176 g2p = UsersGroupRepoToPerm()
177 g2p.repository = cur_repo
178 g2p.users_group = UsersGroup.get_by_group_name(member)
179 g2p.permission = self.sa.query(Permission)\
180 .filter(Permission.
181 permission_name == perm)\
182 .scalar()
183 self.sa.add(g2p)
176 RepoModel().grant_users_group_permission(
177 repo=cur_repo, group_name=member, perm=perm
178 )
184 179
185 180 # update current repo
186 181 for k, v in form_data.items():
@@ -314,28 +309,93 b' class RepoModel(BaseModel):'
314 309 log.error(traceback.format_exc())
315 310 raise
316 311
317 def delete_perm_user(self, form_data, repo_name):
318 try:
319 obj = self.sa.query(UserRepoToPerm)\
320 .filter(UserRepoToPerm.repository \
321 == self.get_by_repo_name(repo_name))\
322 .filter(UserRepoToPerm.user_id == form_data['user_id']).one()
323 self.sa.delete(obj)
324 except:
325 log.error(traceback.format_exc())
326 raise
312 def grant_user_permission(self, repo, user, perm):
313 """
314 Grant permission for user on given repository, or update existing one
315 if found
316
317 :param repo: Instance of Repository, repository_id, or repository name
318 :param user: Instance of User, user_id or username
319 :param perm: Instance of Permission, or permission_name
320 """
321 user = self.__get_user(user)
322 repo = self.__get_repo(repo)
323 permission = self.__get_perm(perm)
324
325 # check if we have that permission already
326 obj = self.sa.query(UserRepoToPerm)\
327 .filter(UserRepoToPerm.user == user)\
328 .filter(UserRepoToPerm.repository == repo)\
329 .scalar()
330 if obj is None:
331 # create new !
332 obj = UserRepoToPerm()
333 obj.repository = repo
334 obj.user = user
335 obj.permission = permission
336 self.sa.add(obj)
337
338 def revoke_user_permission(self, repo, user):
339 """
340 Revoke permission for user on given repository
341
342 :param repo: Instance of Repository, repository_id, or repository name
343 :param user: Instance of User, user_id or username
344 """
345 user = self.__get_user(user)
346 repo = self.__get_repo(repo)
347
348 obj = self.sa.query(UserRepoToPerm)\
349 .filter(UserRepoToPerm.repository == repo)\
350 .filter(UserRepoToPerm.user == user)\
351 .one()
352 self.sa.delete(obj)
327 353
328 def delete_perm_users_group(self, form_data, repo_name):
329 try:
330 obj = self.sa.query(UsersGroupRepoToPerm)\
331 .filter(UsersGroupRepoToPerm.repository \
332 == self.get_by_repo_name(repo_name))\
333 .filter(UsersGroupRepoToPerm.users_group_id
334 == form_data['users_group_id']).one()
335 self.sa.delete(obj)
336 except:
337 log.error(traceback.format_exc())
338 raise
354 def grant_users_group_permission(self, repo, group_name, perm):
355 """
356 Grant permission for users group on given repository, or update
357 existing one if found
358
359 :param repo: Instance of Repository, repository_id, or repository name
360 :param group_name: Instance of UserGroup, users_group_id,
361 or users group name
362 :param perm: Instance of Permission, or permission_name
363 """
364 repo = self.__get_repo(repo)
365 group_name = self.__get_users_group(group_name)
366 permission = self.__get_perm(perm)
367
368 # check if we have that permission already
369 obj = self.sa.query(UsersGroupRepoToPerm)\
370 .filter(UsersGroupRepoToPerm.users_group == group_name)\
371 .filter(UsersGroupRepoToPerm.repository == repo)\
372 .scalar()
373
374 if obj is None:
375 # create new
376 obj = UsersGroupRepoToPerm()
377
378 obj.repository = repo
379 obj.users_group = group_name
380 obj.permission = permission
381 self.sa.add(obj)
382
383 def revoke_users_group_permission(self, repo, group_name):
384 """
385 Revoke permission for users group on given repository
386
387 :param repo: Instance of Repository, repository_id, or repository name
388 :param group_name: Instance of UserGroup, users_group_id,
389 or users group name
390 """
391 repo = self.__get_repo(repo)
392 group_name = self.__get_users_group(group_name)
393
394 obj = self.sa.query(UsersGroupRepoToPerm)\
395 .filter(UsersGroupRepoToPerm.repository == repo)\
396 .filter(UsersGroupRepoToPerm.users_group == group_name)\
397 .one()
398 self.sa.delete(obj)
339 399
340 400 def delete_stats(self, repo_name):
341 401 """
@@ -345,8 +405,9 b' class RepoModel(BaseModel):'
345 405 """
346 406 try:
347 407 obj = self.sa.query(Statistics)\
348 .filter(Statistics.repository == \
349 self.get_by_repo_name(repo_name)).one()
408 .filter(Statistics.repository ==
409 self.get_by_repo_name(repo_name))\
410 .one()
350 411 self.sa.delete(obj)
351 412 except:
352 413 log.error(traceback.format_exc())
@@ -373,10 +434,9 b' class RepoModel(BaseModel):'
373 434 new_parent_path = ''
374 435
375 436 # we need to make it str for mercurial
376 repo_path = os.path.join(*map(lambda x:safe_str(x),
437 repo_path = os.path.join(*map(lambda x: safe_str(x),
377 438 [self.repos_path, new_parent_path, repo_name]))
378 439
379
380 440 # check if this path is not a repository
381 441 if is_valid_repo(repo_path, self.repos_path):
382 442 raise Exception('This path %s is a valid repository' % repo_path)
@@ -393,7 +453,6 b' class RepoModel(BaseModel):'
393 453
394 454 backend(repo_path, create=True, src_url=clone_uri)
395 455
396
397 456 def __rename_repo(self, old, new):
398 457 """
399 458 renames repository on filesystem
@@ -406,8 +465,9 b' class RepoModel(BaseModel):'
406 465 old_path = os.path.join(self.repos_path, old)
407 466 new_path = os.path.join(self.repos_path, new)
408 467 if os.path.isdir(new_path):
409 raise Exception('Was trying to rename to already existing dir %s' \
410 % new_path)
468 raise Exception(
469 'Was trying to rename to already existing dir %s' % new_path
470 )
411 471 shutil.move(old_path, new_path)
412 472
413 473 def __delete_repo(self, repo):
@@ -426,7 +486,6 b' class RepoModel(BaseModel):'
426 486 shutil.move(os.path.join(rm_path, '.%s' % alias),
427 487 os.path.join(rm_path, 'rm__.%s' % alias))
428 488 # disable repo
429 shutil.move(rm_path, os.path.join(self.repos_path, 'rm__%s__%s' \
430 % (datetime.today()\
431 .strftime('%Y%m%d_%H%M%S_%f'),
432 repo.repo_name)))
489 _d = 'rm__%s__%s' % (datetime.now().strftime('%Y%m%d_%H%M%S_%f'),
490 repo.repo_name)
491 shutil.move(rm_path, os.path.join(self.repos_path, _d))
@@ -26,14 +26,29 b''
26 26
27 27 import logging
28 28 from rhodecode.model import BaseModel
29 from rhodecode.model.db import UserRepoToPerm, UsersGroupRepoToPerm, Permission
29 from rhodecode.model.db import UserRepoToPerm, UsersGroupRepoToPerm, Permission,\
30 User, Repository
30 31
31 32 log = logging.getLogger(__name__)
32 33
33 34
34 35 class RepositoryPermissionModel(BaseModel):
35 36
37 def __get_user(self, user):
38 return self._get_instance(User, user, callback=User.get_by_username)
39
40 def __get_repo(self, repository):
41 return self._get_instance(Repository, repository,
42 callback=Repository.get_by_repo_name)
43
44 def __get_perm(self, permission):
45 return self._get_instance(Permission, permission,
46 callback=Permission.get_by_key)
47
36 48 def get_user_permission(self, repository, user):
49 repository = self.__get_repo(repository)
50 user = self.__get_user(user)
51
37 52 return UserRepoToPerm.query() \
38 53 .filter(UserRepoToPerm.user == user) \
39 54 .filter(UserRepoToPerm.repository == repository) \
@@ -28,18 +28,32 b' import logging'
28 28 import traceback
29 29 import shutil
30 30
31 from pylons.i18n.translation import _
32
33 from vcs.utils.lazy import LazyProperty
31 from rhodecode.lib import LazyProperty
34 32
35 33 from rhodecode.model import BaseModel
36 from rhodecode.model.db import RepoGroup, RhodeCodeUi
34 from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
35 User, Permission, UsersGroupRepoGroupToPerm, UsersGroup
37 36
38 37 log = logging.getLogger(__name__)
39 38
40 39
41 40 class ReposGroupModel(BaseModel):
42 41
42 def __get_user(self, user):
43 return self._get_instance(User, user, callback=User.get_by_username)
44
45 def __get_users_group(self, users_group):
46 return self._get_instance(UsersGroup, users_group,
47 callback=UsersGroup.get_by_group_name)
48
49 def __get_repos_group(self, repos_group):
50 return self._get_instance(RepoGroup, repos_group,
51 callback=RepoGroup.get_by_group_name)
52
53 def __get_perm(self, permission):
54 return self._get_instance(Permission, permission,
55 callback=Permission.get_by_key)
56
43 57 @LazyProperty
44 58 def repos_path(self):
45 59 """
@@ -49,6 +63,24 b' class ReposGroupModel(BaseModel):'
49 63 q = RhodeCodeUi.get_by_key('/').one()
50 64 return q.ui_value
51 65
66 def _create_default_perms(self, new_group):
67 # create default permission
68 repo_group_to_perm = UserRepoGroupToPerm()
69 default_perm = 'group.read'
70 for p in User.get_by_username('default').user_perms:
71 if p.permission.permission_name.startswith('group.'):
72 default_perm = p.permission.permission_name
73 break
74
75 repo_group_to_perm.permission_id = self.sa.query(Permission)\
76 .filter(Permission.permission_name == default_perm)\
77 .one().permission_id
78
79 repo_group_to_perm.group = new_group
80 repo_group_to_perm.user_id = User.get_by_username('default').user_id
81
82 self.sa.add(repo_group_to_perm)
83
52 84 def __create_group(self, group_name):
53 85 """
54 86 makes repositories group on filesystem
@@ -102,16 +134,21 b' class ReposGroupModel(BaseModel):'
102 134 # delete only if that path really exists
103 135 os.rmdir(rm_path)
104 136
105 def create(self, form_data):
137 def create(self, group_name, group_description, parent, just_db=False):
106 138 try:
107 139 new_repos_group = RepoGroup()
108 new_repos_group.group_description = form_data['group_description']
109 new_repos_group.parent_group = RepoGroup.get(form_data['group_parent_id'])
110 new_repos_group.group_name = new_repos_group.get_new_name(form_data['group_name'])
140 new_repos_group.group_description = group_description
141 new_repos_group.parent_group = self.__get_repos_group(parent)
142 new_repos_group.group_name = new_repos_group.get_new_name(group_name)
111 143
112 144 self.sa.add(new_repos_group)
113 self.sa.flush()
114 self.__create_group(new_repos_group.group_name)
145 self._create_default_perms(new_repos_group)
146
147 if not just_db:
148 # we need to flush here, in order to check if database won't
149 # throw any exceptions, create filesystem dirs at the very end
150 self.sa.flush()
151 self.__create_group(new_repos_group.group_name)
115 152
116 153 return new_repos_group
117 154 except:
@@ -122,6 +159,29 b' class ReposGroupModel(BaseModel):'
122 159
123 160 try:
124 161 repos_group = RepoGroup.get(repos_group_id)
162
163 # update permissions
164 for member, perm, member_type in form_data['perms_updates']:
165 if member_type == 'user':
166 # this updates also current one if found
167 ReposGroupModel().grant_user_permission(
168 repos_group=repos_group, user=member, perm=perm
169 )
170 else:
171 ReposGroupModel().grant_users_group_permission(
172 repos_group=repos_group, group_name=member, perm=perm
173 )
174 # set new permissions
175 for member, perm, member_type in form_data['perms_new']:
176 if member_type == 'user':
177 ReposGroupModel().grant_user_permission(
178 repos_group=repos_group, user=member, perm=perm
179 )
180 else:
181 ReposGroupModel().grant_users_group_permission(
182 repos_group=repos_group, group_name=member, perm=perm
183 )
184
125 185 old_path = repos_group.full_path
126 186
127 187 # change properties
@@ -154,3 +214,97 b' class ReposGroupModel(BaseModel):'
154 214 except:
155 215 log.error(traceback.format_exc())
156 216 raise
217
218 def grant_user_permission(self, repos_group, user, perm):
219 """
220 Grant permission for user on given repositories group, or update
221 existing one if found
222
223 :param repos_group: Instance of ReposGroup, repositories_group_id,
224 or repositories_group name
225 :param user: Instance of User, user_id or username
226 :param perm: Instance of Permission, or permission_name
227 """
228
229 repos_group = self.__get_repos_group(repos_group)
230 user = self.__get_user(user)
231 permission = self.__get_perm(perm)
232
233 # check if we have that permission already
234 obj = self.sa.query(UserRepoGroupToPerm)\
235 .filter(UserRepoGroupToPerm.user == user)\
236 .filter(UserRepoGroupToPerm.group == repos_group)\
237 .scalar()
238 if obj is None:
239 # create new !
240 obj = UserRepoGroupToPerm()
241 obj.group = repos_group
242 obj.user = user
243 obj.permission = permission
244 self.sa.add(obj)
245
246 def revoke_user_permission(self, repos_group, user):
247 """
248 Revoke permission for user on given repositories group
249
250 :param repos_group: Instance of ReposGroup, repositories_group_id,
251 or repositories_group name
252 :param user: Instance of User, user_id or username
253 """
254
255 repos_group = self.__get_repos_group(repos_group)
256 user = self.__get_user(user)
257
258 obj = self.sa.query(UserRepoGroupToPerm)\
259 .filter(UserRepoGroupToPerm.user == user)\
260 .filter(UserRepoGroupToPerm.group == repos_group)\
261 .one()
262 self.sa.delete(obj)
263
264 def grant_users_group_permission(self, repos_group, group_name, perm):
265 """
266 Grant permission for users group on given repositories group, or update
267 existing one if found
268
269 :param repos_group: Instance of ReposGroup, repositories_group_id,
270 or repositories_group name
271 :param group_name: Instance of UserGroup, users_group_id,
272 or users group name
273 :param perm: Instance of Permission, or permission_name
274 """
275 repos_group = self.__get_repos_group(repos_group)
276 group_name = self.__get_users_group(group_name)
277 permission = self.__get_perm(perm)
278
279 # check if we have that permission already
280 obj = self.sa.query(UsersGroupRepoGroupToPerm)\
281 .filter(UsersGroupRepoGroupToPerm.group == repos_group)\
282 .filter(UsersGroupRepoGroupToPerm.users_group == group_name)\
283 .scalar()
284
285 if obj is None:
286 # create new
287 obj = UsersGroupRepoGroupToPerm()
288
289 obj.group = repos_group
290 obj.users_group = group_name
291 obj.permission = permission
292 self.sa.add(obj)
293
294 def revoke_users_group_permission(self, repos_group, group_name):
295 """
296 Revoke permission for users group on given repositories group
297
298 :param repos_group: Instance of ReposGroup, repositories_group_id,
299 or repositories_group name
300 :param group_name: Instance of UserGroup, users_group_id,
301 or users group name
302 """
303 repos_group = self.__get_repos_group(repos_group)
304 group_name = self.__get_users_group(group_name)
305
306 obj = self.sa.query(UsersGroupRepoGroupToPerm)\
307 .filter(UsersGroupRepoGroupToPerm.group == repos_group)\
308 .filter(UsersGroupRepoGroupToPerm.users_group == group_name)\
309 .one()
310 self.sa.delete(obj)
@@ -36,12 +36,12 b' from vcs.nodes import FileNode'
36 36 from rhodecode import BACKENDS
37 37 from rhodecode.lib import helpers as h
38 38 from rhodecode.lib import safe_str
39 from rhodecode.lib.auth import HasRepoPermissionAny
39 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
40 40 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
41 41 action_logger, EmptyChangeset
42 42 from rhodecode.model import BaseModel
43 43 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
44 UserFollowing, UserLog, User
44 UserFollowing, UserLog, User, RepoGroup
45 45
46 46 log = logging.getLogger(__name__)
47 47
@@ -80,15 +80,16 b' class CachedRepoList(object):'
80 80 for dbr in self.db_repo_list:
81 81 scmr = dbr.scm_instance_cached
82 82 # check permission at this level
83 if not HasRepoPermissionAny('repository.read', 'repository.write',
84 'repository.admin')(dbr.repo_name,
85 'get repo check'):
83 if not HasRepoPermissionAny(
84 'repository.read', 'repository.write', 'repository.admin'
85 )(dbr.repo_name, 'get repo check'):
86 86 continue
87 87
88 88 if scmr is None:
89 log.error('%s this repository is present in database but it '
90 'cannot be created as an scm instance',
91 dbr.repo_name)
89 log.error(
90 '%s this repository is present in database but it '
91 'cannot be created as an scm instance' % dbr.repo_name
92 )
92 93 continue
93 94
94 95 last_change = scmr.last_change
@@ -115,6 +116,28 b' class CachedRepoList(object):'
115 116 yield tmp_d
116 117
117 118
119 class GroupList(object):
120
121 def __init__(self, db_repo_group_list):
122 self.db_repo_group_list = db_repo_group_list
123
124 def __len__(self):
125 return len(self.db_repo_group_list)
126
127 def __repr__(self):
128 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
129
130 def __iter__(self):
131 for dbgr in self.db_repo_group_list:
132 # check permission at this level
133 if not HasReposGroupPermissionAny(
134 'group.read', 'group.write', 'group.admin'
135 )(dbgr.group_name, 'get group repo check'):
136 continue
137
138 yield dbgr
139
140
118 141 class ScmModel(BaseModel):
119 142 """
120 143 Generic Scm Model
@@ -200,6 +223,14 b' class ScmModel(BaseModel):'
200 223
201 224 return repo_iter
202 225
226 def get_repos_groups(self, all_groups=None):
227 if all_groups is None:
228 all_groups = RepoGroup.query()\
229 .filter(RepoGroup.group_parent_id == None).all()
230 group_iter = GroupList(all_groups)
231
232 return group_iter
233
203 234 def mark_for_invalidation(self, repo_name):
204 235 """Puts cache invalidation task into db for
205 236 further global cache invalidation
@@ -35,7 +35,7 b' from rhodecode.lib.caching_query import '
35 35 from rhodecode.model import BaseModel
36 36 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
37 37 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember, \
38 Notification
38 Notification, RepoGroup, UserRepoGroupToPerm, UsersGroup
39 39 from rhodecode.lib.exceptions import DefaultUserException, \
40 40 UserOwnsReposException
41 41
@@ -46,16 +46,26 b' from sqlalchemy.orm import joinedload'
46 46 log = logging.getLogger(__name__)
47 47
48 48
49 PERM_WEIGHTS = {'repository.none': 0,
50 'repository.read': 1,
51 'repository.write': 3,
52 'repository.admin': 3}
49 PERM_WEIGHTS = {
50 'repository.none': 0,
51 'repository.read': 1,
52 'repository.write': 3,
53 'repository.admin': 4,
54 'group.none': 0,
55 'group.read': 1,
56 'group.write': 3,
57 'group.admin': 4,
58 }
53 59
54 60
55 61 class UserModel(BaseModel):
56 62
57 63 def __get_user(self, user):
58 return self._get_instance(User, user)
64 return self._get_instance(User, user, callback=User.get_by_username)
65
66 def __get_perm(self, permission):
67 return self._get_instance(Permission, permission,
68 callback=Permission.get_by_key)
59 69
60 70 def get(self, user_id, cache=False):
61 71 user = self.sa.query(User)
@@ -348,9 +358,12 b' class UserModel(BaseModel):'
348 358
349 359 :param user: user instance to fill his perms
350 360 """
351
352 user.permissions['repositories'] = {}
353 user.permissions['global'] = set()
361 RK = 'repositories'
362 GK = 'repositories_groups'
363 GLOBAL = 'global'
364 user.permissions[RK] = {}
365 user.permissions[GK] = {}
366 user.permissions[GLOBAL] = set()
354 367
355 368 #======================================================================
356 369 # fetch default permissions
@@ -358,36 +371,45 b' class UserModel(BaseModel):'
358 371 default_user = User.get_by_username('default', cache=True)
359 372 default_user_id = default_user.user_id
360 373
361 default_perms = Permission.get_default_perms(default_user_id)
374 default_repo_perms = Permission.get_default_perms(default_user_id)
375 default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
362 376
363 377 if user.is_admin:
364 378 #==================================================================
365 # #admin have all default rights set to admin
379 # admin user have all default rights for repositories
380 # and groups set to admin
366 381 #==================================================================
367 user.permissions['global'].add('hg.admin')
382 user.permissions[GLOBAL].add('hg.admin')
368 383
369 for perm in default_perms:
384 # repositories
385 for perm in default_repo_perms:
386 r_k = perm.UserRepoToPerm.repository.repo_name
370 387 p = 'repository.admin'
371 user.permissions['repositories'][perm.UserRepoToPerm.
372 repository.repo_name] = p
388 user.permissions[RK][r_k] = p
389
390 # repositories groups
391 for perm in default_repo_groups_perms:
392 rg_k = perm.UserRepoGroupToPerm.group.group_name
393 p = 'group.admin'
394 user.permissions[GK][rg_k] = p
373 395
374 396 else:
375 397 #==================================================================
376 # set default permissions
398 # set default permissions first for repositories and groups
377 399 #==================================================================
378 400 uid = user.user_id
379 401
380 # default global
402 # default global permissions
381 403 default_global_perms = self.sa.query(UserToPerm)\
382 404 .filter(UserToPerm.user_id == default_user_id)
383 405
384 406 for perm in default_global_perms:
385 user.permissions['global'].add(perm.permission.permission_name)
407 user.permissions[GLOBAL].add(perm.permission.permission_name)
386 408
387 409 # default for repositories
388 for perm in default_perms:
389 if perm.Repository.private and not (perm.Repository.user_id ==
390 uid):
410 for perm in default_repo_perms:
411 r_k = perm.UserRepoToPerm.repository.repo_name
412 if perm.Repository.private and not (perm.Repository.user_id == uid):
391 413 # disable defaults for private repos,
392 414 p = 'repository.none'
393 415 elif perm.Repository.user_id == uid:
@@ -396,8 +418,13 b' class UserModel(BaseModel):'
396 418 else:
397 419 p = perm.Permission.permission_name
398 420
399 user.permissions['repositories'][perm.UserRepoToPerm.
400 repository.repo_name] = p
421 user.permissions[RK][r_k] = p
422
423 # default for repositories groups
424 for perm in default_repo_groups_perms:
425 rg_k = perm.UserRepoGroupToPerm.group.group_name
426 p = perm.Permission.permission_name
427 user.permissions[GK][rg_k] = p
401 428
402 429 #==================================================================
403 430 # overwrite default with user permissions if any
@@ -409,25 +436,24 b' class UserModel(BaseModel):'
409 436 .filter(UserToPerm.user_id == uid).all()
410 437
411 438 for perm in user_perms:
412 user.permissions['global'].add(perm.permission.permission_name)
439 user.permissions[GLOBAL].add(perm.permission.permission_name)
413 440
414 441 # user repositories
415 user_repo_perms = self.sa.query(UserRepoToPerm, Permission,
416 Repository)\
417 .join((Repository, UserRepoToPerm.repository_id ==
418 Repository.repo_id))\
419 .join((Permission, UserRepoToPerm.permission_id ==
420 Permission.permission_id))\
421 .filter(UserRepoToPerm.user_id == uid).all()
442 user_repo_perms = \
443 self.sa.query(UserRepoToPerm, Permission, Repository)\
444 .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
445 .join((Permission, UserRepoToPerm.permission_id == Permission.permission_id))\
446 .filter(UserRepoToPerm.user_id == uid)\
447 .all()
422 448
423 449 for perm in user_repo_perms:
424 450 # set admin if owner
451 r_k = perm.UserRepoToPerm.repository.repo_name
425 452 if perm.Repository.user_id == uid:
426 453 p = 'repository.admin'
427 454 else:
428 455 p = perm.Permission.permission_name
429 user.permissions['repositories'][perm.UserRepoToPerm.
430 repository.repo_name] = p
456 user.permissions[RK][r_k] = p
431 457
432 458 #==================================================================
433 459 # check if user is part of groups for this repository and fill in
@@ -442,30 +468,44 b' class UserModel(BaseModel):'
442 468 .filter(UsersGroupMember.user_id == uid).all()
443 469
444 470 for perm in user_perms_from_users_groups:
445 user.permissions['global'].add(perm.permission.permission_name)
471 user.permissions[GLOBAL].add(perm.permission.permission_name)
446 472
447 473 # users group repositories
448 user_repo_perms_from_users_groups = self.sa.query(
449 UsersGroupRepoToPerm,
450 Permission, Repository,)\
451 .join((Repository, UsersGroupRepoToPerm.repository_id ==
452 Repository.repo_id))\
453 .join((Permission, UsersGroupRepoToPerm.permission_id ==
454 Permission.permission_id))\
455 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
456 UsersGroupMember.users_group_id))\
457 .filter(UsersGroupMember.user_id == uid).all()
474 user_repo_perms_from_users_groups = \
475 self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\
476 .join((Repository, UsersGroupRepoToPerm.repository_id == Repository.repo_id))\
477 .join((Permission, UsersGroupRepoToPerm.permission_id == Permission.permission_id))\
478 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == UsersGroupMember.users_group_id))\
479 .filter(UsersGroupMember.user_id == uid)\
480 .all()
458 481
459 482 for perm in user_repo_perms_from_users_groups:
483 r_k = perm.UsersGroupRepoToPerm.repository.repo_name
460 484 p = perm.Permission.permission_name
461 cur_perm = user.permissions['repositories'][perm.
462 UsersGroupRepoToPerm.
463 repository.repo_name]
485 cur_perm = user.permissions[RK][r_k]
464 486 # overwrite permission only if it's greater than permission
465 487 # given from other sources
466 488 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
467 user.permissions['repositories'][perm.UsersGroupRepoToPerm.
468 repository.repo_name] = p
489 user.permissions[RK][r_k] = p
490
491 #==================================================================
492 # get access for this user for repos group and override defaults
493 #==================================================================
494
495 # user repositories groups
496 user_repo_groups_perms = \
497 self.sa.query(UserRepoGroupToPerm, Permission, RepoGroup)\
498 .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
499 .join((Permission, UserRepoGroupToPerm.permission_id == Permission.permission_id))\
500 .filter(UserRepoToPerm.user_id == uid)\
501 .all()
502
503 for perm in user_repo_groups_perms:
504 rg_k = perm.UserRepoGroupToPerm.group.group_name
505 p = perm.Permission.permission_name
506 cur_perm = user.permissions[GK][rg_k]
507 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
508 user.permissions[GK][rg_k] = p
469 509
470 510 return user
471 511
@@ -480,23 +520,28 b' class UserModel(BaseModel):'
480 520 .filter(UserToPerm.permission == perm).scalar() is not None
481 521
482 522 def grant_perm(self, user, perm):
483 if not isinstance(perm, Permission):
484 raise Exception('perm needs to be an instance of Permission class '
485 'got %s instead' % type(perm))
523 """
524 Grant user global permissions
486 525
526 :param user:
527 :param perm:
528 """
487 529 user = self.__get_user(user)
488
530 perm = self.__get_perm(perm)
489 531 new = UserToPerm()
490 532 new.user = user
491 533 new.permission = perm
492 534 self.sa.add(new)
493 535
494 536 def revoke_perm(self, user, perm):
495 if not isinstance(perm, Permission):
496 raise Exception('perm needs to be an instance of Permission class '
497 'got %s instead' % type(perm))
537 """
538 Revoke users global permissions
498 539
540 :param user:
541 :param perm:
542 """
499 543 user = self.__get_user(user)
544 perm = self.__get_perm(perm)
500 545
501 546 obj = UserToPerm.query().filter(UserToPerm.user == user)\
502 547 .filter(UserToPerm.permission == perm).scalar()
@@ -38,7 +38,12 b' log = logging.getLogger(__name__)'
38 38 class UsersGroupModel(BaseModel):
39 39
40 40 def __get_users_group(self, users_group):
41 return self._get_instance(UsersGroup, users_group)
41 return self._get_instance(UsersGroup, users_group,
42 callback=UsersGroup.get_by_group_name)
43
44 def __get_perm(self, permission):
45 return self._get_instance(Permission, permission,
46 callback=Permission.get_by_key)
42 47
43 48 def get(self, users_group_id, cache=False):
44 49 return UsersGroup.get(users_group_id)
@@ -80,7 +85,15 b' class UsersGroupModel(BaseModel):'
80 85 log.error(traceback.format_exc())
81 86 raise
82 87
83 def delete(self, users_group):
88 def delete(self, users_group, force=False):
89 """
90 Deletes repos group, unless force flag is used
91 raises exception if there are members in that group, else deletes
92 group and users
93
94 :param users_group:
95 :param force:
96 """
84 97 try:
85 98 users_group = self.__get_users_group(users_group)
86 99
@@ -88,7 +101,7 b' class UsersGroupModel(BaseModel):'
88 101 assigned_groups = UsersGroupRepoToPerm.query()\
89 102 .filter(UsersGroupRepoToPerm.users_group == users_group).all()
90 103
91 if assigned_groups:
104 if assigned_groups and force is False:
92 105 raise UsersGroupsAssignedException('RepoGroup assigned to %s' %
93 106 assigned_groups)
94 107
@@ -118,10 +131,8 b' class UsersGroupModel(BaseModel):'
118 131 raise
119 132
120 133 def has_perm(self, users_group, perm):
121 if not isinstance(perm, Permission):
122 raise Exception('perm needs to be an instance of Permission class')
123
124 134 users_group = self.__get_users_group(users_group)
135 perm = self.__get_perm(perm)
125 136
126 137 return UsersGroupToPerm.query()\
127 138 .filter(UsersGroupToPerm.users_group == users_group)\
@@ -139,10 +150,8 b' class UsersGroupModel(BaseModel):'
139 150 self.sa.add(new)
140 151
141 152 def revoke_perm(self, users_group, perm):
142 if not isinstance(perm, Permission):
143 raise Exception('perm needs to be an instance of Permission class')
144
145 153 users_group = self.__get_users_group(users_group)
154 perm = self.__get_perm(perm)
146 155
147 156 obj = UsersGroupToPerm.query()\
148 157 .filter(UsersGroupToPerm.users_group == users_group)\
@@ -53,9 +53,18 b''
53 53 ${h.select('group_parent_id','',c.repo_groups,class_="medium")}
54 54 </div>
55 55 </div>
56 <div class="field">
57 <div class="label">
58 <label for="input">${_('Permissions')}:</label>
59 </div>
60 <div class="input">
61 <%include file="repos_group_edit_perms.html"/>
62 </div>
56 63
64 </div>
57 65 <div class="buttons">
58 ${h.submit('save',_('save'),class_="ui-button")}
66 ${h.submit('save',_('Save'),class_="ui-button")}
67 ${h.reset('reset',_('Reset'),class_="ui-button")}
59 68 </div>
60 69 </div>
61 70 </div>
@@ -38,7 +38,9 b''
38 38 </div>
39 39 </td>
40 40 <td>${gr.group_description}</td>
41 ##<td><b>${gr.repositories.count()}</b></td>
41 ## this is commented out since for multi nested repos can be HEAVY!
42 ## in number of executed queries during traversing uncomment at will
43 ##<td><b>${gr.repositories_recursive_count}</b></td>
42 44 </tr>
43 45 % endfor
44 46
@@ -12,13 +12,27 b' from rhodecode.model.user import UserMod'
12 12 from rhodecode.model.meta import Session
13 13 from rhodecode.model.notification import NotificationModel
14 14 from rhodecode.model.users_group import UsersGroupModel
15 from rhodecode.lib.auth import AuthUser
16
17
18 def _make_group(path, desc='desc', parent_id=None,
19 skip_if_exists=False):
20
21 gr = RepoGroup.get_by_group_name(path)
22 if gr and skip_if_exists:
23 return gr
24
25 gr = ReposGroupModel().create(path, desc, parent_id)
26 Session.commit()
27 return gr
28
15 29
16 30 class TestReposGroups(unittest.TestCase):
17 31
18 32 def setUp(self):
19 self.g1 = self.__make_group('test1', skip_if_exists=True)
20 self.g2 = self.__make_group('test2', skip_if_exists=True)
21 self.g3 = self.__make_group('test3', skip_if_exists=True)
33 self.g1 = _make_group('test1', skip_if_exists=True)
34 self.g2 = _make_group('test2', skip_if_exists=True)
35 self.g3 = _make_group('test3', skip_if_exists=True)
22 36
23 37 def tearDown(self):
24 38 print 'out'
@@ -31,102 +45,81 b' class TestReposGroups(unittest.TestCase)'
31 45 def _check_folders(self):
32 46 print os.listdir(TESTS_TMP_PATH)
33 47
34 def __make_group(self, path, desc='desc', parent_id=None,
35 skip_if_exists=False):
36
37 gr = RepoGroup.get_by_group_name(path)
38 if gr and skip_if_exists:
39 return gr
40
41 form_data = dict(group_name=path,
42 group_description=desc,
43 group_parent_id=parent_id)
44 gr = ReposGroupModel().create(form_data)
45 Session.commit()
46 return gr
47
48 48 def __delete_group(self, id_):
49 49 ReposGroupModel().delete(id_)
50 50
51
52 51 def __update_group(self, id_, path, desc='desc', parent_id=None):
53 52 form_data = dict(group_name=path,
54 53 group_description=desc,
55 group_parent_id=parent_id)
54 group_parent_id=parent_id,
55 perms_updates=[],
56 perms_new=[])
56 57
57 58 gr = ReposGroupModel().update(id_, form_data)
58 59 return gr
59 60
60 61 def test_create_group(self):
61 g = self.__make_group('newGroup')
62 g = _make_group('newGroup')
62 63 self.assertEqual(g.full_path, 'newGroup')
63 64
64 65 self.assertTrue(self.__check_path('newGroup'))
65 66
66
67 67 def test_create_same_name_group(self):
68 self.assertRaises(IntegrityError, lambda:self.__make_group('newGroup'))
68 self.assertRaises(IntegrityError, lambda:_make_group('newGroup'))
69 69 Session.rollback()
70 70
71 71 def test_same_subgroup(self):
72 sg1 = self.__make_group('sub1', parent_id=self.g1.group_id)
72 sg1 = _make_group('sub1', parent_id=self.g1.group_id)
73 73 self.assertEqual(sg1.parent_group, self.g1)
74 74 self.assertEqual(sg1.full_path, 'test1/sub1')
75 75 self.assertTrue(self.__check_path('test1', 'sub1'))
76 76
77 ssg1 = self.__make_group('subsub1', parent_id=sg1.group_id)
77 ssg1 = _make_group('subsub1', parent_id=sg1.group_id)
78 78 self.assertEqual(ssg1.parent_group, sg1)
79 79 self.assertEqual(ssg1.full_path, 'test1/sub1/subsub1')
80 80 self.assertTrue(self.__check_path('test1', 'sub1', 'subsub1'))
81 81
82
83 82 def test_remove_group(self):
84 sg1 = self.__make_group('deleteme')
83 sg1 = _make_group('deleteme')
85 84 self.__delete_group(sg1.group_id)
86 85
87 86 self.assertEqual(RepoGroup.get(sg1.group_id), None)
88 87 self.assertFalse(self.__check_path('deteteme'))
89 88
90 sg1 = self.__make_group('deleteme', parent_id=self.g1.group_id)
89 sg1 = _make_group('deleteme', parent_id=self.g1.group_id)
91 90 self.__delete_group(sg1.group_id)
92 91
93 92 self.assertEqual(RepoGroup.get(sg1.group_id), None)
94 93 self.assertFalse(self.__check_path('test1', 'deteteme'))
95 94
96
97 95 def test_rename_single_group(self):
98 sg1 = self.__make_group('initial')
96 sg1 = _make_group('initial')
99 97
100 98 new_sg1 = self.__update_group(sg1.group_id, 'after')
101 99 self.assertTrue(self.__check_path('after'))
102 100 self.assertEqual(RepoGroup.get_by_group_name('initial'), None)
103 101
104
105 102 def test_update_group_parent(self):
106 103
107 sg1 = self.__make_group('initial', parent_id=self.g1.group_id)
104 sg1 = _make_group('initial', parent_id=self.g1.group_id)
108 105
109 106 new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g1.group_id)
110 107 self.assertTrue(self.__check_path('test1', 'after'))
111 108 self.assertEqual(RepoGroup.get_by_group_name('test1/initial'), None)
112 109
113
114 110 new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g3.group_id)
115 111 self.assertTrue(self.__check_path('test3', 'after'))
116 112 self.assertEqual(RepoGroup.get_by_group_name('test3/initial'), None)
117 113
118
119 114 new_sg1 = self.__update_group(sg1.group_id, 'hello')
120 115 self.assertTrue(self.__check_path('hello'))
121 116
122 117 self.assertEqual(RepoGroup.get_by_group_name('hello'), new_sg1)
123 118
124
125
126 119 def test_subgrouping_with_repo(self):
127 120
128 g1 = self.__make_group('g1')
129 g2 = self.__make_group('g2')
121 g1 = _make_group('g1')
122 g2 = _make_group('g2')
130 123
131 124 # create new repo
132 125 form_data = dict(repo_name='john',
@@ -150,13 +143,13 b' class TestReposGroups(unittest.TestCase)'
150 143 RepoModel().update(r.repo_name, form_data)
151 144 self.assertEqual(r.repo_name, 'g1/john')
152 145
153
154 146 self.__update_group(g1.group_id, 'g1', parent_id=g2.group_id)
155 147 self.assertTrue(self.__check_path('g2', 'g1'))
156 148
157 149 # test repo
158 150 self.assertEqual(r.repo_name, os.path.join('g2', 'g1', r.just_name))
159 151
152
160 153 class TestUser(unittest.TestCase):
161 154 def __init__(self, methodName='runTest'):
162 155 Session.remove()
@@ -245,7 +238,6 b' class TestNotifications(unittest.TestCas'
245 238 self.assertEqual(len(unotification), len(usrs))
246 239 self.assertEqual([x.user.user_id for x in unotification], usrs)
247 240
248
249 241 def test_user_notifications(self):
250 242 self.assertEqual([], Notification.query().all())
251 243 self.assertEqual([], UserNotification.query().all())
@@ -284,7 +276,6 b' class TestNotifications(unittest.TestCas'
284 276 == notification).all()
285 277 self.assertEqual(un, [])
286 278
287
288 279 def test_delete_association(self):
289 280
290 281 self.assertEqual([], Notification.query().all())
@@ -361,6 +352,7 b' class TestNotifications(unittest.TestCas'
361 352 self.assertEqual(NotificationModel()
362 353 .get_unread_cnt_for_user(self.u3), 2)
363 354
355
364 356 class TestUsers(unittest.TestCase):
365 357
366 358 def __init__(self, methodName='runTest'):
@@ -401,4 +393,163 b' class TestUsers(unittest.TestCase):'
401 393 #revoke
402 394 UserModel().revoke_perm(self.u1, perm)
403 395 Session.commit()
404 self.assertEqual(UserModel().has_perm(self.u1, perm),False)
396 self.assertEqual(UserModel().has_perm(self.u1, perm), False)
397
398
399 class TestPermissions(unittest.TestCase):
400 def __init__(self, methodName='runTest'):
401 super(TestPermissions, self).__init__(methodName=methodName)
402
403 def setUp(self):
404 self.u1 = UserModel().create_or_update(
405 username=u'u1', password=u'qweqwe',
406 email=u'u1@rhodecode.org', name=u'u1', lastname=u'u1'
407 )
408 self.a1 = UserModel().create_or_update(
409 username=u'a1', password=u'qweqwe',
410 email=u'a1@rhodecode.org', name=u'a1', lastname=u'a1', admin=True
411 )
412 Session.commit()
413
414 def tearDown(self):
415 UserModel().delete(self.u1)
416 UserModel().delete(self.a1)
417 if hasattr(self, 'g1'):
418 ReposGroupModel().delete(self.g1.group_id)
419 if hasattr(self, 'g2'):
420 ReposGroupModel().delete(self.g2.group_id)
421
422 if hasattr(self, 'ug1'):
423 UsersGroupModel().delete(self.ug1, force=True)
424
425 Session.commit()
426
427 def test_default_perms_set(self):
428 u1_auth = AuthUser(user_id=self.u1.user_id)
429 perms = {
430 'repositories_groups': {},
431 'global': set([u'hg.create.repository', u'repository.read',
432 u'hg.register.manual_activate']),
433 'repositories': {u'vcs_test_hg': u'repository.read'}
434 }
435 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
436 perms['repositories'][HG_REPO])
437 new_perm = 'repository.write'
438 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm)
439 Session.commit()
440
441 u1_auth = AuthUser(user_id=self.u1.user_id)
442 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO], new_perm)
443
444 def test_default_admin_perms_set(self):
445 a1_auth = AuthUser(user_id=self.a1.user_id)
446 perms = {
447 'repositories_groups': {},
448 'global': set([u'hg.admin']),
449 'repositories': {u'vcs_test_hg': u'repository.admin'}
450 }
451 self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
452 perms['repositories'][HG_REPO])
453 new_perm = 'repository.write'
454 RepoModel().grant_user_permission(repo=HG_REPO, user=self.a1, perm=new_perm)
455 Session.commit()
456 # cannot really downgrade admins permissions !? they still get's set as
457 # admin !
458 u1_auth = AuthUser(user_id=self.a1.user_id)
459 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
460 perms['repositories'][HG_REPO])
461
462 def test_default_group_perms(self):
463 self.g1 = _make_group('test1', skip_if_exists=True)
464 self.g2 = _make_group('test2', skip_if_exists=True)
465 u1_auth = AuthUser(user_id=self.u1.user_id)
466 perms = {
467 'repositories_groups': {u'test1': 'group.read', u'test2': 'group.read'},
468 'global': set([u'hg.create.repository', u'repository.read', u'hg.register.manual_activate']),
469 'repositories': {u'vcs_test_hg': u'repository.read'}
470 }
471 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
472 perms['repositories'][HG_REPO])
473 self.assertEqual(u1_auth.permissions['repositories_groups'],
474 perms['repositories_groups'])
475
476 def test_default_admin_group_perms(self):
477 self.g1 = _make_group('test1', skip_if_exists=True)
478 self.g2 = _make_group('test2', skip_if_exists=True)
479 a1_auth = AuthUser(user_id=self.a1.user_id)
480 perms = {
481 'repositories_groups': {u'test1': 'group.admin', u'test2': 'group.admin'},
482 'global': set(['hg.admin']),
483 'repositories': {u'vcs_test_hg': 'repository.admin'}
484 }
485
486 self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
487 perms['repositories'][HG_REPO])
488 self.assertEqual(a1_auth.permissions['repositories_groups'],
489 perms['repositories_groups'])
490
491 def test_propagated_permission_from_users_group(self):
492 # make group
493 self.ug1 = UsersGroupModel().create('G1')
494 # add user to group
495 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
496
497 # set permission to lower
498 new_perm = 'repository.none'
499 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm)
500 Session.commit()
501 u1_auth = AuthUser(user_id=self.u1.user_id)
502 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
503 new_perm)
504
505 # grant perm for group this should override permission from user
506 new_perm = 'repository.write'
507 RepoModel().grant_users_group_permission(repo=HG_REPO,
508 group_name=self.ug1,
509 perm=new_perm)
510 # check perms
511 u1_auth = AuthUser(user_id=self.u1.user_id)
512 perms = {
513 'repositories_groups': {},
514 'global': set([u'hg.create.repository', u'repository.read',
515 u'hg.register.manual_activate']),
516 'repositories': {u'vcs_test_hg': u'repository.read'}
517 }
518 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
519 new_perm)
520 self.assertEqual(u1_auth.permissions['repositories_groups'],
521 perms['repositories_groups'])
522
523 def test_propagated_permission_from_users_group_lower_weight(self):
524 # make group
525 self.ug1 = UsersGroupModel().create('G1')
526 # add user to group
527 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
528
529 # set permission to lower
530 new_perm_h = 'repository.write'
531 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1,
532 perm=new_perm_h)
533 Session.commit()
534 u1_auth = AuthUser(user_id=self.u1.user_id)
535 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
536 new_perm_h)
537
538 # grant perm for group this should NOT override permission from user
539 # since it's lower than granted
540 new_perm_l = 'repository.read'
541 RepoModel().grant_users_group_permission(repo=HG_REPO,
542 group_name=self.ug1,
543 perm=new_perm_l)
544 # check perms
545 u1_auth = AuthUser(user_id=self.u1.user_id)
546 perms = {
547 'repositories_groups': {},
548 'global': set([u'hg.create.repository', u'repository.read',
549 u'hg.register.manual_activate']),
550 'repositories': {u'vcs_test_hg': u'repository.write'}
551 }
552 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
553 new_perm_h)
554 self.assertEqual(u1_auth.permissions['repositories_groups'],
555 perms['repositories_groups'])
@@ -89,7 +89,7 b' beaker.cache.lock_dir=/tmp/data/cache/lo'
89 89 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
90 90
91 91 beaker.cache.super_short_term.type=memory
92 beaker.cache.super_short_term.expire=10
92 beaker.cache.super_short_term.expire=1
93 93 beaker.cache.super_short_term.key_length = 256
94 94
95 95 beaker.cache.short_term.type=memory
@@ -101,7 +101,7 b' beaker.cache.long_term.expire=36000'
101 101 beaker.cache.long_term.key_length = 256
102 102
103 103 beaker.cache.sql_cache_short.type=memory
104 beaker.cache.sql_cache_short.expire=10
104 beaker.cache.sql_cache_short.expire=1
105 105 beaker.cache.sql_cache_short.key_length = 256
106 106
107 107 beaker.cache.sql_cache_med.type=memory
General Comments 0
You need to be logged in to leave comments. Login now