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 | ``RhodeCode`` is a fast and powerful management tool for Mercurial_ and GIT_ |
|
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 | It works on http/https and has a built in permission/authentication system with |
|
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 |
|
8 | the ability to authenticate via LDAP or ActiveDirectory. RhodeCode also provides | |
9 | simple API so it's easy integrable with existing external systems. |
|
9 | simple API so it's easy integrable with existing external systems. | |
10 |
|
10 | |||
11 | RhodeCode is similar in some respects to github or bitbucket_, |
|
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 | This command can be executed only using api_key belonging to user with admin |
|
91 | This command can be executed only using api_key belonging to user with admin | |
92 | rights. |
|
92 | rights. | |
93 |
|
93 | |||
|
94 | ||||
94 | INPUT:: |
|
95 | INPUT:: | |
95 |
|
96 | |||
96 | api_key : "<api_key>" |
|
97 | api_key : "<api_key>" | |
@@ -122,6 +123,7 b' get_users' | |||||
122 | Lists all existing users. This command can be executed only using api_key |
|
123 | Lists all existing users. This command can be executed only using api_key | |
123 | belonging to user with admin rights. |
|
124 | belonging to user with admin rights. | |
124 |
|
125 | |||
|
126 | ||||
125 | INPUT:: |
|
127 | INPUT:: | |
126 |
|
128 | |||
127 | api_key : "<api_key>" |
|
129 | api_key : "<api_key>" | |
@@ -145,12 +147,14 b' OUTPUT::' | |||||
145 | ] |
|
147 | ] | |
146 | error: null |
|
148 | error: null | |
147 |
|
149 | |||
|
150 | ||||
148 | create_user |
|
151 | create_user | |
149 | ----------- |
|
152 | ----------- | |
150 |
|
153 | |||
151 | Creates new user or updates current one if such user exists. This command can |
|
154 | Creates new user or updates current one if such user exists. This command can | |
152 | be executed only using api_key belonging to user with admin rights. |
|
155 | be executed only using api_key belonging to user with admin rights. | |
153 |
|
156 | |||
|
157 | ||||
154 | INPUT:: |
|
158 | INPUT:: | |
155 |
|
159 | |||
156 | api_key : "<api_key>" |
|
160 | api_key : "<api_key>" | |
@@ -174,12 +178,14 b' OUTPUT::' | |||||
174 | } |
|
178 | } | |
175 | error: null |
|
179 | error: null | |
176 |
|
180 | |||
|
181 | ||||
177 | get_users_group |
|
182 | get_users_group | |
178 | --------------- |
|
183 | --------------- | |
179 |
|
184 | |||
180 | Gets an existing users group. This command can be executed only using api_key |
|
185 | Gets an existing users group. This command can be executed only using api_key | |
181 | belonging to user with admin rights. |
|
186 | belonging to user with admin rights. | |
182 |
|
187 | |||
|
188 | ||||
183 | INPUT:: |
|
189 | INPUT:: | |
184 |
|
190 | |||
185 | api_key : "<api_key>" |
|
191 | api_key : "<api_key>" | |
@@ -210,12 +216,14 b' OUTPUT::' | |||||
210 | } |
|
216 | } | |
211 | error : null |
|
217 | error : null | |
212 |
|
218 | |||
|
219 | ||||
213 | get_users_groups |
|
220 | get_users_groups | |
214 | ---------------- |
|
221 | ---------------- | |
215 |
|
222 | |||
216 | Lists all existing users groups. This command can be executed only using |
|
223 | Lists all existing users groups. This command can be executed only using | |
217 | api_key belonging to user with admin rights. |
|
224 | api_key belonging to user with admin rights. | |
218 |
|
225 | |||
|
226 | ||||
219 | INPUT:: |
|
227 | INPUT:: | |
220 |
|
228 | |||
221 | api_key : "<api_key>" |
|
229 | api_key : "<api_key>" | |
@@ -253,6 +261,7 b' create_users_group' | |||||
253 | Creates new users group. This command can be executed only using api_key |
|
261 | Creates new users group. This command can be executed only using api_key | |
254 | belonging to user with admin rights |
|
262 | belonging to user with admin rights | |
255 |
|
263 | |||
|
264 | ||||
256 | INPUT:: |
|
265 | INPUT:: | |
257 |
|
266 | |||
258 | api_key : "<api_key>" |
|
267 | api_key : "<api_key>" | |
@@ -270,12 +279,14 b' OUTPUT::' | |||||
270 | } |
|
279 | } | |
271 | error: null |
|
280 | error: null | |
272 |
|
281 | |||
|
282 | ||||
273 | add_user_to_users_group |
|
283 | add_user_to_users_group | |
274 | ----------------------- |
|
284 | ----------------------- | |
275 |
|
285 | |||
276 | Adds a user to a users group. This command can be executed only using api_key |
|
286 | Adds a user to a users group. This command can be executed only using api_key | |
277 | belonging to user with admin rights |
|
287 | belonging to user with admin rights | |
278 |
|
288 | |||
|
289 | ||||
279 | INPUT:: |
|
290 | INPUT:: | |
280 |
|
291 | |||
281 | api_key : "<api_key>" |
|
292 | api_key : "<api_key>" | |
@@ -293,12 +304,14 b' OUTPUT::' | |||||
293 | } |
|
304 | } | |
294 | error: null |
|
305 | error: null | |
295 |
|
306 | |||
|
307 | ||||
296 | get_repo |
|
308 | get_repo | |
297 | -------- |
|
309 | -------- | |
298 |
|
310 | |||
299 | Gets an existing repository. This command can be executed only using api_key |
|
311 | Gets an existing repository. This command can be executed only using api_key | |
300 | belonging to user with admin rights |
|
312 | belonging to user with admin rights | |
301 |
|
313 | |||
|
314 | ||||
302 | INPUT:: |
|
315 | INPUT:: | |
303 |
|
316 | |||
304 | api_key : "<api_key>" |
|
317 | api_key : "<api_key>" | |
@@ -338,12 +351,14 b' OUTPUT::' | |||||
338 | } |
|
351 | } | |
339 | error: null |
|
352 | error: null | |
340 |
|
353 | |||
|
354 | ||||
341 | get_repos |
|
355 | get_repos | |
342 | --------- |
|
356 | --------- | |
343 |
|
357 | |||
344 | Lists all existing repositories. This command can be executed only using api_key |
|
358 | Lists all existing repositories. This command can be executed only using api_key | |
345 | belonging to user with admin rights |
|
359 | belonging to user with admin rights | |
346 |
|
360 | |||
|
361 | ||||
347 | INPUT:: |
|
362 | INPUT:: | |
348 |
|
363 | |||
349 | api_key : "<api_key>" |
|
364 | api_key : "<api_key>" | |
@@ -372,6 +387,7 b" at given revision. It's possible to spec" | |||||
372 | `dirs`. This command can be executed only using api_key belonging to user |
|
387 | `dirs`. This command can be executed only using api_key belonging to user | |
373 | with admin rights |
|
388 | with admin rights | |
374 |
|
389 | |||
|
390 | ||||
375 | INPUT:: |
|
391 | INPUT:: | |
376 |
|
392 | |||
377 | api_key : "<api_key>" |
|
393 | api_key : "<api_key>" | |
@@ -395,7 +411,6 b' OUTPUT::' | |||||
395 | error: null |
|
411 | error: null | |
396 |
|
412 | |||
397 |
|
413 | |||
398 |
|
||||
399 | create_repo |
|
414 | create_repo | |
400 | ----------- |
|
415 | ----------- | |
401 |
|
416 | |||
@@ -405,6 +420,7 b' If repository name contains "/", all nee' | |||||
405 | For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent), |
|
420 | For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent), | |
406 | and create "baz" repository with "bar" as group. |
|
421 | and create "baz" repository with "bar" as group. | |
407 |
|
422 | |||
|
423 | ||||
408 | INPUT:: |
|
424 | INPUT:: | |
409 |
|
425 | |||
410 | api_key : "<api_key>" |
|
426 | api_key : "<api_key>" | |
@@ -420,54 +436,106 b' INPUT::' | |||||
420 | OUTPUT:: |
|
436 | OUTPUT:: | |
421 |
|
437 | |||
422 | result: { |
|
438 | result: { | |
423 |
|
|
439 | "id": "<newrepoid>", | |
424 |
|
|
440 | "msg": "Created new repository <reponame>", | |
425 | } |
|
441 | } | |
426 | error: null |
|
442 | error: null | |
427 |
|
443 | |||
428 | add_user_to_repo |
|
444 | ||
429 | ---------------- |
|
445 | grant_user_permission | |
|
446 | --------------------- | |||
430 |
|
447 | |||
431 | Add a user to a repository. This command can be executed only using api_key |
|
448 | Grant permission for user on given repository, or update existing one | |
432 | belonging to user with admin rights. |
|
449 | if found. This command can be executed only using api_key belonging to user | |
433 | If "perm" is None, user will be removed from the repository. |
|
450 | with admin rights. | |
|
451 | ||||
434 |
|
452 | |||
435 | INPUT:: |
|
453 | INPUT:: | |
436 |
|
454 | |||
437 | api_key : "<api_key>" |
|
455 | api_key : "<api_key>" | |
438 |
method : " |
|
456 | method : "grant_user_permission" | |
439 | args: { |
|
457 | args: { | |
440 | "repo_name" : "<reponame>", |
|
458 | "repo_name" : "<reponame>", | |
441 | "username" : "<username>", |
|
459 | "username" : "<username>", | |
442 |
"perm" : "( |
|
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 | OUTPUT:: |
|
487 | OUTPUT:: | |
446 |
|
488 | |||
447 | result: { |
|
489 | result: { | |
448 |
|
|
490 | "msg" : "Revoked perm for user: <suername> in repo: <reponame>" | |
449 | } |
|
491 | } | |
450 | error: null |
|
492 | error: null | |
451 |
|
493 | |||
452 | add_users_group_to_repo |
|
494 | ||
453 | ----------------------- |
|
495 | grant_users_group_permission | |
|
496 | ---------------------------- | |||
454 |
|
497 | |||
455 | Add a users group to a repository. This command can be executed only using |
|
498 | Grant permission for users group on given repository, or update | |
456 | api_key belonging to user with admin rights. If "perm" is None, group will |
|
499 | existing one if found. This command can be executed only using | |
457 | be removed from the repository. |
|
500 | api_key belonging to user with admin rights. | |
|
501 | ||||
458 |
|
502 | |||
459 | INPUT:: |
|
503 | INPUT:: | |
460 |
|
504 | |||
461 | api_key : "<api_key>" |
|
505 | api_key : "<api_key>" | |
462 |
method : " |
|
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 | args: { |
|
531 | args: { | |
464 | "repo_name" : "<reponame>", |
|
532 | "repo_name" : "<reponame>", | |
465 |
"group |
|
533 | "users_group" : "<usersgroupname>", | |
466 | "perm" : "(None|repository.(read|write|admin))", |
|
|||
467 | } |
|
534 | } | |
|
535 | ||||
468 | OUTPUT:: |
|
536 | OUTPUT:: | |
469 |
|
537 | |||
470 | result: { |
|
538 | result: { | |
471 |
|
|
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 | from rhodecode.lib.profiler import ProfilingMiddleware |
|
51 | from rhodecode.lib.profiler import ProfilingMiddleware | |
52 | app = ProfilingMiddleware(app) |
|
52 | app = ProfilingMiddleware(app) | |
53 |
|
53 | |||
|
54 | if asbool(full_stack): | |||
54 |
|
55 | |||
55 | if asbool(full_stack): |
|
|||
56 | # Handle Python exceptions |
|
56 | # Handle Python exceptions | |
57 | app = ErrorHandler(app, global_conf, **config['pylons.errorware']) |
|
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 | app = Cascade([static_app, app]) |
|
80 | app = Cascade([static_app, app]) | |
81 | app = make_gzip_middleware(app, global_conf, compress_level=1) |
|
81 | app = make_gzip_middleware(app, global_conf, compress_level=1) | |
82 |
|
82 | |||
83 |
|
||||
84 | app.config = config |
|
83 | app.config = config | |
85 |
|
84 | |||
86 | return app |
|
85 | return app |
@@ -113,8 +113,9 b' def make_map(config):' | |||||
113 | function=check_repo)) |
|
113 | function=check_repo)) | |
114 | #ajax delete repo perm user |
|
114 | #ajax delete repo perm user | |
115 | m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}", |
|
115 | m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}", | |
116 |
action="delete_perm_user", |
|
116 | action="delete_perm_user", | |
117 | function=check_repo)) |
|
117 | conditions=dict(method=["DELETE"], function=check_repo)) | |
|
118 | ||||
118 | #ajax delete repo perm users_group |
|
119 | #ajax delete repo perm users_group | |
119 | m.connect('delete_repo_users_group', |
|
120 | m.connect('delete_repo_users_group', | |
120 | "/repos_delete_users_group/{repo_name:.*}", |
|
121 | "/repos_delete_users_group/{repo_name:.*}", | |
@@ -128,7 +129,7 b' def make_map(config):' | |||||
128 | m.connect('repo_cache', "/repos_cache/{repo_name:.*}", |
|
129 | m.connect('repo_cache', "/repos_cache/{repo_name:.*}", | |
129 | action="repo_cache", conditions=dict(method=["DELETE"], |
|
130 | action="repo_cache", conditions=dict(method=["DELETE"], | |
130 | function=check_repo)) |
|
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 | action="repo_public_journal", conditions=dict(method=["PUT"], |
|
133 | action="repo_public_journal", conditions=dict(method=["PUT"], | |
133 | function=check_repo)) |
|
134 | function=check_repo)) | |
134 | m.connect('repo_pull', "/repo_pull/{repo_name:.*}", |
|
135 | m.connect('repo_pull', "/repo_pull/{repo_name:.*}", | |
@@ -169,6 +170,17 b' def make_map(config):' | |||||
169 | m.connect("formatted_repos_group", "/repos_groups/{id}.{format}", |
|
170 | m.connect("formatted_repos_group", "/repos_groups/{id}.{format}", | |
170 | action="show", conditions=dict(method=["GET"], |
|
171 | action="show", conditions=dict(method=["GET"], | |
171 | function=check_int)) |
|
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 | #ADMIN USER REST ROUTES |
|
185 | #ADMIN USER REST ROUTES | |
174 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
186 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
@@ -310,8 +322,6 b' def make_map(config):' | |||||
310 | m.connect("formatted_notification", "/notifications/{notification_id}.{format}", |
|
322 | m.connect("formatted_notification", "/notifications/{notification_id}.{format}", | |
311 | action="show", conditions=dict(method=["GET"])) |
|
323 | action="show", conditions=dict(method=["GET"])) | |
312 |
|
324 | |||
313 |
|
||||
314 |
|
||||
315 | #ADMIN MAIN PAGES |
|
325 | #ADMIN MAIN PAGES | |
316 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
326 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
317 | controller='admin/admin') as m: |
|
327 | controller='admin/admin') as m: | |
@@ -320,13 +330,12 b' def make_map(config):' | |||||
320 | action='add_repo') |
|
330 | action='add_repo') | |
321 |
|
331 | |||
322 | #========================================================================== |
|
332 | #========================================================================== | |
323 |
# API V |
|
333 | # API V2 | |
324 | #========================================================================== |
|
334 | #========================================================================== | |
325 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
335 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
326 | controller='api/api') as m: |
|
336 | controller='api/api') as m: | |
327 | m.connect('api', '/api') |
|
337 | m.connect('api', '/api') | |
328 |
|
338 | |||
329 |
|
||||
330 | #USER JOURNAL |
|
339 | #USER JOURNAL | |
331 | rmap.connect('journal', '%s/journal' % ADMIN_PREFIX, controller='journal') |
|
340 | rmap.connect('journal', '%s/journal' % ADMIN_PREFIX, controller='journal') | |
332 |
|
341 | |||
@@ -388,11 +397,13 b' def make_map(config):' | |||||
388 | controller='changeset', revision='tip', |
|
397 | controller='changeset', revision='tip', | |
389 | conditions=dict(function=check_repo)) |
|
398 | conditions=dict(function=check_repo)) | |
390 |
|
399 | |||
391 |
rmap.connect('changeset_comment', |
|
400 | rmap.connect('changeset_comment', | |
|
401 | '/{repo_name:.*}/changeset/{revision}/comment', | |||
392 | controller='changeset', revision='tip', action='comment', |
|
402 | controller='changeset', revision='tip', action='comment', | |
393 | conditions=dict(function=check_repo)) |
|
403 | conditions=dict(function=check_repo)) | |
394 |
|
404 | |||
395 |
rmap.connect('changeset_comment_delete', |
|
405 | rmap.connect('changeset_comment_delete', | |
|
406 | '/{repo_name:.*}/changeset/comment/{comment_id}/delete', | |||
396 | controller='changeset', action='delete_comment', |
|
407 | controller='changeset', action='delete_comment', | |
397 | conditions=dict(function=check_repo, method=["DELETE"])) |
|
408 | conditions=dict(function=check_repo, method=["DELETE"])) | |
398 |
|
409 | |||
@@ -493,5 +504,4 b' def make_map(config):' | |||||
493 | controller='followers', action='followers', |
|
504 | controller='followers', action='followers', | |
494 | conditions=dict(function=check_repo)) |
|
505 | conditions=dict(function=check_repo)) | |
495 |
|
506 | |||
496 |
|
||||
497 | return rmap |
|
507 | return rmap |
@@ -3,7 +3,7 b'' | |||||
3 | rhodecode.controllers.admin.repos |
|
3 | rhodecode.controllers.admin.repos | |
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
5 |
|
5 | |||
6 |
|
|
6 | Repositories controller for RhodeCode | |
7 |
|
7 | |||
8 | :created_on: Apr 7, 2010 |
|
8 | :created_on: Apr 7, 2010 | |
9 | :author: marcink |
|
9 | :author: marcink | |
@@ -277,7 +277,6 b' class ReposController(BaseController):' | |||||
277 |
|
277 | |||
278 | return redirect(url('repos')) |
|
278 | return redirect(url('repos')) | |
279 |
|
279 | |||
280 |
|
||||
281 | @HasRepoPermissionAllDecorator('repository.admin') |
|
280 | @HasRepoPermissionAllDecorator('repository.admin') | |
282 | def delete_perm_user(self, repo_name): |
|
281 | def delete_perm_user(self, repo_name): | |
283 | """ |
|
282 | """ | |
@@ -287,10 +286,11 b' class ReposController(BaseController):' | |||||
287 | """ |
|
286 | """ | |
288 |
|
287 | |||
289 | try: |
|
288 | try: | |
290 | repo_model = RepoModel() |
|
289 | RepoModel().revoke_user_permission(repo=repo_name, | |
291 | repo_model.delete_perm_user(request.POST, repo_name) |
|
290 | user=request.POST['user_id']) | |
292 | Session.commit() |
|
291 | Session.commit() | |
293 |
except Exception |
|
292 | except Exception: | |
|
293 | log.error(traceback.format_exc()) | |||
294 | h.flash(_('An error occurred during deletion of repository user'), |
|
294 | h.flash(_('An error occurred during deletion of repository user'), | |
295 | category='error') |
|
295 | category='error') | |
296 | raise HTTPInternalServerError() |
|
296 | raise HTTPInternalServerError() | |
@@ -302,11 +302,14 b' class ReposController(BaseController):' | |||||
302 |
|
302 | |||
303 | :param repo_name: |
|
303 | :param repo_name: | |
304 | """ |
|
304 | """ | |
|
305 | ||||
305 | try: |
|
306 | try: | |
306 | repo_model = RepoModel() |
|
307 | RepoModel().revoke_users_group_permission( | |
307 | repo_model.delete_perm_users_group(request.POST, repo_name) |
|
308 | repo=repo_name, group_name=request.POST['users_group_id'] | |
|
309 | ) | |||
308 | Session.commit() |
|
310 | Session.commit() | |
309 |
except Exception |
|
311 | except Exception: | |
|
312 | log.error(traceback.format_exc()) | |||
310 | h.flash(_('An error occurred during deletion of repository' |
|
313 | h.flash(_('An error occurred during deletion of repository' | |
311 | ' users groups'), |
|
314 | ' users groups'), | |
312 | category='error') |
|
315 | category='error') | |
@@ -321,8 +324,7 b' class ReposController(BaseController):' | |||||
321 | """ |
|
324 | """ | |
322 |
|
325 | |||
323 | try: |
|
326 | try: | |
324 | repo_model = RepoModel() |
|
327 | RepoModel().delete_stats(repo_name) | |
325 | repo_model.delete_stats(repo_name) |
|
|||
326 | Session.commit() |
|
328 | Session.commit() | |
327 | except Exception, e: |
|
329 | except Exception, e: | |
328 | h.flash(_('An error occurred during deletion of repository stats'), |
|
330 | h.flash(_('An error occurred during deletion of repository stats'), |
@@ -3,7 +3,7 b'' | |||||
3 | rhodecode.controllers.admin.repos_groups |
|
3 | rhodecode.controllers.admin.repos_groups | |
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
5 |
|
5 | |||
6 |
|
|
6 | Repositories groups controller for RhodeCode | |
7 |
|
7 | |||
8 | :created_on: Mar 23, 2010 |
|
8 | :created_on: Mar 23, 2010 | |
9 | :author: marcink |
|
9 | :author: marcink | |
@@ -29,19 +29,22 b' import formencode' | |||||
29 |
|
29 | |||
30 | from formencode import htmlfill |
|
30 | from formencode import htmlfill | |
31 |
|
31 | |||
32 |
from pylons import request |
|
32 | from pylons import request, tmpl_context as c, url | |
33 |
from pylons.controllers.util import |
|
33 | from pylons.controllers.util import redirect | |
34 | from pylons.i18n.translation import _ |
|
34 | from pylons.i18n.translation import _ | |
35 |
|
35 | |||
36 | from sqlalchemy.exc import IntegrityError |
|
36 | from sqlalchemy.exc import IntegrityError | |
37 |
|
37 | |||
38 | from rhodecode.lib import helpers as h |
|
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 | from rhodecode.lib.base import BaseController, render |
|
41 | from rhodecode.lib.base import BaseController, render | |
41 | from rhodecode.model.db import RepoGroup |
|
42 | from rhodecode.model.db import RepoGroup | |
42 | from rhodecode.model.repos_group import ReposGroupModel |
|
43 | from rhodecode.model.repos_group import ReposGroupModel | |
43 | from rhodecode.model.forms import ReposGroupForm |
|
44 | from rhodecode.model.forms import ReposGroupForm | |
44 | from rhodecode.model.meta import Session |
|
45 | from rhodecode.model.meta import Session | |
|
46 | from rhodecode.model.repo import RepoModel | |||
|
47 | from webob.exc import HTTPInternalServerError | |||
45 |
|
48 | |||
46 | log = logging.getLogger(__name__) |
|
49 | log = logging.getLogger(__name__) | |
47 |
|
50 | |||
@@ -60,6 +63,10 b' class ReposGroupsController(BaseControll' | |||||
60 | c.repo_groups = RepoGroup.groups_choices() |
|
63 | c.repo_groups = RepoGroup.groups_choices() | |
61 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) |
|
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 | def __load_data(self, group_id): |
|
70 | def __load_data(self, group_id): | |
64 | """ |
|
71 | """ | |
65 | Load defaults settings for edit, and update |
|
72 | Load defaults settings for edit, and update | |
@@ -74,13 +81,22 b' class ReposGroupsController(BaseControll' | |||||
74 |
|
81 | |||
75 | data['group_name'] = repo_group.name |
|
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 | return data |
|
94 | return data | |
78 |
|
95 | |||
79 | @HasPermissionAnyDecorator('hg.admin') |
|
96 | @HasPermissionAnyDecorator('hg.admin') | |
80 | def index(self, format='html'): |
|
97 | def index(self, format='html'): | |
81 | """GET /repos_groups: All items in the collection""" |
|
98 | """GET /repos_groups: All items in the collection""" | |
82 | # url('repos_groups') |
|
99 | # url('repos_groups') | |
83 |
|
||||
84 | sk = lambda g: g.parents[0].group_name if g.parents else g.group_name |
|
100 | sk = lambda g: g.parents[0].group_name if g.parents else g.group_name | |
85 | c.groups = sorted(RepoGroup.query().all(), key=sk) |
|
101 | c.groups = sorted(RepoGroup.query().all(), key=sk) | |
86 | return render('admin/repos_groups/repos_groups_show.html') |
|
102 | return render('admin/repos_groups/repos_groups_show.html') | |
@@ -94,7 +110,11 b' class ReposGroupsController(BaseControll' | |||||
94 | c.repo_groups_choices)() |
|
110 | c.repo_groups_choices)() | |
95 | try: |
|
111 | try: | |
96 | form_result = repos_group_form.to_python(dict(request.POST)) |
|
112 | form_result = repos_group_form.to_python(dict(request.POST)) | |
97 |
ReposGroupModel().create( |
|
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 | Session.commit() |
|
118 | Session.commit() | |
99 | h.flash(_('created repos group %s') \ |
|
119 | h.flash(_('created repos group %s') \ | |
100 | % form_result['group_name'], category='success') |
|
120 | % form_result['group_name'], category='success') | |
@@ -134,10 +154,11 b' class ReposGroupsController(BaseControll' | |||||
134 | self.__load_defaults() |
|
154 | self.__load_defaults() | |
135 | c.repos_group = RepoGroup.get(id) |
|
155 | c.repos_group = RepoGroup.get(id) | |
136 |
|
156 | |||
137 |
repos_group_form = ReposGroupForm( |
|
157 | repos_group_form = ReposGroupForm( | |
138 | old_data=c.repos_group.get_dict(), |
|
158 | edit=True, | |
139 | available_groups= |
|
159 | old_data=c.repos_group.get_dict(), | |
140 | c.repo_groups_choices)() |
|
160 | available_groups=c.repo_groups_choices | |
|
161 | )() | |||
141 | try: |
|
162 | try: | |
142 | form_result = repos_group_form.to_python(dict(request.POST)) |
|
163 | form_result = repos_group_form.to_python(dict(request.POST)) | |
143 | ReposGroupModel().update(id, form_result) |
|
164 | ReposGroupModel().update(id, form_result) | |
@@ -201,10 +222,52 b' class ReposGroupsController(BaseControll' | |||||
201 |
|
222 | |||
202 | return redirect(url('repos_groups')) |
|
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 | def show_by_name(self, group_name): |
|
265 | def show_by_name(self, group_name): | |
205 | id_ = RepoGroup.get_by_group_name(group_name).group_id |
|
266 | id_ = RepoGroup.get_by_group_name(group_name).group_id | |
206 | return self.show(id_) |
|
267 | return self.show(id_) | |
207 |
|
268 | |||
|
269 | @HasReposGroupPermissionAnyDecorator('group.read', 'group.write', | |||
|
270 | 'group.admin') | |||
208 | def show(self, id, format='html'): |
|
271 | def show(self, id, format='html'): | |
209 | """GET /repos_groups/id: Show a specific item""" |
|
272 | """GET /repos_groups/id: Show a specific item""" | |
210 | # url('repos_group', id=ID) |
|
273 | # url('repos_group', id=ID) | |
@@ -240,7 +303,7 b' class ReposGroupsController(BaseControll' | |||||
240 | defaults = self.__load_data(id_) |
|
303 | defaults = self.__load_data(id_) | |
241 |
|
304 | |||
242 | # we need to exclude this group from the group list for editing |
|
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 | return htmlfill.render( |
|
308 | return htmlfill.render( | |
246 | render('admin/repos_groups/repos_groups_edit.html'), |
|
309 | render('admin/repos_groups/repos_groups_edit.html'), |
@@ -401,13 +401,7 b' class ApiController(JSONRPCController):' | |||||
401 | for g in groups: |
|
401 | for g in groups: | |
402 | group = RepoGroup.get_by_group_name(g) |
|
402 | group = RepoGroup.get_by_group_name(g) | |
403 | if not group: |
|
403 | if not group: | |
404 | group = ReposGroupModel().create( |
|
404 | group = ReposGroupModel().create(g, '', parent_id) | |
405 | dict( |
|
|||
406 | group_name=g, |
|
|||
407 | group_description='', |
|
|||
408 | group_parent_id=parent_id |
|
|||
409 | ) |
|
|||
410 | ) |
|
|||
411 | parent_id = group.group_id |
|
405 | parent_id = group.group_id | |
412 |
|
406 | |||
413 | repo = RepoModel().create( |
|
407 | repo = RepoModel().create( | |
@@ -434,11 +428,11 b' class ApiController(JSONRPCController):' | |||||
434 | raise JSONRPCError('failed to create repository %s' % repo_name) |
|
428 | raise JSONRPCError('failed to create repository %s' % repo_name) | |
435 |
|
429 | |||
436 | @HasPermissionAnyDecorator('hg.admin') |
|
430 | @HasPermissionAnyDecorator('hg.admin') | |
437 |
def |
|
431 | def grant_user_permission(self, repo_name, username, perm): | |
438 | """ |
|
432 | """ | |
439 |
|
|
433 | Grant permission for user on given repository, or update existing one | |
|
434 | if found | |||
440 |
|
435 | |||
441 | :param apiuser: |
|
|||
442 | :param repo_name: |
|
436 | :param repo_name: | |
443 | :param username: |
|
437 | :param username: | |
444 | :param perm: |
|
438 | :param perm: | |
@@ -449,17 +443,15 b' class ApiController(JSONRPCController):' | |||||
449 | if repo is None: |
|
443 | if repo is None: | |
450 | raise JSONRPCError('unknown repository %s' % repo) |
|
444 | raise JSONRPCError('unknown repository %s' % repo) | |
451 |
|
445 | |||
452 | try: |
|
446 | user = User.get_by_username(username) | |
453 | user = User.get_by_username(username) |
|
447 | if user is None: | |
454 | except NoResultFound: |
|
448 | raise JSONRPCError('unknown user %s' % username) | |
455 | raise JSONRPCError('unknown user %s' % user) |
|
|||
456 |
|
449 | |||
457 | RepositoryPermissionModel()\ |
|
450 | RepoModel().grant_user_permission(repo=repo, user=user, perm=perm) | |
458 | .update_or_delete_user_permission(repo, user, perm) |
|
451 | ||
459 | Session.commit() |
|
452 | Session.commit() | |
460 |
|
||||
461 | return dict( |
|
453 | return dict( | |
462 |
msg=' |
|
454 | msg='Granted perm: %s for user: %s in repo: %s' % ( | |
463 | perm, username, repo_name |
|
455 | perm, username, repo_name | |
464 | ) |
|
456 | ) | |
465 | ) |
|
457 | ) | |
@@ -472,11 +464,45 b' class ApiController(JSONRPCController):' | |||||
472 | ) |
|
464 | ) | |
473 |
|
465 | |||
474 | @HasPermissionAnyDecorator('hg.admin') |
|
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 | :param repo_name: |
|
506 | :param repo_name: | |
481 | :param group_name: |
|
507 | :param group_name: | |
482 | :param perm: |
|
508 | :param perm: | |
@@ -487,24 +513,59 b' class ApiController(JSONRPCController):' | |||||
487 | if repo is None: |
|
513 | if repo is None: | |
488 | raise JSONRPCError('unknown repository %s' % repo) |
|
514 | raise JSONRPCError('unknown repository %s' % repo) | |
489 |
|
515 | |||
490 | try: |
|
516 | user_group = UsersGroup.get_by_group_name(group_name) | |
491 | user_group = UsersGroup.get_by_group_name(group_name) |
|
517 | if user_group is None: | |
492 | except NoResultFound: |
|
|||
493 | raise JSONRPCError('unknown users group %s' % user_group) |
|
518 | raise JSONRPCError('unknown users group %s' % user_group) | |
494 |
|
519 | |||
495 | RepositoryPermissionModel()\ |
|
520 | RepoModel().grant_users_group_permission(repo=repo_name, | |
496 | .update_or_delete_users_group_permission(repo, user_group, |
|
521 | group_name=group_name, | |
497 |
|
|
522 | perm=perm) | |
|
523 | ||||
498 | Session.commit() |
|
524 | Session.commit() | |
499 | return dict( |
|
525 | return dict( | |
500 |
msg=' |
|
526 | msg='Granted perm: %s for group: %s in repo: %s' % ( | |
501 | perm, group_name, repo_name |
|
527 | perm, group_name, repo_name | |
502 | ) |
|
528 | ) | |
503 | ) |
|
529 | ) | |
504 | except Exception: |
|
530 | except Exception: | |
505 | log.error(traceback.format_exc()) |
|
531 | log.error(traceback.format_exc()) | |
506 | raise JSONRPCError( |
|
532 | raise JSONRPCError( | |
507 | 'failed to edit permission %(repo)s for %(usergr)s' % dict( |
|
533 | 'failed to edit permission %(repo)s for %(usersgr)s' % dict( | |
508 | usergr=group_name, repo=repo_name |
|
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 | from rhodecode.lib.auth import LoginRequired |
|
31 | from rhodecode.lib.auth import LoginRequired | |
32 | from rhodecode.lib.base import BaseController, render |
|
32 | from rhodecode.lib.base import BaseController, render | |
33 |
from rhodecode.model.db import |
|
33 | from rhodecode.model.db import Repository | |
34 |
|
34 | |||
35 | log = logging.getLogger(__name__) |
|
35 | log = logging.getLogger(__name__) | |
36 |
|
36 | |||
@@ -42,11 +42,8 b' class HomeController(BaseController):' | |||||
42 | super(HomeController, self).__before__() |
|
42 | super(HomeController, self).__before__() | |
43 |
|
43 | |||
44 | def index(self): |
|
44 | def index(self): | |
45 |
|
||||
46 | c.repos_list = self.scm_model.get_repos() |
|
45 | c.repos_list = self.scm_model.get_repos() | |
47 |
|
46 | c.groups = self.scm_model.get_repos_groups() | ||
48 | c.groups = RepoGroup.query()\ |
|
|||
49 | .filter(RepoGroup.group_parent_id == None).all() |
|
|||
50 |
|
47 | |||
51 | return render('/index.html') |
|
48 | return render('/index.html') | |
52 |
|
49 |
@@ -25,6 +25,8 b'' | |||||
25 |
|
25 | |||
26 | import os |
|
26 | import os | |
27 | import re |
|
27 | import re | |
|
28 | from vcs.utils.lazy import LazyProperty | |||
|
29 | ||||
28 |
|
30 | |||
29 | def __get_lem(): |
|
31 | def __get_lem(): | |
30 | from pygments import lexers |
|
32 | from pygments import lexers | |
@@ -213,6 +215,7 b" def safe_unicode(str_, from_encoding='ut" | |||||
213 | except (ImportError, UnicodeDecodeError, Exception): |
|
215 | except (ImportError, UnicodeDecodeError, Exception): | |
214 | return unicode(str_, from_encoding, 'replace') |
|
216 | return unicode(str_, from_encoding, 'replace') | |
215 |
|
217 | |||
|
218 | ||||
216 | def safe_str(unicode_, to_encoding='utf8'): |
|
219 | def safe_str(unicode_, to_encoding='utf8'): | |
217 | """ |
|
220 | """ | |
218 | safe str function. Does few trick to turn unicode_ into string |
|
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 | return safe_str |
|
253 | return safe_str | |
251 |
|
254 | |||
252 |
|
255 | |||
253 |
|
||||
254 | def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs): |
|
256 | def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs): | |
255 | """ |
|
257 | """ | |
256 | Custom engine_from_config functions that makes sure we use NullPool for |
|
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 | return ''.join(uri) |
|
396 | return ''.join(uri) | |
395 |
|
397 | |||
|
398 | ||||
396 | def get_changeset_safe(repo, rev): |
|
399 | def get_changeset_safe(repo, rev): | |
397 | """ |
|
400 | """ | |
398 | Safe version of get_changeset if this changeset doesn't exists for a |
|
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 | "was: %s" % err) |
|
440 | "was: %s" % err) | |
438 | return None |
|
441 | return None | |
439 |
|
442 | |||
|
443 | ||||
440 | def extract_mentioned_users(s): |
|
444 | def extract_mentioned_users(s): | |
441 | """ |
|
445 | """ | |
442 | Returns unique usernames from given string s that have @mention |
|
446 | Returns unique usernames from given string s that have @mention |
@@ -31,7 +31,7 b' import hashlib' | |||||
31 | from tempfile import _RandomNameSequence |
|
31 | from tempfile import _RandomNameSequence | |
32 | from decorator import decorator |
|
32 | from decorator import decorator | |
33 |
|
33 | |||
34 |
from pylons import config, |
|
34 | from pylons import config, url, request | |
35 | from pylons.controllers.util import abort, redirect |
|
35 | from pylons.controllers.util import abort, redirect | |
36 | from pylons.i18n.translation import _ |
|
36 | from pylons.i18n.translation import _ | |
37 |
|
37 | |||
@@ -45,7 +45,7 b' if __platform__ in PLATFORM_OTHERS:' | |||||
45 |
|
45 | |||
46 | from rhodecode.lib import str2bool, safe_unicode |
|
46 | from rhodecode.lib import str2bool, safe_unicode | |
47 | from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError |
|
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 | from rhodecode.lib.auth_ldap import AuthLdap |
|
49 | from rhodecode.lib.auth_ldap import AuthLdap | |
50 |
|
50 | |||
51 | from rhodecode.model import meta |
|
51 | from rhodecode.model import meta | |
@@ -80,8 +80,8 b' class PasswordGenerator(object):' | |||||
80 | def __init__(self, passwd=''): |
|
80 | def __init__(self, passwd=''): | |
81 | self.passwd = passwd |
|
81 | self.passwd = passwd | |
82 |
|
82 | |||
83 | def gen_password(self, len, type): |
|
83 | def gen_password(self, length, type_): | |
84 | self.passwd = ''.join([random.choice(type) for _ in xrange(len)]) |
|
84 | self.passwd = ''.join([random.choice(type_) for _ in xrange(length)]) | |
85 | return self.passwd |
|
85 | return self.passwd | |
86 |
|
86 | |||
87 |
|
87 | |||
@@ -575,6 +575,41 b' class HasRepoPermissionAnyDecorator(Perm' | |||||
575 | return False |
|
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 | # CHECK FUNCTIONS |
|
614 | # CHECK FUNCTIONS | |
580 | #============================================================================== |
|
615 | #============================================================================== | |
@@ -641,8 +676,9 b' class HasRepoPermissionAll(PermsFunction' | |||||
641 | self.repo_name = get_repo_slug(request) |
|
676 | self.repo_name = get_repo_slug(request) | |
642 |
|
677 | |||
643 | try: |
|
678 | try: | |
644 |
self.user_perms = set( |
|
679 | self.user_perms = set( | |
645 | 'ories'][self.repo_name]]) |
|
680 | [self.user_perms['repositories'][self.repo_name]] | |
|
681 | ) | |||
646 | except KeyError: |
|
682 | except KeyError: | |
647 | return False |
|
683 | return False | |
648 | self.granted_for = self.repo_name |
|
684 | self.granted_for = self.repo_name | |
@@ -662,8 +698,9 b' class HasRepoPermissionAny(PermsFunction' | |||||
662 | self.repo_name = get_repo_slug(request) |
|
698 | self.repo_name = get_repo_slug(request) | |
663 |
|
699 | |||
664 | try: |
|
700 | try: | |
665 |
self.user_perms = set( |
|
701 | self.user_perms = set( | |
666 | 'tories'][self.repo_name]]) |
|
702 | [self.user_perms['repositories'][self.repo_name]] | |
|
703 | ) | |||
667 | except KeyError: |
|
704 | except KeyError: | |
668 | return False |
|
705 | return False | |
669 | self.granted_for = self.repo_name |
|
706 | self.granted_for = self.repo_name | |
@@ -672,6 +709,42 b' class HasRepoPermissionAny(PermsFunction' | |||||
672 | return False |
|
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 | # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH |
|
749 | # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH | |
677 | #============================================================================== |
|
750 | #============================================================================== |
@@ -442,23 +442,28 b' class DbManage(object):' | |||||
442 |
|
442 | |||
443 | def create_permissions(self): |
|
443 | def create_permissions(self): | |
444 | # module.(access|create|change|delete)_[name] |
|
444 | # module.(access|create|change|delete)_[name] | |
445 |
# module.(read|write| |
|
445 | # module.(none|read|write|admin) | |
446 | perms = [('repository.none', 'Repository no access'), |
|
446 | perms = [ | |
447 |
|
|
447 | ('repository.none', 'Repository no access'), | |
448 |
|
|
448 | ('repository.read', 'Repository read access'), | |
449 |
|
|
449 | ('repository.write', 'Repository write access'), | |
450 | ('hg.admin', 'Hg Administrator'), |
|
450 | ('repository.admin', 'Repository admin access'), | |
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'), |
|
|||
457 |
|
451 | |||
458 | ('hg.register.auto_activate', 'Register new user with ' |
|
452 | ('group.none', 'Repositories Group no access'), | |
459 | 'RhodeCode without auto ' |
|
453 | ('group.read', 'Repositories Group read access'), | |
460 | 'activation'), |
|
454 | ('group.write', 'Repositories Group write access'), | |
461 | ] |
|
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 | for p in perms: |
|
468 | for p in perms: | |
464 | new_perm = Permission() |
|
469 | new_perm = Permission() |
@@ -130,7 +130,7 b' def log_create_repository(repository_dic' | |||||
130 | Post create repository Hook. This is a dummy function for admins to re-use |
|
130 | Post create repository Hook. This is a dummy function for admins to re-use | |
131 | if needed |
|
131 | if needed | |
132 |
|
132 | |||
133 |
:param repository: dict dump of repository object |
|
133 | :param repository: dict dump of repository object | |
134 | :param created_by: username who created repository |
|
134 | :param created_by: username who created repository | |
135 | :param created_date: date of creation |
|
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 | from rhodecode.model.db import Repository, User, RhodeCodeUi, \ |
|
52 | from rhodecode.model.db import Repository, User, RhodeCodeUi, \ | |
53 | UserLog, RepoGroup, RhodeCodeSetting |
|
53 | UserLog, RepoGroup, RhodeCodeSetting | |
54 | from rhodecode.model.meta import Session |
|
54 | from rhodecode.model.meta import Session | |
|
55 | from rhodecode.model.repos_group import ReposGroupModel | |||
55 |
|
56 | |||
56 | log = logging.getLogger(__name__) |
|
57 | log = logging.getLogger(__name__) | |
57 |
|
58 | |||
@@ -94,6 +95,10 b' def get_repo_slug(request):' | |||||
94 | return request.environ['pylons.routes_dict'].get('repo_name') |
|
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 | def action_logger(user, action, repo, ipaddr='', sa=None, commit=False): |
|
102 | def action_logger(user, action, repo, ipaddr='', sa=None, commit=False): | |
98 | """ |
|
103 | """ | |
99 | Action logger for various actions made by users |
|
104 | Action logger for various actions made by users | |
@@ -197,6 +202,7 b' def is_valid_repo(repo_name, base_path):' | |||||
197 | except VCSError: |
|
202 | except VCSError: | |
198 | return False |
|
203 | return False | |
199 |
|
204 | |||
|
205 | ||||
200 | def is_valid_repos_group(repos_group_name, base_path): |
|
206 | def is_valid_repos_group(repos_group_name, base_path): | |
201 | """ |
|
207 | """ | |
202 | Returns True if given path is a repos group False otherwise |
|
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 | return False |
|
223 | return False | |
218 |
|
224 | |||
|
225 | ||||
219 | def ask_ok(prompt, retries=4, complaint='Yes or no, please!'): |
|
226 | def ask_ok(prompt, retries=4, complaint='Yes or no, please!'): | |
220 | while True: |
|
227 | while True: | |
221 | ok = raw_input(prompt) |
|
228 | ok = raw_input(prompt) | |
@@ -317,7 +324,8 b' class EmptyChangeset(BaseChangeset):' | |||||
317 | an EmptyChangeset |
|
324 | an EmptyChangeset | |
318 | """ |
|
325 | """ | |
319 |
|
326 | |||
320 |
def __init__(self, cs='0' * 40, repo=None, requested_revision=None, |
|
327 | def __init__(self, cs='0' * 40, repo=None, requested_revision=None, | |
|
328 | alias=None): | |||
321 | self._empty_cs = cs |
|
329 | self._empty_cs = cs | |
322 | self.revision = -1 |
|
330 | self.revision = -1 | |
323 | self.message = '' |
|
331 | self.message = '' | |
@@ -368,14 +376,23 b' def map_groups(groups):' | |||||
368 |
|
376 | |||
369 | # last element is repo in nested groups structure |
|
377 | # last element is repo in nested groups structure | |
370 | groups = groups[:-1] |
|
378 | groups = groups[:-1] | |
371 |
|
379 | rgm = ReposGroupModel(sa) | ||
372 | for lvl, group_name in enumerate(groups): |
|
380 | for lvl, group_name in enumerate(groups): | |
|
381 | log.debug('creating group level: %s group_name: %s' % (lvl, group_name)) | |||
373 | group_name = '/'.join(groups[:lvl] + [group_name]) |
|
382 | group_name = '/'.join(groups[:lvl] + [group_name]) | |
374 |
group = |
|
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 | if group is None: |
|
391 | if group is None: | |
377 | group = RepoGroup(group_name, parent) |
|
392 | group = RepoGroup(group_name, parent) | |
|
393 | group.group_description = desc | |||
378 | sa.add(group) |
|
394 | sa.add(group) | |
|
395 | rgm._create_default_perms(group) | |||
379 | sa.commit() |
|
396 | sa.commit() | |
380 | parent = group |
|
397 | parent = group | |
381 | return group |
|
398 | return group | |
@@ -404,15 +421,14 b' def repo2db_mapper(initial_repo_list, re' | |||||
404 | log.info('repository %s not found creating default' % name) |
|
421 | log.info('repository %s not found creating default' % name) | |
405 | added.append(name) |
|
422 | added.append(name) | |
406 | form_data = { |
|
423 | form_data = { | |
407 |
|
|
424 | 'repo_name': name, | |
408 |
|
|
425 | 'repo_name_full': name, | |
409 |
|
|
426 | 'repo_type': repo.alias, | |
410 |
|
|
427 | 'description': repo.description \ | |
411 |
|
|
428 | if repo.description != 'unknown' else '%s repository' % name, | |
412 | '%s repository' % name, |
|
429 | 'private': False, | |
413 | 'private': False, |
|
430 | 'group_id': getattr(group, 'group_id', None) | |
414 | 'group_id': getattr(group, 'group_id', None) |
|
431 | } | |
415 | } |
|
|||
416 | rm.create(form_data, user, just_db=True) |
|
432 | rm.create(form_data, user, just_db=True) | |
417 | sa.commit() |
|
433 | sa.commit() | |
418 | removed = [] |
|
434 | removed = [] | |
@@ -426,6 +442,7 b' def repo2db_mapper(initial_repo_list, re' | |||||
426 |
|
442 | |||
427 | return added, removed |
|
443 | return added, removed | |
428 |
|
444 | |||
|
445 | ||||
429 | # set cache regions for beaker so celery can utilise it |
|
446 | # set cache regions for beaker so celery can utilise it | |
430 | def add_cache(settings): |
|
447 | def add_cache(settings): | |
431 | cache_settings = {'regions': None} |
|
448 | cache_settings = {'regions': None} |
@@ -74,12 +74,13 b' class BaseModel(object):' | |||||
74 | else: |
|
74 | else: | |
75 | self.sa = meta.Session |
|
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 | :param cls: class to fetch |
|
81 | :param cls: class to fetch | |
82 | :param instance: int or Instance |
|
82 | :param instance: int or Instance | |
|
83 | :param callback: callback to call if all lookups failed | |||
83 | """ |
|
84 | """ | |
84 |
|
85 | |||
85 | if isinstance(instance, cls): |
|
86 | if isinstance(instance, cls): | |
@@ -88,5 +89,10 b' class BaseModel(object):' | |||||
88 | return cls.get(instance) |
|
89 | return cls.get(instance) | |
89 | else: |
|
90 | else: | |
90 | if instance: |
|
91 | if instance: | |
91 | raise Exception('given object must be int or Instance' |
|
92 | if callback is None: | |
92 | ' of %s got %s' % (type(cls), type(instance))) |
|
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 | group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) |
|
717 | group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) | |
718 | group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) |
|
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 | parent_group = relationship('RepoGroup', remote_side=group_id) |
|
723 | parent_group = relationship('RepoGroup', remote_side=group_id) | |
721 |
|
724 | |||
722 | def __init__(self, group_name='', parent_group=None): |
|
725 | def __init__(self, group_name='', parent_group=None): | |
@@ -833,8 +836,9 b' class Permission(Base, BaseModel):' | |||||
833 | permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) |
|
836 | permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) | |
834 |
|
837 | |||
835 | def __repr__(self): |
|
838 | def __repr__(self): | |
836 |
return "<%s('%s:%s')>" % ( |
|
839 | return "<%s('%s:%s')>" % ( | |
837 |
|
|
840 | self.__class__.__name__, self.permission_id, self.permission_name | |
|
841 | ) | |||
838 |
|
842 | |||
839 | @classmethod |
|
843 | @classmethod | |
840 | def get_by_key(cls, key): |
|
844 | def get_by_key(cls, key): | |
@@ -843,9 +847,18 b' class Permission(Base, BaseModel):' | |||||
843 | @classmethod |
|
847 | @classmethod | |
844 | def get_default_perms(cls, default_user_id): |
|
848 | def get_default_perms(cls, default_user_id): | |
845 | q = Session.query(UserRepoToPerm, Repository, cls)\ |
|
849 | q = Session.query(UserRepoToPerm, Repository, cls)\ | |
846 |
|
|
850 | .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ | |
847 |
|
|
851 | .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ | |
848 |
|
|
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 | return q.all() |
|
863 | return q.all() | |
851 |
|
864 |
@@ -388,57 +388,66 b' def ValidForkType(old_data):' | |||||
388 | return _ValidForkType |
|
388 | return _ValidForkType | |
389 |
|
389 | |||
390 |
|
390 | |||
391 | class ValidPerms(formencode.validators.FancyValidator): |
|
391 | def ValidPerms(type_='repo'): | |
392 | messages = {'perm_new_member_name': _('This username or users group name' |
|
392 | if type_ == 'group': | |
393 | ' is not valid')} |
|
393 | EMPTY_PERM = 'group.none' | |
|
394 | elif type_ == 'repo': | |||
|
395 | EMPTY_PERM = 'repository.none' | |||
394 |
|
396 | |||
395 | def to_python(self, value, state): |
|
397 | class _ValidPerms(formencode.validators.FancyValidator): | |
396 |
|
|
398 | messages = { | |
397 | perms_new = [] |
|
399 | 'perm_new_member_name': | |
398 | #build a list of permission to update and new permission to create |
|
400 | _('This username or users group name is not valid') | |
399 | for k, v in value.items(): |
|
401 | } | |
400 | #means new added member to permissions |
|
402 | ||
401 | if k.startswith('perm_new_member'): |
|
403 | def to_python(self, value, state): | |
402 | new_perm = value.get('perm_new_member', False) |
|
404 | perms_update = [] | |
403 | new_member = value.get('perm_new_member_name', False) |
|
405 | perms_new = [] | |
404 | new_type = value.get('perm_new_member_type') |
|
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: |
|
414 | if new_member and new_perm: | |
407 | if (new_member, new_perm, new_type) not in perms_new: |
|
415 | if (new_member, new_perm, new_type) not in perms_new: | |
408 | perms_new.append((new_member, new_perm, new_type)) |
|
416 | perms_new.append((new_member, new_perm, new_type)) | |
409 | elif k.startswith('u_perm_') or k.startswith('g_perm_'): |
|
417 | elif k.startswith('u_perm_') or k.startswith('g_perm_'): | |
410 | member = k[7:] |
|
418 | member = k[7:] | |
411 | t = {'u': 'user', |
|
419 | t = {'u': 'user', | |
412 | 'g': 'users_group' |
|
420 | 'g': 'users_group' | |
413 | }[k[0]] |
|
421 | }[k[0]] | |
414 | if member == 'default': |
|
422 | if member == 'default': | |
415 |
if value |
|
423 | if value.get('private'): | |
416 | #set none for default when updating to private repo |
|
424 | # set none for default when updating to private repo | |
417 |
v = |
|
425 | v = EMPTY_PERM | |
418 | perms_update.append((member, v, t)) |
|
426 | perms_update.append((member, v, t)) | |
419 |
|
427 | |||
420 | value['perms_updates'] = perms_update |
|
428 | value['perms_updates'] = perms_update | |
421 | value['perms_new'] = perms_new |
|
429 | value['perms_new'] = perms_new | |
422 |
|
430 | |||
423 | #update permissions |
|
431 | # update permissions | |
424 | for k, v, t in perms_new: |
|
432 | for k, v, t in perms_new: | |
425 | try: |
|
433 | try: | |
426 | if t is 'user': |
|
434 | if t is 'user': | |
427 | self.user_db = User.query()\ |
|
435 | self.user_db = User.query()\ | |
428 | .filter(User.active == True)\ |
|
436 | .filter(User.active == True)\ | |
429 | .filter(User.username == k).one() |
|
437 | .filter(User.username == k).one() | |
430 | if t is 'users_group': |
|
438 | if t is 'users_group': | |
431 | self.user_db = UsersGroup.query()\ |
|
439 | self.user_db = UsersGroup.query()\ | |
432 | .filter(UsersGroup.users_group_active == True)\ |
|
440 | .filter(UsersGroup.users_group_active == True)\ | |
433 | .filter(UsersGroup.users_group_name == k).one() |
|
441 | .filter(UsersGroup.users_group_name == k).one() | |
434 |
|
442 | |||
435 | except Exception: |
|
443 | except Exception: | |
436 | msg = self.message('perm_new_member_name', |
|
444 | msg = self.message('perm_new_member_name', | |
437 | state=State_obj) |
|
445 | state=State_obj) | |
438 | raise formencode.Invalid( |
|
446 | raise formencode.Invalid( | |
439 | msg, value, state, error_dict={'perm_new_member_name': msg} |
|
447 | msg, value, state, error_dict={'perm_new_member_name': msg} | |
440 | ) |
|
448 | ) | |
441 | return value |
|
449 | return value | |
|
450 | return _ValidPerms | |||
442 |
|
451 | |||
443 |
|
452 | |||
444 | class ValidSettings(formencode.validators.FancyValidator): |
|
453 | class ValidSettings(formencode.validators.FancyValidator): | |
@@ -588,7 +597,7 b' def UsersGroupForm(edit=False, old_data=' | |||||
588 | def ReposGroupForm(edit=False, old_data={}, available_groups=[]): |
|
597 | def ReposGroupForm(edit=False, old_data={}, available_groups=[]): | |
589 | class _ReposGroupForm(formencode.Schema): |
|
598 | class _ReposGroupForm(formencode.Schema): | |
590 | allow_extra_fields = True |
|
599 | allow_extra_fields = True | |
591 |
filter_extra_fields = |
|
600 | filter_extra_fields = False | |
592 |
|
601 | |||
593 | group_name = All(UnicodeString(strip=True, min=1, not_empty=True), |
|
602 | group_name = All(UnicodeString(strip=True, min=1, not_empty=True), | |
594 | SlugifyName()) |
|
603 | SlugifyName()) | |
@@ -598,7 +607,7 b' def ReposGroupForm(edit=False, old_data=' | |||||
598 | testValueList=True, |
|
607 | testValueList=True, | |
599 | if_missing=None, not_empty=False) |
|
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 | return _ReposGroupForm |
|
612 | return _ReposGroupForm | |
604 |
|
613 | |||
@@ -649,7 +658,7 b' def RepoForm(edit=False, old_data={}, su' | |||||
649 | #this is repo owner |
|
658 | #this is repo owner | |
650 | user = All(UnicodeString(not_empty=True), ValidRepoUser) |
|
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 | return _RepoForm |
|
662 | return _RepoForm | |
654 |
|
663 | |||
655 |
|
664 | |||
@@ -683,7 +692,7 b' def RepoSettingsForm(edit=False, old_dat' | |||||
683 | repo_group = OneOf(repo_groups, hideList=True) |
|
692 | repo_group = OneOf(repo_groups, hideList=True) | |
684 | private = StringBoolean(if_missing=False) |
|
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 | ValidSettings] |
|
696 | ValidSettings] | |
688 | return _RepoForm |
|
697 | return _RepoForm | |
689 |
|
698 |
@@ -42,10 +42,7 b' log = logging.getLogger(__name__)' | |||||
42 | class NotificationModel(BaseModel): |
|
42 | class NotificationModel(BaseModel): | |
43 |
|
43 | |||
44 | def __get_user(self, user): |
|
44 | def __get_user(self, user): | |
45 | if isinstance(user, basestring): |
|
45 | return self._get_instance(User, user, callback=User.get_by_username) | |
46 | return User.get_by_username(username=user) |
|
|||
47 | else: |
|
|||
48 | return self._get_instance(User, user) |
|
|||
49 |
|
46 | |||
50 | def __get_notification(self, notification): |
|
47 | def __get_notification(self, notification): | |
51 | if isinstance(notification, Notification): |
|
48 | if isinstance(notification, Notification): |
@@ -28,9 +28,9 b' import logging' | |||||
28 | import traceback |
|
28 | import traceback | |
29 | from datetime import datetime |
|
29 | from datetime import datetime | |
30 |
|
30 | |||
31 | from vcs.utils.lazy import LazyProperty |
|
|||
32 | from vcs.backends import get_backend |
|
31 | from vcs.backends import get_backend | |
33 |
|
32 | |||
|
33 | from rhodecode.lib import LazyProperty | |||
34 | from rhodecode.lib import safe_str, safe_unicode |
|
34 | from rhodecode.lib import safe_str, safe_unicode | |
35 | from rhodecode.lib.caching_query import FromCache |
|
35 | from rhodecode.lib.caching_query import FromCache | |
36 | from rhodecode.lib.hooks import log_create_repository |
|
36 | from rhodecode.lib.hooks import log_create_repository | |
@@ -39,11 +39,31 b' from rhodecode.model import BaseModel' | |||||
39 | from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \ |
|
39 | from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \ | |
40 | Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup |
|
40 | Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup | |
41 |
|
41 | |||
|
42 | ||||
42 | log = logging.getLogger(__name__) |
|
43 | log = logging.getLogger(__name__) | |
43 |
|
44 | |||
44 |
|
45 | |||
45 | class RepoModel(BaseModel): |
|
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 | @LazyProperty |
|
67 | @LazyProperty | |
48 | def repos_path(self): |
|
68 | def repos_path(self): | |
49 | """ |
|
69 | """ | |
@@ -138,49 +158,24 b' class RepoModel(BaseModel):' | |||||
138 | # update permissions |
|
158 | # update permissions | |
139 | for member, perm, member_type in form_data['perms_updates']: |
|
159 | for member, perm, member_type in form_data['perms_updates']: | |
140 | if member_type == 'user': |
|
160 | if member_type == 'user': | |
141 | _member = User.get_by_username(member) |
|
161 | # this updates existing one | |
142 | r2p = self.sa.query(UserRepoToPerm)\ |
|
162 | RepoModel().grant_user_permission( | |
143 |
|
|
163 | repo=cur_repo, user=member, perm=perm | |
144 | .filter(UserRepoToPerm.repository == cur_repo)\ |
|
164 | ) | |
145 | .one() |
|
|||
146 |
|
||||
147 | r2p.permission = self.sa.query(Permission)\ |
|
|||
148 | .filter(Permission.permission_name == |
|
|||
149 | perm).scalar() |
|
|||
150 | self.sa.add(r2p) |
|
|||
151 | else: |
|
165 | else: | |
152 |
|
|
166 | RepoModel().grant_users_group_permission( | |
153 | .filter(UsersGroupRepoToPerm.users_group == |
|
167 | repo=cur_repo, group_name=member, perm=perm | |
154 | UsersGroup.get_by_group_name(member))\ |
|
168 | ) | |
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 |
|
||||
163 | # set new permissions |
|
169 | # set new permissions | |
164 | for member, perm, member_type in form_data['perms_new']: |
|
170 | for member, perm, member_type in form_data['perms_new']: | |
165 | if member_type == 'user': |
|
171 | if member_type == 'user': | |
166 |
|
|
172 | RepoModel().grant_user_permission( | |
167 |
|
|
173 | repo=cur_repo, user=member, perm=perm | |
168 | r2p.user = User.get_by_username(member) |
|
174 | ) | |
169 |
|
||||
170 | r2p.permission = self.sa.query(Permission)\ |
|
|||
171 | .filter(Permission. |
|
|||
172 | permission_name == perm)\ |
|
|||
173 | .scalar() |
|
|||
174 | self.sa.add(r2p) |
|
|||
175 | else: |
|
175 | else: | |
176 |
|
|
176 | RepoModel().grant_users_group_permission( | |
177 | g2p.repository = cur_repo |
|
177 | repo=cur_repo, group_name=member, perm=perm | |
178 | g2p.users_group = UsersGroup.get_by_group_name(member) |
|
178 | ) | |
179 | g2p.permission = self.sa.query(Permission)\ |
|
|||
180 | .filter(Permission. |
|
|||
181 | permission_name == perm)\ |
|
|||
182 | .scalar() |
|
|||
183 | self.sa.add(g2p) |
|
|||
184 |
|
179 | |||
185 | # update current repo |
|
180 | # update current repo | |
186 | for k, v in form_data.items(): |
|
181 | for k, v in form_data.items(): | |
@@ -314,28 +309,93 b' class RepoModel(BaseModel):' | |||||
314 | log.error(traceback.format_exc()) |
|
309 | log.error(traceback.format_exc()) | |
315 | raise |
|
310 | raise | |
316 |
|
311 | |||
317 | def delete_perm_user(self, form_data, repo_name): |
|
312 | def grant_user_permission(self, repo, user, perm): | |
318 |
|
|
313 | """ | |
319 | obj = self.sa.query(UserRepoToPerm)\ |
|
314 | Grant permission for user on given repository, or update existing one | |
320 | .filter(UserRepoToPerm.repository \ |
|
315 | if found | |
321 | == self.get_by_repo_name(repo_name))\ |
|
316 | ||
322 | .filter(UserRepoToPerm.user_id == form_data['user_id']).one() |
|
317 | :param repo: Instance of Repository, repository_id, or repository name | |
323 | self.sa.delete(obj) |
|
318 | :param user: Instance of User, user_id or username | |
324 | except: |
|
319 | :param perm: Instance of Permission, or permission_name | |
325 | log.error(traceback.format_exc()) |
|
320 | """ | |
326 | raise |
|
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 |
|
354 | def grant_users_group_permission(self, repo, group_name, perm): | |
329 |
|
|
355 | """ | |
330 | obj = self.sa.query(UsersGroupRepoToPerm)\ |
|
356 | Grant permission for users group on given repository, or update | |
331 | .filter(UsersGroupRepoToPerm.repository \ |
|
357 | existing one if found | |
332 | == self.get_by_repo_name(repo_name))\ |
|
358 | ||
333 | .filter(UsersGroupRepoToPerm.users_group_id |
|
359 | :param repo: Instance of Repository, repository_id, or repository name | |
334 | == form_data['users_group_id']).one() |
|
360 | :param group_name: Instance of UserGroup, users_group_id, | |
335 | self.sa.delete(obj) |
|
361 | or users group name | |
336 | except: |
|
362 | :param perm: Instance of Permission, or permission_name | |
337 | log.error(traceback.format_exc()) |
|
363 | """ | |
338 | raise |
|
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 | def delete_stats(self, repo_name): |
|
400 | def delete_stats(self, repo_name): | |
341 | """ |
|
401 | """ | |
@@ -345,8 +405,9 b' class RepoModel(BaseModel):' | |||||
345 | """ |
|
405 | """ | |
346 | try: |
|
406 | try: | |
347 | obj = self.sa.query(Statistics)\ |
|
407 | obj = self.sa.query(Statistics)\ | |
348 |
.filter(Statistics.repository == |
|
408 | .filter(Statistics.repository == | |
349 |
self.get_by_repo_name(repo_name)) |
|
409 | self.get_by_repo_name(repo_name))\ | |
|
410 | .one() | |||
350 | self.sa.delete(obj) |
|
411 | self.sa.delete(obj) | |
351 | except: |
|
412 | except: | |
352 | log.error(traceback.format_exc()) |
|
413 | log.error(traceback.format_exc()) | |
@@ -373,10 +434,9 b' class RepoModel(BaseModel):' | |||||
373 | new_parent_path = '' |
|
434 | new_parent_path = '' | |
374 |
|
435 | |||
375 | # we need to make it str for mercurial |
|
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 | [self.repos_path, new_parent_path, repo_name])) |
|
438 | [self.repos_path, new_parent_path, repo_name])) | |
378 |
|
439 | |||
379 |
|
||||
380 | # check if this path is not a repository |
|
440 | # check if this path is not a repository | |
381 | if is_valid_repo(repo_path, self.repos_path): |
|
441 | if is_valid_repo(repo_path, self.repos_path): | |
382 | raise Exception('This path %s is a valid repository' % repo_path) |
|
442 | raise Exception('This path %s is a valid repository' % repo_path) | |
@@ -393,7 +453,6 b' class RepoModel(BaseModel):' | |||||
393 |
|
453 | |||
394 | backend(repo_path, create=True, src_url=clone_uri) |
|
454 | backend(repo_path, create=True, src_url=clone_uri) | |
395 |
|
455 | |||
396 |
|
||||
397 | def __rename_repo(self, old, new): |
|
456 | def __rename_repo(self, old, new): | |
398 | """ |
|
457 | """ | |
399 | renames repository on filesystem |
|
458 | renames repository on filesystem | |
@@ -406,8 +465,9 b' class RepoModel(BaseModel):' | |||||
406 | old_path = os.path.join(self.repos_path, old) |
|
465 | old_path = os.path.join(self.repos_path, old) | |
407 | new_path = os.path.join(self.repos_path, new) |
|
466 | new_path = os.path.join(self.repos_path, new) | |
408 | if os.path.isdir(new_path): |
|
467 | if os.path.isdir(new_path): | |
409 | raise Exception('Was trying to rename to already existing dir %s' \ |
|
468 | raise Exception( | |
410 | % new_path) |
|
469 | 'Was trying to rename to already existing dir %s' % new_path | |
|
470 | ) | |||
411 | shutil.move(old_path, new_path) |
|
471 | shutil.move(old_path, new_path) | |
412 |
|
472 | |||
413 | def __delete_repo(self, repo): |
|
473 | def __delete_repo(self, repo): | |
@@ -426,7 +486,6 b' class RepoModel(BaseModel):' | |||||
426 | shutil.move(os.path.join(rm_path, '.%s' % alias), |
|
486 | shutil.move(os.path.join(rm_path, '.%s' % alias), | |
427 | os.path.join(rm_path, 'rm__.%s' % alias)) |
|
487 | os.path.join(rm_path, 'rm__.%s' % alias)) | |
428 | # disable repo |
|
488 | # disable repo | |
429 | shutil.move(rm_path, os.path.join(self.repos_path, 'rm__%s__%s' \ |
|
489 | _d = 'rm__%s__%s' % (datetime.now().strftime('%Y%m%d_%H%M%S_%f'), | |
430 |
|
|
490 | repo.repo_name) | |
431 | .strftime('%Y%m%d_%H%M%S_%f'), |
|
491 | shutil.move(rm_path, os.path.join(self.repos_path, _d)) | |
432 | repo.repo_name))) |
|
@@ -26,14 +26,29 b'' | |||||
26 |
|
26 | |||
27 | import logging |
|
27 | import logging | |
28 | from rhodecode.model import BaseModel |
|
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 | log = logging.getLogger(__name__) |
|
32 | log = logging.getLogger(__name__) | |
32 |
|
33 | |||
33 |
|
34 | |||
34 | class RepositoryPermissionModel(BaseModel): |
|
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 | def get_user_permission(self, repository, user): |
|
48 | def get_user_permission(self, repository, user): | |
|
49 | repository = self.__get_repo(repository) | |||
|
50 | user = self.__get_user(user) | |||
|
51 | ||||
37 | return UserRepoToPerm.query() \ |
|
52 | return UserRepoToPerm.query() \ | |
38 | .filter(UserRepoToPerm.user == user) \ |
|
53 | .filter(UserRepoToPerm.user == user) \ | |
39 | .filter(UserRepoToPerm.repository == repository) \ |
|
54 | .filter(UserRepoToPerm.repository == repository) \ |
@@ -28,18 +28,32 b' import logging' | |||||
28 | import traceback |
|
28 | import traceback | |
29 | import shutil |
|
29 | import shutil | |
30 |
|
30 | |||
31 | from pylons.i18n.translation import _ |
|
31 | from rhodecode.lib import LazyProperty | |
32 |
|
||||
33 | from vcs.utils.lazy import LazyProperty |
|
|||
34 |
|
32 | |||
35 | from rhodecode.model import BaseModel |
|
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 | log = logging.getLogger(__name__) |
|
37 | log = logging.getLogger(__name__) | |
39 |
|
38 | |||
40 |
|
39 | |||
41 | class ReposGroupModel(BaseModel): |
|
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 | @LazyProperty |
|
57 | @LazyProperty | |
44 | def repos_path(self): |
|
58 | def repos_path(self): | |
45 | """ |
|
59 | """ | |
@@ -49,6 +63,24 b' class ReposGroupModel(BaseModel):' | |||||
49 | q = RhodeCodeUi.get_by_key('/').one() |
|
63 | q = RhodeCodeUi.get_by_key('/').one() | |
50 | return q.ui_value |
|
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 | def __create_group(self, group_name): |
|
84 | def __create_group(self, group_name): | |
53 | """ |
|
85 | """ | |
54 | makes repositories group on filesystem |
|
86 | makes repositories group on filesystem | |
@@ -102,16 +134,21 b' class ReposGroupModel(BaseModel):' | |||||
102 | # delete only if that path really exists |
|
134 | # delete only if that path really exists | |
103 | os.rmdir(rm_path) |
|
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 | try: |
|
138 | try: | |
107 | new_repos_group = RepoGroup() |
|
139 | new_repos_group = RepoGroup() | |
108 |
new_repos_group.group_description = |
|
140 | new_repos_group.group_description = group_description | |
109 |
new_repos_group.parent_group = |
|
141 | new_repos_group.parent_group = self.__get_repos_group(parent) | |
110 |
new_repos_group.group_name = new_repos_group.get_new_name( |
|
142 | new_repos_group.group_name = new_repos_group.get_new_name(group_name) | |
111 |
|
143 | |||
112 | self.sa.add(new_repos_group) |
|
144 | self.sa.add(new_repos_group) | |
113 | self.sa.flush() |
|
145 | self._create_default_perms(new_repos_group) | |
114 | self.__create_group(new_repos_group.group_name) |
|
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 | return new_repos_group |
|
153 | return new_repos_group | |
117 | except: |
|
154 | except: | |
@@ -122,6 +159,29 b' class ReposGroupModel(BaseModel):' | |||||
122 |
|
159 | |||
123 | try: |
|
160 | try: | |
124 | repos_group = RepoGroup.get(repos_group_id) |
|
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 | old_path = repos_group.full_path |
|
185 | old_path = repos_group.full_path | |
126 |
|
186 | |||
127 | # change properties |
|
187 | # change properties | |
@@ -154,3 +214,97 b' class ReposGroupModel(BaseModel):' | |||||
154 | except: |
|
214 | except: | |
155 | log.error(traceback.format_exc()) |
|
215 | log.error(traceback.format_exc()) | |
156 | raise |
|
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 | from rhodecode import BACKENDS |
|
36 | from rhodecode import BACKENDS | |
37 | from rhodecode.lib import helpers as h |
|
37 | from rhodecode.lib import helpers as h | |
38 | from rhodecode.lib import safe_str |
|
38 | from rhodecode.lib import safe_str | |
39 | from rhodecode.lib.auth import HasRepoPermissionAny |
|
39 | from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny | |
40 | from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \ |
|
40 | from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \ | |
41 | action_logger, EmptyChangeset |
|
41 | action_logger, EmptyChangeset | |
42 | from rhodecode.model import BaseModel |
|
42 | from rhodecode.model import BaseModel | |
43 | from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \ |
|
43 | from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \ | |
44 | UserFollowing, UserLog, User |
|
44 | UserFollowing, UserLog, User, RepoGroup | |
45 |
|
45 | |||
46 | log = logging.getLogger(__name__) |
|
46 | log = logging.getLogger(__name__) | |
47 |
|
47 | |||
@@ -80,15 +80,16 b' class CachedRepoList(object):' | |||||
80 | for dbr in self.db_repo_list: |
|
80 | for dbr in self.db_repo_list: | |
81 | scmr = dbr.scm_instance_cached |
|
81 | scmr = dbr.scm_instance_cached | |
82 | # check permission at this level |
|
82 | # check permission at this level | |
83 |
if not HasRepoPermissionAny( |
|
83 | if not HasRepoPermissionAny( | |
84 | 'repository.admin')(dbr.repo_name, |
|
84 | 'repository.read', 'repository.write', 'repository.admin' | |
85 | 'get repo check'): |
|
85 | )(dbr.repo_name, 'get repo check'): | |
86 | continue |
|
86 | continue | |
87 |
|
87 | |||
88 | if scmr is None: |
|
88 | if scmr is None: | |
89 | log.error('%s this repository is present in database but it ' |
|
89 | log.error( | |
90 | 'cannot be created as an scm instance', |
|
90 | '%s this repository is present in database but it ' | |
91 |
dbr.repo_name |
|
91 | 'cannot be created as an scm instance' % dbr.repo_name | |
|
92 | ) | |||
92 | continue |
|
93 | continue | |
93 |
|
94 | |||
94 | last_change = scmr.last_change |
|
95 | last_change = scmr.last_change | |
@@ -115,6 +116,28 b' class CachedRepoList(object):' | |||||
115 | yield tmp_d |
|
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 | class ScmModel(BaseModel): |
|
141 | class ScmModel(BaseModel): | |
119 | """ |
|
142 | """ | |
120 | Generic Scm Model |
|
143 | Generic Scm Model | |
@@ -200,6 +223,14 b' class ScmModel(BaseModel):' | |||||
200 |
|
223 | |||
201 | return repo_iter |
|
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 | def mark_for_invalidation(self, repo_name): |
|
234 | def mark_for_invalidation(self, repo_name): | |
204 | """Puts cache invalidation task into db for |
|
235 | """Puts cache invalidation task into db for | |
205 | further global cache invalidation |
|
236 | further global cache invalidation |
@@ -35,7 +35,7 b' from rhodecode.lib.caching_query import ' | |||||
35 | from rhodecode.model import BaseModel |
|
35 | from rhodecode.model import BaseModel | |
36 | from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \ |
|
36 | from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \ | |
37 | UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember, \ |
|
37 | UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember, \ | |
38 | Notification |
|
38 | Notification, RepoGroup, UserRepoGroupToPerm, UsersGroup | |
39 | from rhodecode.lib.exceptions import DefaultUserException, \ |
|
39 | from rhodecode.lib.exceptions import DefaultUserException, \ | |
40 | UserOwnsReposException |
|
40 | UserOwnsReposException | |
41 |
|
41 | |||
@@ -46,16 +46,26 b' from sqlalchemy.orm import joinedload' | |||||
46 | log = logging.getLogger(__name__) |
|
46 | log = logging.getLogger(__name__) | |
47 |
|
47 | |||
48 |
|
48 | |||
49 |
PERM_WEIGHTS = { |
|
49 | PERM_WEIGHTS = { | |
50 |
|
|
50 | 'repository.none': 0, | |
51 |
|
|
51 | 'repository.read': 1, | |
52 |
|
|
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 | class UserModel(BaseModel): |
|
61 | class UserModel(BaseModel): | |
56 |
|
62 | |||
57 | def __get_user(self, user): |
|
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 | def get(self, user_id, cache=False): |
|
70 | def get(self, user_id, cache=False): | |
61 | user = self.sa.query(User) |
|
71 | user = self.sa.query(User) | |
@@ -348,9 +358,12 b' class UserModel(BaseModel):' | |||||
348 |
|
358 | |||
349 | :param user: user instance to fill his perms |
|
359 | :param user: user instance to fill his perms | |
350 | """ |
|
360 | """ | |
351 |
|
361 | RK = 'repositories' | ||
352 | user.permissions['repositories'] = {} |
|
362 | GK = 'repositories_groups' | |
353 | user.permissions['global'] = set() |
|
363 | GLOBAL = 'global' | |
|
364 | user.permissions[RK] = {} | |||
|
365 | user.permissions[GK] = {} | |||
|
366 | user.permissions[GLOBAL] = set() | |||
354 |
|
367 | |||
355 | #====================================================================== |
|
368 | #====================================================================== | |
356 | # fetch default permissions |
|
369 | # fetch default permissions | |
@@ -358,36 +371,45 b' class UserModel(BaseModel):' | |||||
358 | default_user = User.get_by_username('default', cache=True) |
|
371 | default_user = User.get_by_username('default', cache=True) | |
359 | default_user_id = default_user.user_id |
|
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 | if user.is_admin: |
|
377 | if user.is_admin: | |
364 | #================================================================== |
|
378 | #================================================================== | |
365 |
# |
|
379 | # admin user have all default rights for repositories | |
|
380 | # and groups set to admin | |||
366 | #================================================================== |
|
381 | #================================================================== | |
367 |
user.permissions[ |
|
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 | p = 'repository.admin' |
|
387 | p = 'repository.admin' | |
371 |
user.permissions[ |
|
388 | user.permissions[RK][r_k] = p | |
372 | repository.repo_name] = 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 | else: |
|
396 | else: | |
375 | #================================================================== |
|
397 | #================================================================== | |
376 | # set default permissions |
|
398 | # set default permissions first for repositories and groups | |
377 | #================================================================== |
|
399 | #================================================================== | |
378 | uid = user.user_id |
|
400 | uid = user.user_id | |
379 |
|
401 | |||
380 | # default global |
|
402 | # default global permissions | |
381 | default_global_perms = self.sa.query(UserToPerm)\ |
|
403 | default_global_perms = self.sa.query(UserToPerm)\ | |
382 | .filter(UserToPerm.user_id == default_user_id) |
|
404 | .filter(UserToPerm.user_id == default_user_id) | |
383 |
|
405 | |||
384 | for perm in default_global_perms: |
|
406 | for perm in default_global_perms: | |
385 |
user.permissions[ |
|
407 | user.permissions[GLOBAL].add(perm.permission.permission_name) | |
386 |
|
408 | |||
387 | # default for repositories |
|
409 | # default for repositories | |
388 | for perm in default_perms: |
|
410 | for perm in default_repo_perms: | |
389 | if perm.Repository.private and not (perm.Repository.user_id == |
|
411 | r_k = perm.UserRepoToPerm.repository.repo_name | |
390 | uid): |
|
412 | if perm.Repository.private and not (perm.Repository.user_id == uid): | |
391 | # disable defaults for private repos, |
|
413 | # disable defaults for private repos, | |
392 | p = 'repository.none' |
|
414 | p = 'repository.none' | |
393 | elif perm.Repository.user_id == uid: |
|
415 | elif perm.Repository.user_id == uid: | |
@@ -396,8 +418,13 b' class UserModel(BaseModel):' | |||||
396 | else: |
|
418 | else: | |
397 | p = perm.Permission.permission_name |
|
419 | p = perm.Permission.permission_name | |
398 |
|
420 | |||
399 |
user.permissions[ |
|
421 | user.permissions[RK][r_k] = p | |
400 | repository.repo_name] = 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 | # overwrite default with user permissions if any |
|
430 | # overwrite default with user permissions if any | |
@@ -409,25 +436,24 b' class UserModel(BaseModel):' | |||||
409 | .filter(UserToPerm.user_id == uid).all() |
|
436 | .filter(UserToPerm.user_id == uid).all() | |
410 |
|
437 | |||
411 | for perm in user_perms: |
|
438 | for perm in user_perms: | |
412 |
user.permissions[ |
|
439 | user.permissions[GLOBAL].add(perm.permission.permission_name) | |
413 |
|
440 | |||
414 | # user repositories |
|
441 | # user repositories | |
415 | user_repo_perms = self.sa.query(UserRepoToPerm, Permission, |
|
442 | user_repo_perms = \ | |
416 | Repository)\ |
|
443 | self.sa.query(UserRepoToPerm, Permission, Repository)\ | |
417 |
|
|
444 | .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ | |
418 | Repository.repo_id))\ |
|
445 | .join((Permission, UserRepoToPerm.permission_id == Permission.permission_id))\ | |
419 |
|
|
446 | .filter(UserRepoToPerm.user_id == uid)\ | |
420 | Permission.permission_id))\ |
|
447 | .all() | |
421 | .filter(UserRepoToPerm.user_id == uid).all() |
|
|||
422 |
|
448 | |||
423 | for perm in user_repo_perms: |
|
449 | for perm in user_repo_perms: | |
424 | # set admin if owner |
|
450 | # set admin if owner | |
|
451 | r_k = perm.UserRepoToPerm.repository.repo_name | |||
425 | if perm.Repository.user_id == uid: |
|
452 | if perm.Repository.user_id == uid: | |
426 | p = 'repository.admin' |
|
453 | p = 'repository.admin' | |
427 | else: |
|
454 | else: | |
428 | p = perm.Permission.permission_name |
|
455 | p = perm.Permission.permission_name | |
429 |
user.permissions[ |
|
456 | user.permissions[RK][r_k] = p | |
430 | repository.repo_name] = p |
|
|||
431 |
|
457 | |||
432 | #================================================================== |
|
458 | #================================================================== | |
433 | # check if user is part of groups for this repository and fill in |
|
459 | # check if user is part of groups for this repository and fill in | |
@@ -442,30 +468,44 b' class UserModel(BaseModel):' | |||||
442 | .filter(UsersGroupMember.user_id == uid).all() |
|
468 | .filter(UsersGroupMember.user_id == uid).all() | |
443 |
|
469 | |||
444 | for perm in user_perms_from_users_groups: |
|
470 | for perm in user_perms_from_users_groups: | |
445 |
user.permissions[ |
|
471 | user.permissions[GLOBAL].add(perm.permission.permission_name) | |
446 |
|
472 | |||
447 | # users group repositories |
|
473 | # users group repositories | |
448 |
user_repo_perms_from_users_groups = |
|
474 | user_repo_perms_from_users_groups = \ | |
449 | UsersGroupRepoToPerm, |
|
475 | self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\ | |
450 | Permission, Repository,)\ |
|
476 | .join((Repository, UsersGroupRepoToPerm.repository_id == Repository.repo_id))\ | |
451 |
|
|
477 | .join((Permission, UsersGroupRepoToPerm.permission_id == Permission.permission_id))\ | |
452 | Repository.repo_id))\ |
|
478 | .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == UsersGroupMember.users_group_id))\ | |
453 |
|
|
479 | .filter(UsersGroupMember.user_id == uid)\ | |
454 | Permission.permission_id))\ |
|
480 | .all() | |
455 | .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == |
|
|||
456 | UsersGroupMember.users_group_id))\ |
|
|||
457 | .filter(UsersGroupMember.user_id == uid).all() |
|
|||
458 |
|
481 | |||
459 | for perm in user_repo_perms_from_users_groups: |
|
482 | for perm in user_repo_perms_from_users_groups: | |
|
483 | r_k = perm.UsersGroupRepoToPerm.repository.repo_name | |||
460 | p = perm.Permission.permission_name |
|
484 | p = perm.Permission.permission_name | |
461 |
cur_perm = user.permissions[ |
|
485 | cur_perm = user.permissions[RK][r_k] | |
462 | UsersGroupRepoToPerm. |
|
|||
463 | repository.repo_name] |
|
|||
464 | # overwrite permission only if it's greater than permission |
|
486 | # overwrite permission only if it's greater than permission | |
465 | # given from other sources |
|
487 | # given from other sources | |
466 | if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]: |
|
488 | if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]: | |
467 |
user.permissions[ |
|
489 | user.permissions[RK][r_k] = p | |
468 | repository.repo_name] = 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 | return user |
|
510 | return user | |
471 |
|
511 | |||
@@ -480,23 +520,28 b' class UserModel(BaseModel):' | |||||
480 | .filter(UserToPerm.permission == perm).scalar() is not None |
|
520 | .filter(UserToPerm.permission == perm).scalar() is not None | |
481 |
|
521 | |||
482 | def grant_perm(self, user, perm): |
|
522 | def grant_perm(self, user, perm): | |
483 | if not isinstance(perm, Permission): |
|
523 | """ | |
484 | raise Exception('perm needs to be an instance of Permission class ' |
|
524 | Grant user global permissions | |
485 | 'got %s instead' % type(perm)) |
|
|||
486 |
|
|
525 | ||
|
526 | :param user: | |||
|
527 | :param perm: | |||
|
528 | """ | |||
487 | user = self.__get_user(user) |
|
529 | user = self.__get_user(user) | |
488 |
|
530 | perm = self.__get_perm(perm) | ||
489 | new = UserToPerm() |
|
531 | new = UserToPerm() | |
490 | new.user = user |
|
532 | new.user = user | |
491 | new.permission = perm |
|
533 | new.permission = perm | |
492 | self.sa.add(new) |
|
534 | self.sa.add(new) | |
493 |
|
535 | |||
494 | def revoke_perm(self, user, perm): |
|
536 | def revoke_perm(self, user, perm): | |
495 | if not isinstance(perm, Permission): |
|
537 | """ | |
496 | raise Exception('perm needs to be an instance of Permission class ' |
|
538 | Revoke users global permissions | |
497 | 'got %s instead' % type(perm)) |
|
|||
498 |
|
|
539 | ||
|
540 | :param user: | |||
|
541 | :param perm: | |||
|
542 | """ | |||
499 | user = self.__get_user(user) |
|
543 | user = self.__get_user(user) | |
|
544 | perm = self.__get_perm(perm) | |||
500 |
|
545 | |||
501 | obj = UserToPerm.query().filter(UserToPerm.user == user)\ |
|
546 | obj = UserToPerm.query().filter(UserToPerm.user == user)\ | |
502 | .filter(UserToPerm.permission == perm).scalar() |
|
547 | .filter(UserToPerm.permission == perm).scalar() |
@@ -38,7 +38,12 b' log = logging.getLogger(__name__)' | |||||
38 | class UsersGroupModel(BaseModel): |
|
38 | class UsersGroupModel(BaseModel): | |
39 |
|
39 | |||
40 | def __get_users_group(self, users_group): |
|
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 | def get(self, users_group_id, cache=False): |
|
48 | def get(self, users_group_id, cache=False): | |
44 | return UsersGroup.get(users_group_id) |
|
49 | return UsersGroup.get(users_group_id) | |
@@ -80,7 +85,15 b' class UsersGroupModel(BaseModel):' | |||||
80 | log.error(traceback.format_exc()) |
|
85 | log.error(traceback.format_exc()) | |
81 | raise |
|
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 | try: |
|
97 | try: | |
85 | users_group = self.__get_users_group(users_group) |
|
98 | users_group = self.__get_users_group(users_group) | |
86 |
|
99 | |||
@@ -88,7 +101,7 b' class UsersGroupModel(BaseModel):' | |||||
88 | assigned_groups = UsersGroupRepoToPerm.query()\ |
|
101 | assigned_groups = UsersGroupRepoToPerm.query()\ | |
89 | .filter(UsersGroupRepoToPerm.users_group == users_group).all() |
|
102 | .filter(UsersGroupRepoToPerm.users_group == users_group).all() | |
90 |
|
103 | |||
91 | if assigned_groups: |
|
104 | if assigned_groups and force is False: | |
92 | raise UsersGroupsAssignedException('RepoGroup assigned to %s' % |
|
105 | raise UsersGroupsAssignedException('RepoGroup assigned to %s' % | |
93 | assigned_groups) |
|
106 | assigned_groups) | |
94 |
|
107 | |||
@@ -118,10 +131,8 b' class UsersGroupModel(BaseModel):' | |||||
118 | raise |
|
131 | raise | |
119 |
|
132 | |||
120 | def has_perm(self, users_group, perm): |
|
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 | users_group = self.__get_users_group(users_group) |
|
134 | users_group = self.__get_users_group(users_group) | |
|
135 | perm = self.__get_perm(perm) | |||
125 |
|
136 | |||
126 | return UsersGroupToPerm.query()\ |
|
137 | return UsersGroupToPerm.query()\ | |
127 | .filter(UsersGroupToPerm.users_group == users_group)\ |
|
138 | .filter(UsersGroupToPerm.users_group == users_group)\ | |
@@ -139,10 +150,8 b' class UsersGroupModel(BaseModel):' | |||||
139 | self.sa.add(new) |
|
150 | self.sa.add(new) | |
140 |
|
151 | |||
141 | def revoke_perm(self, users_group, perm): |
|
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 | users_group = self.__get_users_group(users_group) |
|
153 | users_group = self.__get_users_group(users_group) | |
|
154 | perm = self.__get_perm(perm) | |||
146 |
|
155 | |||
147 | obj = UsersGroupToPerm.query()\ |
|
156 | obj = UsersGroupToPerm.query()\ | |
148 | .filter(UsersGroupToPerm.users_group == users_group)\ |
|
157 | .filter(UsersGroupToPerm.users_group == users_group)\ |
@@ -53,9 +53,18 b'' | |||||
53 | ${h.select('group_parent_id','',c.repo_groups,class_="medium")} |
|
53 | ${h.select('group_parent_id','',c.repo_groups,class_="medium")} | |
54 | </div> |
|
54 | </div> | |
55 | </div> |
|
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 | <div class="buttons"> |
|
65 | <div class="buttons"> | |
58 |
${h.submit('save',_(' |
|
66 | ${h.submit('save',_('Save'),class_="ui-button")} | |
|
67 | ${h.reset('reset',_('Reset'),class_="ui-button")} | |||
59 | </div> |
|
68 | </div> | |
60 | </div> |
|
69 | </div> | |
61 | </div> |
|
70 | </div> |
@@ -38,7 +38,9 b'' | |||||
38 | </div> |
|
38 | </div> | |
39 | </td> |
|
39 | </td> | |
40 | <td>${gr.group_description}</td> |
|
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 | </tr> |
|
44 | </tr> | |
43 | % endfor |
|
45 | % endfor | |
44 |
|
46 |
@@ -12,13 +12,27 b' from rhodecode.model.user import UserMod' | |||||
12 | from rhodecode.model.meta import Session |
|
12 | from rhodecode.model.meta import Session | |
13 | from rhodecode.model.notification import NotificationModel |
|
13 | from rhodecode.model.notification import NotificationModel | |
14 | from rhodecode.model.users_group import UsersGroupModel |
|
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 | class TestReposGroups(unittest.TestCase): |
|
30 | class TestReposGroups(unittest.TestCase): | |
17 |
|
31 | |||
18 | def setUp(self): |
|
32 | def setUp(self): | |
19 |
self.g1 = |
|
33 | self.g1 = _make_group('test1', skip_if_exists=True) | |
20 |
self.g2 = |
|
34 | self.g2 = _make_group('test2', skip_if_exists=True) | |
21 |
self.g3 = |
|
35 | self.g3 = _make_group('test3', skip_if_exists=True) | |
22 |
|
36 | |||
23 | def tearDown(self): |
|
37 | def tearDown(self): | |
24 | print 'out' |
|
38 | print 'out' | |
@@ -31,102 +45,81 b' class TestReposGroups(unittest.TestCase)' | |||||
31 | def _check_folders(self): |
|
45 | def _check_folders(self): | |
32 | print os.listdir(TESTS_TMP_PATH) |
|
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 | def __delete_group(self, id_): |
|
48 | def __delete_group(self, id_): | |
49 | ReposGroupModel().delete(id_) |
|
49 | ReposGroupModel().delete(id_) | |
50 |
|
50 | |||
51 |
|
||||
52 | def __update_group(self, id_, path, desc='desc', parent_id=None): |
|
51 | def __update_group(self, id_, path, desc='desc', parent_id=None): | |
53 | form_data = dict(group_name=path, |
|
52 | form_data = dict(group_name=path, | |
54 | group_description=desc, |
|
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 | gr = ReposGroupModel().update(id_, form_data) |
|
58 | gr = ReposGroupModel().update(id_, form_data) | |
58 | return gr |
|
59 | return gr | |
59 |
|
60 | |||
60 | def test_create_group(self): |
|
61 | def test_create_group(self): | |
61 |
g = |
|
62 | g = _make_group('newGroup') | |
62 | self.assertEqual(g.full_path, 'newGroup') |
|
63 | self.assertEqual(g.full_path, 'newGroup') | |
63 |
|
64 | |||
64 | self.assertTrue(self.__check_path('newGroup')) |
|
65 | self.assertTrue(self.__check_path('newGroup')) | |
65 |
|
66 | |||
66 |
|
||||
67 | def test_create_same_name_group(self): |
|
67 | def test_create_same_name_group(self): | |
68 |
self.assertRaises(IntegrityError, lambda: |
|
68 | self.assertRaises(IntegrityError, lambda:_make_group('newGroup')) | |
69 | Session.rollback() |
|
69 | Session.rollback() | |
70 |
|
70 | |||
71 | def test_same_subgroup(self): |
|
71 | def test_same_subgroup(self): | |
72 |
sg1 = |
|
72 | sg1 = _make_group('sub1', parent_id=self.g1.group_id) | |
73 | self.assertEqual(sg1.parent_group, self.g1) |
|
73 | self.assertEqual(sg1.parent_group, self.g1) | |
74 | self.assertEqual(sg1.full_path, 'test1/sub1') |
|
74 | self.assertEqual(sg1.full_path, 'test1/sub1') | |
75 | self.assertTrue(self.__check_path('test1', 'sub1')) |
|
75 | self.assertTrue(self.__check_path('test1', 'sub1')) | |
76 |
|
76 | |||
77 |
ssg1 = |
|
77 | ssg1 = _make_group('subsub1', parent_id=sg1.group_id) | |
78 | self.assertEqual(ssg1.parent_group, sg1) |
|
78 | self.assertEqual(ssg1.parent_group, sg1) | |
79 | self.assertEqual(ssg1.full_path, 'test1/sub1/subsub1') |
|
79 | self.assertEqual(ssg1.full_path, 'test1/sub1/subsub1') | |
80 | self.assertTrue(self.__check_path('test1', 'sub1', 'subsub1')) |
|
80 | self.assertTrue(self.__check_path('test1', 'sub1', 'subsub1')) | |
81 |
|
81 | |||
82 |
|
||||
83 | def test_remove_group(self): |
|
82 | def test_remove_group(self): | |
84 |
sg1 = |
|
83 | sg1 = _make_group('deleteme') | |
85 | self.__delete_group(sg1.group_id) |
|
84 | self.__delete_group(sg1.group_id) | |
86 |
|
85 | |||
87 | self.assertEqual(RepoGroup.get(sg1.group_id), None) |
|
86 | self.assertEqual(RepoGroup.get(sg1.group_id), None) | |
88 | self.assertFalse(self.__check_path('deteteme')) |
|
87 | self.assertFalse(self.__check_path('deteteme')) | |
89 |
|
88 | |||
90 |
sg1 = |
|
89 | sg1 = _make_group('deleteme', parent_id=self.g1.group_id) | |
91 | self.__delete_group(sg1.group_id) |
|
90 | self.__delete_group(sg1.group_id) | |
92 |
|
91 | |||
93 | self.assertEqual(RepoGroup.get(sg1.group_id), None) |
|
92 | self.assertEqual(RepoGroup.get(sg1.group_id), None) | |
94 | self.assertFalse(self.__check_path('test1', 'deteteme')) |
|
93 | self.assertFalse(self.__check_path('test1', 'deteteme')) | |
95 |
|
94 | |||
96 |
|
||||
97 | def test_rename_single_group(self): |
|
95 | def test_rename_single_group(self): | |
98 |
sg1 = |
|
96 | sg1 = _make_group('initial') | |
99 |
|
97 | |||
100 | new_sg1 = self.__update_group(sg1.group_id, 'after') |
|
98 | new_sg1 = self.__update_group(sg1.group_id, 'after') | |
101 | self.assertTrue(self.__check_path('after')) |
|
99 | self.assertTrue(self.__check_path('after')) | |
102 | self.assertEqual(RepoGroup.get_by_group_name('initial'), None) |
|
100 | self.assertEqual(RepoGroup.get_by_group_name('initial'), None) | |
103 |
|
101 | |||
104 |
|
||||
105 | def test_update_group_parent(self): |
|
102 | def test_update_group_parent(self): | |
106 |
|
103 | |||
107 |
sg1 = |
|
104 | sg1 = _make_group('initial', parent_id=self.g1.group_id) | |
108 |
|
105 | |||
109 | new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g1.group_id) |
|
106 | new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g1.group_id) | |
110 | self.assertTrue(self.__check_path('test1', 'after')) |
|
107 | self.assertTrue(self.__check_path('test1', 'after')) | |
111 | self.assertEqual(RepoGroup.get_by_group_name('test1/initial'), None) |
|
108 | self.assertEqual(RepoGroup.get_by_group_name('test1/initial'), None) | |
112 |
|
109 | |||
113 |
|
||||
114 | new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g3.group_id) |
|
110 | new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g3.group_id) | |
115 | self.assertTrue(self.__check_path('test3', 'after')) |
|
111 | self.assertTrue(self.__check_path('test3', 'after')) | |
116 | self.assertEqual(RepoGroup.get_by_group_name('test3/initial'), None) |
|
112 | self.assertEqual(RepoGroup.get_by_group_name('test3/initial'), None) | |
117 |
|
113 | |||
118 |
|
||||
119 | new_sg1 = self.__update_group(sg1.group_id, 'hello') |
|
114 | new_sg1 = self.__update_group(sg1.group_id, 'hello') | |
120 | self.assertTrue(self.__check_path('hello')) |
|
115 | self.assertTrue(self.__check_path('hello')) | |
121 |
|
116 | |||
122 | self.assertEqual(RepoGroup.get_by_group_name('hello'), new_sg1) |
|
117 | self.assertEqual(RepoGroup.get_by_group_name('hello'), new_sg1) | |
123 |
|
118 | |||
124 |
|
||||
125 |
|
||||
126 | def test_subgrouping_with_repo(self): |
|
119 | def test_subgrouping_with_repo(self): | |
127 |
|
120 | |||
128 |
g1 = |
|
121 | g1 = _make_group('g1') | |
129 |
g2 = |
|
122 | g2 = _make_group('g2') | |
130 |
|
123 | |||
131 | # create new repo |
|
124 | # create new repo | |
132 | form_data = dict(repo_name='john', |
|
125 | form_data = dict(repo_name='john', | |
@@ -150,13 +143,13 b' class TestReposGroups(unittest.TestCase)' | |||||
150 | RepoModel().update(r.repo_name, form_data) |
|
143 | RepoModel().update(r.repo_name, form_data) | |
151 | self.assertEqual(r.repo_name, 'g1/john') |
|
144 | self.assertEqual(r.repo_name, 'g1/john') | |
152 |
|
145 | |||
153 |
|
||||
154 | self.__update_group(g1.group_id, 'g1', parent_id=g2.group_id) |
|
146 | self.__update_group(g1.group_id, 'g1', parent_id=g2.group_id) | |
155 | self.assertTrue(self.__check_path('g2', 'g1')) |
|
147 | self.assertTrue(self.__check_path('g2', 'g1')) | |
156 |
|
148 | |||
157 | # test repo |
|
149 | # test repo | |
158 | self.assertEqual(r.repo_name, os.path.join('g2', 'g1', r.just_name)) |
|
150 | self.assertEqual(r.repo_name, os.path.join('g2', 'g1', r.just_name)) | |
159 |
|
151 | |||
|
152 | ||||
160 | class TestUser(unittest.TestCase): |
|
153 | class TestUser(unittest.TestCase): | |
161 | def __init__(self, methodName='runTest'): |
|
154 | def __init__(self, methodName='runTest'): | |
162 | Session.remove() |
|
155 | Session.remove() | |
@@ -245,7 +238,6 b' class TestNotifications(unittest.TestCas' | |||||
245 | self.assertEqual(len(unotification), len(usrs)) |
|
238 | self.assertEqual(len(unotification), len(usrs)) | |
246 | self.assertEqual([x.user.user_id for x in unotification], usrs) |
|
239 | self.assertEqual([x.user.user_id for x in unotification], usrs) | |
247 |
|
240 | |||
248 |
|
||||
249 | def test_user_notifications(self): |
|
241 | def test_user_notifications(self): | |
250 | self.assertEqual([], Notification.query().all()) |
|
242 | self.assertEqual([], Notification.query().all()) | |
251 | self.assertEqual([], UserNotification.query().all()) |
|
243 | self.assertEqual([], UserNotification.query().all()) | |
@@ -284,7 +276,6 b' class TestNotifications(unittest.TestCas' | |||||
284 | == notification).all() |
|
276 | == notification).all() | |
285 | self.assertEqual(un, []) |
|
277 | self.assertEqual(un, []) | |
286 |
|
278 | |||
287 |
|
||||
288 | def test_delete_association(self): |
|
279 | def test_delete_association(self): | |
289 |
|
280 | |||
290 | self.assertEqual([], Notification.query().all()) |
|
281 | self.assertEqual([], Notification.query().all()) | |
@@ -361,6 +352,7 b' class TestNotifications(unittest.TestCas' | |||||
361 | self.assertEqual(NotificationModel() |
|
352 | self.assertEqual(NotificationModel() | |
362 | .get_unread_cnt_for_user(self.u3), 2) |
|
353 | .get_unread_cnt_for_user(self.u3), 2) | |
363 |
|
354 | |||
|
355 | ||||
364 | class TestUsers(unittest.TestCase): |
|
356 | class TestUsers(unittest.TestCase): | |
365 |
|
357 | |||
366 | def __init__(self, methodName='runTest'): |
|
358 | def __init__(self, methodName='runTest'): | |
@@ -401,4 +393,163 b' class TestUsers(unittest.TestCase):' | |||||
401 | #revoke |
|
393 | #revoke | |
402 | UserModel().revoke_perm(self.u1, perm) |
|
394 | UserModel().revoke_perm(self.u1, perm) | |
403 | Session.commit() |
|
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 | beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long |
|
89 | beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long | |
90 |
|
90 | |||
91 | beaker.cache.super_short_term.type=memory |
|
91 | beaker.cache.super_short_term.type=memory | |
92 |
beaker.cache.super_short_term.expire=1 |
|
92 | beaker.cache.super_short_term.expire=1 | |
93 | beaker.cache.super_short_term.key_length = 256 |
|
93 | beaker.cache.super_short_term.key_length = 256 | |
94 |
|
94 | |||
95 | beaker.cache.short_term.type=memory |
|
95 | beaker.cache.short_term.type=memory | |
@@ -101,7 +101,7 b' beaker.cache.long_term.expire=36000' | |||||
101 | beaker.cache.long_term.key_length = 256 |
|
101 | beaker.cache.long_term.key_length = 256 | |
102 |
|
102 | |||
103 | beaker.cache.sql_cache_short.type=memory |
|
103 | beaker.cache.sql_cache_short.type=memory | |
104 |
beaker.cache.sql_cache_short.expire=1 |
|
104 | beaker.cache.sql_cache_short.expire=1 | |
105 | beaker.cache.sql_cache_short.key_length = 256 |
|
105 | beaker.cache.sql_cache_short.key_length = 256 | |
106 |
|
106 | |||
107 | beaker.cache.sql_cache_med.type=memory |
|
107 | beaker.cache.sql_cache_med.type=memory |
General Comments 0
You need to be logged in to leave comments.
Login now