Show More
@@ -30,13 +30,14 b' import traceback' | |||||
30 | import formencode |
|
30 | import formencode | |
31 |
|
31 | |||
32 | from formencode import htmlfill |
|
32 | from formencode import htmlfill | |
33 | from pylons import request, session, tmpl_context as c, url |
|
33 | from pylons import request, session, tmpl_context as c, url, config | |
34 | from pylons.controllers.util import abort, redirect |
|
34 | from pylons.controllers.util import abort, redirect | |
35 | from pylons.i18n.translation import _ |
|
35 | from pylons.i18n.translation import _ | |
36 |
|
36 | |||
37 |
from rhodecode.lib.exceptions import |
|
37 | from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException | |
38 | from rhodecode.lib import helpers as h |
|
38 | from rhodecode.lib import helpers as h | |
39 | from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator |
|
39 | from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \ | |
|
40 | fill_perms | |||
40 | from rhodecode.lib.base import BaseController, render |
|
41 | from rhodecode.lib.base import BaseController, render | |
41 |
|
42 | |||
42 | from rhodecode.model.db import User |
|
43 | from rhodecode.model.db import User | |
@@ -57,7 +58,7 b' class UsersController(BaseController):' | |||||
57 | c.admin_user = session.get('admin_user') |
|
58 | c.admin_user = session.get('admin_user') | |
58 | c.admin_username = session.get('admin_username') |
|
59 | c.admin_username = session.get('admin_username') | |
59 | super(UsersController, self).__before__() |
|
60 | super(UsersController, self).__before__() | |
60 |
|
61 | c.available_permissions = config['available_permissions'] | ||
61 |
|
62 | |||
62 | def index(self, format='html'): |
|
63 | def index(self, format='html'): | |
63 | """GET /users: All items in the collection""" |
|
64 | """GET /users: All items in the collection""" | |
@@ -140,7 +141,7 b' class UsersController(BaseController):' | |||||
140 | user_model = UserModel() |
|
141 | user_model = UserModel() | |
141 | try: |
|
142 | try: | |
142 | user_model.delete(id) |
|
143 | user_model.delete(id) | |
143 | h.flash(_('sucessfully deleted user'), category='success') |
|
144 | h.flash(_('successfully deleted user'), category='success') | |
144 | except (UserOwnsReposException, DefaultUserException), e: |
|
145 | except (UserOwnsReposException, DefaultUserException), e: | |
145 | h.flash(str(e), category='warning') |
|
146 | h.flash(str(e), category='warning') | |
146 | except Exception: |
|
147 | except Exception: | |
@@ -162,8 +163,11 b' class UsersController(BaseController):' | |||||
162 | if c.user.username == 'default': |
|
163 | if c.user.username == 'default': | |
163 | h.flash(_("You can't edit this user"), category='warning') |
|
164 | h.flash(_("You can't edit this user"), category='warning') | |
164 | return redirect(url('users')) |
|
165 | return redirect(url('users')) | |
|
166 | c.user.permissions = {} | |||
|
167 | c.granted_permissions = fill_perms(c.user).permissions['global'] | |||
165 |
|
168 | |||
166 | defaults = c.user.get_dict() |
|
169 | defaults = c.user.get_dict() | |
|
170 | ||||
167 | return htmlfill.render( |
|
171 | return htmlfill.render( | |
168 | render('admin/users/user_edit.html'), |
|
172 | render('admin/users/user_edit.html'), | |
169 | defaults=defaults, |
|
173 | defaults=defaults, |
@@ -1,8 +1,14 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | # -*- coding: utf-8 -*- | |
2 | # encoding: utf-8 |
|
2 | """ | |
3 | # authentication and permission libraries |
|
3 | rhodecode.lib.auth | |
4 | # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com> |
|
4 | ~~~~~~~~~~~~~~~~~~ | |
5 | # |
|
5 | ||
|
6 | authentication and permission libraries | |||
|
7 | ||||
|
8 | :created_on: Apr 4, 2010 | |||
|
9 | :copyright: (c) 2010 by marcink. | |||
|
10 | :license: LICENSE_NAME, see LICENSE_FILE for more details. | |||
|
11 | """ | |||
6 | # This program is free software; you can redistribute it and/or |
|
12 | # This program is free software; you can redistribute it and/or | |
7 | # modify it under the terms of the GNU General Public License |
|
13 | # modify it under the terms of the GNU General Public License | |
8 | # as published by the Free Software Foundation; version 2 |
|
14 | # as published by the Free Software Foundation; version 2 | |
@@ -17,26 +23,26 b'' | |||||
17 | # along with this program; if not, write to the Free Software |
|
23 | # along with this program; if not, write to the Free Software | |
18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
24 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
19 | # MA 02110-1301, USA. |
|
25 | # MA 02110-1301, USA. | |
20 | """ |
|
|||
21 | Created on April 4, 2010 |
|
|||
22 |
|
26 | |||
23 | @author: marcink |
|
27 | import bcrypt | |
24 | """ |
|
28 | import random | |
|
29 | import logging | |||
|
30 | import traceback | |||
|
31 | ||||
|
32 | from decorator import decorator | |||
|
33 | ||||
25 | from pylons import config, session, url, request |
|
34 | from pylons import config, session, url, request | |
26 | from pylons.controllers.util import abort, redirect |
|
35 | from pylons.controllers.util import abort, redirect | |
27 | from rhodecode.lib.exceptions import * |
|
36 | ||
|
37 | from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError | |||
28 | from rhodecode.lib.utils import get_repo_slug |
|
38 | from rhodecode.lib.utils import get_repo_slug | |
29 | from rhodecode.lib.auth_ldap import AuthLdap |
|
39 | from rhodecode.lib.auth_ldap import AuthLdap | |
|
40 | ||||
30 | from rhodecode.model import meta |
|
41 | from rhodecode.model import meta | |
31 | from rhodecode.model.user import UserModel |
|
42 | from rhodecode.model.user import UserModel | |
32 | from rhodecode.model.caching_query import FromCache |
|
|||
33 | from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \ |
|
43 | from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \ | |
34 | UserToPerm |
|
44 | UserToPerm | |
35 | import bcrypt |
|
45 | ||
36 | from decorator import decorator |
|
|||
37 | import logging |
|
|||
38 | import random |
|
|||
39 | import traceback |
|
|||
40 |
|
46 | |||
41 | log = logging.getLogger(__name__) |
|
47 | log = logging.getLogger(__name__) | |
42 |
|
48 | |||
@@ -172,12 +178,13 b' class AuthUser(object):' | |||||
172 | return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username) |
|
178 | return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username) | |
173 |
|
179 | |||
174 | def set_available_permissions(config): |
|
180 | def set_available_permissions(config): | |
175 | """ |
|
181 | """This function will propagate pylons globals with all available defined | |
176 | This function will propagate pylons globals with all available defined |
|
|||
177 | permission given in db. We don't wannt to check each time from db for new |
|
182 | permission given in db. We don't wannt to check each time from db for new | |
178 | permissions since adding a new permission also requires application restart |
|
183 | permissions since adding a new permission also requires application restart | |
179 | ie. to decorate new views with the newly created permission |
|
184 | ie. to decorate new views with the newly created permission | |
180 | :param config: |
|
185 | ||
|
186 | :param config: current pylons config instance | |||
|
187 | ||||
181 | """ |
|
188 | """ | |
182 | log.info('getting information about all available permissions') |
|
189 | log.info('getting information about all available permissions') | |
183 | try: |
|
190 | try: | |
@@ -195,9 +202,10 b' def set_base_path(config):' | |||||
195 |
|
202 | |||
196 |
|
203 | |||
197 | def fill_perms(user): |
|
204 | def fill_perms(user): | |
198 | """ |
|
205 | """Fills user permission attribute with permissions taken from database | |
199 | Fills user permission attribute with permissions taken from database |
|
206 | ||
200 | :param user: |
|
207 | :param user: | |
|
208 | ||||
201 | """ |
|
209 | """ | |
202 |
|
210 | |||
203 | sa = meta.Session() |
|
211 | sa = meta.Session() |
@@ -117,6 +117,11 b' class User(Base, BaseModel):' | |||||
117 | def full_contact(self): |
|
117 | def full_contact(self): | |
118 | return '%s %s <%s>' % (self.name, self.lastname, self.email) |
|
118 | return '%s %s <%s>' % (self.name, self.lastname, self.email) | |
119 |
|
119 | |||
|
120 | ||||
|
121 | @property | |||
|
122 | def is_admin(self): | |||
|
123 | return self.admin | |||
|
124 | ||||
120 | def __repr__(self): |
|
125 | def __repr__(self): | |
121 | return "<%s('id:%s:%s')>" % (self.__class__.__name__, |
|
126 | return "<%s('id:%s:%s')>" % (self.__class__.__name__, | |
122 | self.user_id, self.username) |
|
127 | self.user_id, self.username) |
@@ -113,8 +113,122 b'' | |||||
113 | <div class="title"> |
|
113 | <div class="title"> | |
114 | <h5>${_('Permissions')}</h5> |
|
114 | <h5>${_('Permissions')}</h5> | |
115 | </div> |
|
115 | </div> | |
116 | <div class="table"> |
|
116 | <form id="map_form" method="post" action="{%url update_permissions %}"> | |
117 | Permissions settings goes here ! |
|
117 | <div class="form"> | |
118 | </div> |
|
118 | <div class="fields"> | |
|
119 | ||||
|
120 | ||||
|
121 | ||||
|
122 | <table> | |||
|
123 | <tr> | |||
|
124 | <td class="label">${_('Permissions')}:</td> | |||
|
125 | <td> | |||
|
126 | <div> | |||
|
127 | <div style="float:left"> | |||
|
128 | <div class="text">${_('Granted permissions')}</div> | |||
|
129 | ${h.select('granted_permissions',[],c.granted_permissions,multiple=True,size=8,style="min-width:210px")} | |||
|
130 | </div> | |||
|
131 | <div style="float:left;width:20px;padding-top:50px"> | |||
|
132 | <img alt="add" id="add_element" | |||
|
133 | style="padding:2px;cursor:pointer" | |||
|
134 | src="/images/icons/arrow_left.png"> | |||
|
135 | <br /> | |||
|
136 | <img alt="remove" id="remove_element" | |||
|
137 | style="padding:2px;cursor:pointer" | |||
|
138 | src="/images/icons/arrow_right.png"> | |||
|
139 | </div> | |||
|
140 | <div style="float:left"> | |||
|
141 | <div class="text">${_('Available permissions')}</div> | |||
|
142 | ${h.select('available_permissions',[],c.available_permissions,multiple=True,size=8,style="min-width:210px")} | |||
|
143 | </div> | |||
|
144 | </div> | |||
|
145 | </td> | |||
|
146 | </tr> | |||
|
147 | ||||
|
148 | </table> | |||
|
149 | <div class="buttons"> | |||
|
150 | ${h.submit('Save','Save',class_="ui-button")} | |||
|
151 | </div> | |||
|
152 | </div> | |||
|
153 | </div> | |||
|
154 | </form> | |||
|
155 | ||||
|
156 | ||||
|
157 | <script type="text/javascript"> | |||
|
158 | YAHOO.util.Event.onDOMReady(function(){ | |||
|
159 | ||||
|
160 | var D = YAHOO.util.Dom; | |||
|
161 | var E = YAHOO.util.Event; | |||
|
162 | ||||
|
163 | //temp container for storage. | |||
|
164 | var cache = new Array(); | |||
|
165 | var c = D.get('id_granted_permissions'); | |||
|
166 | ||||
|
167 | //get only selected options for further fullfilment | |||
|
168 | for(var i = 0;node =c.options[i];i++){ | |||
|
169 | if(node.selected){ | |||
|
170 | //push selected to my temp storage left overs :) | |||
|
171 | cache.push(node); | |||
|
172 | } | |||
|
173 | } | |||
|
174 | ||||
|
175 | //clear select | |||
|
176 | c.options.length = 0; | |||
|
177 | ||||
|
178 | //fill it with remembered options | |||
|
179 | for(var i = 0;node = cache[i];i++){ | |||
|
180 | c.options[i]=new Option(node.text, node.value, false, false); | |||
|
181 | } | |||
|
182 | ||||
|
183 | function target_callback(e){ | |||
|
184 | window.location='/admin/t4?g='+e.target.value; | |||
|
185 | } | |||
|
186 | ||||
|
187 | function prompts_action_callback(e){ | |||
|
188 | ||||
|
189 | var choosen = D.get('id_granted_permissions'); | |||
|
190 | var availible = D.get('id_available_permissions'); | |||
|
191 | ||||
|
192 | if (this.id=='add_element'){ | |||
|
193 | for(var i=0; node = availible.options[i];i++){ | |||
|
194 | if(node.selected){ | |||
|
195 | choosen.appendChild(new Option(node.text, node.value, false, false)); | |||
|
196 | } | |||
|
197 | } | |||
|
198 | } | |||
|
199 | else if (this.id=='remove_element'){ | |||
|
200 | ||||
|
201 | //temp container for storage. | |||
|
202 | cache = new Array(); | |||
|
203 | ||||
|
204 | for(var i = 0;node = choosen.options[i];i++){ | |||
|
205 | if(!node.selected){ | |||
|
206 | //push left overs :) | |||
|
207 | cache.push(node); | |||
|
208 | } | |||
|
209 | } | |||
|
210 | //clear select | |||
|
211 | choosen.options.length = 0; | |||
|
212 | for(var i = 0;node = cache[i];i++){ | |||
|
213 | choosen.options[i]=new Option(node.text, node.value, false, false); | |||
|
214 | } | |||
|
215 | } | |||
|
216 | else{ | |||
|
217 | ||||
|
218 | } | |||
|
219 | } | |||
|
220 | ||||
|
221 | E.addListener('id_groups','change',target_callback); | |||
|
222 | ||||
|
223 | E.addListener(['add_element','remove_element'],'click',prompts_action_callback) | |||
|
224 | ||||
|
225 | E.addListener('map_form','submit',function(){ | |||
|
226 | var choosen = D.get('id_granted_permissions'); | |||
|
227 | for (var i = 0; i < choosen.options.length; i++) { | |||
|
228 | choosen.options[i].selected = 'selected'; | |||
|
229 | } | |||
|
230 | }) | |||
|
231 | }); | |||
|
232 | </script> | |||
119 | </div> |
|
233 | </div> | |
120 | </%def> No newline at end of file |
|
234 | </%def> |
@@ -100,7 +100,7 b' class TestAdminUsersController(TestContr' | |||||
100 | new_user = self.sa.query(User).filter(User.username == username).one() |
|
100 | new_user = self.sa.query(User).filter(User.username == username).one() | |
101 | response = self.app.delete(url('user', id=new_user.user_id)) |
|
101 | response = self.app.delete(url('user', id=new_user.user_id)) | |
102 |
|
102 | |||
103 | assert """sucessfully deleted user""" in response.session['flash'][0], 'No info about user deletion' |
|
103 | assert """successfully deleted user""" in response.session['flash'][0], 'No info about user deletion' | |
104 |
|
104 | |||
105 |
|
105 | |||
106 | def test_delete_browser_fakeout(self): |
|
106 | def test_delete_browser_fakeout(self): |
General Comments 0
You need to be logged in to leave comments.
Login now