##// END OF EJS Templates
Iteration on default permissions...
marcink -
r3736:87e6960e beta
parent child Browse files
Show More
@@ -0,0 +1,86 b''
1 ## snippet for displaying default permission box
2 ## usage:
3 ## <%namespace name="dpb" file="/base/default_perms_box.html"/>
4 ## ${dpb.default_perms_box(<url_to_form>)}
5
6
7 <%def name="default_perms_box(form_url)">
8 ${h.form(form_url, method='put')}
9 <div class="form">
10 <!-- fields -->
11 <div class="fields">
12 <div class="field">
13 <div class="checkboxes">
14 <label for="inherit_default_permissions">${_('Inherit default permissions')}:</label>
15 ${h.checkbox('inherit_default_permissions',value=True)}
16 </div>
17 <span class="help-block">
18 ${h.literal(_('Select to inherit permissions from %s settings. '
19 'With this selected below options does not apply.')
20 % h.link_to('default', url('edit_permission', id='default')))}
21 </span>
22 </div>
23 <div id="inherit_overlay">
24 <div class="field">
25 <div class="checkboxes">
26 <label for="create_repo_perm">${_('Create repositories')}:</label>
27 ${h.checkbox('create_repo_perm',value=True)}
28 </div>
29 <span class="help-block">
30 ${h.literal(_('Select this option to allow repository creation for this user'))}
31 </span>
32 </div>
33 <div class="field">
34 <div class="checkboxes">
35 <label for="create_user_group_perm">${_('Create user groups')}:</label>
36 ${h.checkbox('create_user_group_perm',value=True)}
37 </div>
38 <span class="help-block">
39 ${h.literal(_('Select this option to allow user group creation for this user'))}
40 </span>
41 </div>
42 <div class="field">
43 <div class="checkboxes">
44 <label for="fork_repo_perm">${_('Fork repositories')}:</label>
45 ${h.checkbox('fork_repo_perm',value=True)}
46 </div>
47 <span class="help-block">
48 ${h.literal(_('Select this option to allow repository forking for this user'))}
49 </span>
50 </div>
51 </div>
52 <div class="buttons">
53 ${h.submit('save',_('Save'),class_="ui-btn large")}
54 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
55 </div>
56 </div>
57 </div>
58 ${h.end_form()}
59
60 ## JS
61 <script>
62 YUE.onDOMReady(function(e){
63
64 var show_custom_perms = function(inherit_default){
65 if(inherit_default){
66 YUD.setStyle('inherit_overlay', 'display', 'none');
67 }
68 else{
69 YUD.setStyle('inherit_overlay', 'display', '');
70 }
71 }
72
73 var defaults = YUD.get('inherit_default_permissions').checked;
74 show_custom_perms(defaults);
75 YUE.on('inherit_default_permissions', 'change', function(e){
76 if(YUD.get('inherit_default_permissions').checked){
77 show_custom_perms(true);
78 }
79 else{
80 show_custom_perms(false);
81 }
82 })
83 })
84 </script>
85
86 </%def>
@@ -1,361 +1,359 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.users
3 rhodecode.controllers.admin.users
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Users crud controller for pylons
6 Users crud controller for pylons
7
7
8 :created_on: Apr 4, 2010
8 :created_on: Apr 4, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import formencode
28 import formencode
29 from pylons import response
29 from pylons import response
30
30
31 from formencode import htmlfill
31 from formencode import htmlfill
32 from pylons import request, session, tmpl_context as c, url, config
32 from pylons import request, session, tmpl_context as c, url, config
33 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
34 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
35
35
36 import rhodecode
36 import rhodecode
37 from rhodecode.lib.exceptions import DefaultUserException, \
37 from rhodecode.lib.exceptions import DefaultUserException, \
38 UserOwnsReposException
38 UserOwnsReposException
39 from rhodecode.lib import helpers as h
39 from rhodecode.lib import helpers as h
40 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
40 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
41 AuthUser
41 AuthUser
42 from rhodecode.lib.base import BaseController, render
42 from rhodecode.lib.base import BaseController, render
43
43
44 from rhodecode.model.db import User, UserEmailMap, UserIpMap
44 from rhodecode.model.db import User, UserEmailMap, UserIpMap, UserToPerm
45 from rhodecode.model.forms import UserForm
45 from rhodecode.model.forms import UserForm, CustomDefaultPermissionsForm
46 from rhodecode.model.user import UserModel
46 from rhodecode.model.user import UserModel
47 from rhodecode.model.meta import Session
47 from rhodecode.model.meta import Session
48 from rhodecode.lib.utils import action_logger
48 from rhodecode.lib.utils import action_logger
49 from rhodecode.lib.compat import json
49 from rhodecode.lib.compat import json
50 from rhodecode.lib.utils2 import datetime_to_time, str2bool
50 from rhodecode.lib.utils2 import datetime_to_time, str2bool
51
51
52 log = logging.getLogger(__name__)
52 log = logging.getLogger(__name__)
53
53
54
54
55 class UsersController(BaseController):
55 class UsersController(BaseController):
56 """REST Controller styled on the Atom Publishing Protocol"""
56 """REST Controller styled on the Atom Publishing Protocol"""
57 # To properly map this controller, ensure your config/routing.py
57 # To properly map this controller, ensure your config/routing.py
58 # file has a resource setup:
58 # file has a resource setup:
59 # map.resource('user', 'users')
59 # map.resource('user', 'users')
60
60
61 @LoginRequired()
61 @LoginRequired()
62 @HasPermissionAllDecorator('hg.admin')
62 @HasPermissionAllDecorator('hg.admin')
63 def __before__(self):
63 def __before__(self):
64 super(UsersController, self).__before__()
64 super(UsersController, self).__before__()
65 c.available_permissions = config['available_permissions']
65 c.available_permissions = config['available_permissions']
66
66
67 def index(self, format='html'):
67 def index(self, format='html'):
68 """GET /users: All items in the collection"""
68 """GET /users: All items in the collection"""
69 # url('users')
69 # url('users')
70
70
71 c.users_list = User.query().order_by(User.username).all()
71 c.users_list = User.query().order_by(User.username).all()
72
72
73 users_data = []
73 users_data = []
74 total_records = len(c.users_list)
74 total_records = len(c.users_list)
75 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
75 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
76 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
76 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
77
77
78 grav_tmpl = lambda user_email, size: (
78 grav_tmpl = lambda user_email, size: (
79 template.get_def("user_gravatar")
79 template.get_def("user_gravatar")
80 .render(user_email, size, _=_, h=h, c=c))
80 .render(user_email, size, _=_, h=h, c=c))
81
81
82 user_lnk = lambda user_id, username: (
82 user_lnk = lambda user_id, username: (
83 template.get_def("user_name")
83 template.get_def("user_name")
84 .render(user_id, username, _=_, h=h, c=c))
84 .render(user_id, username, _=_, h=h, c=c))
85
85
86 user_actions = lambda user_id, username: (
86 user_actions = lambda user_id, username: (
87 template.get_def("user_actions")
87 template.get_def("user_actions")
88 .render(user_id, username, _=_, h=h, c=c))
88 .render(user_id, username, _=_, h=h, c=c))
89
89
90 for user in c.users_list:
90 for user in c.users_list:
91
91
92 users_data.append({
92 users_data.append({
93 "gravatar": grav_tmpl(user. email, 24),
93 "gravatar": grav_tmpl(user. email, 24),
94 "raw_username": user.username,
94 "raw_username": user.username,
95 "username": user_lnk(user.user_id, user.username),
95 "username": user_lnk(user.user_id, user.username),
96 "firstname": user.name,
96 "firstname": user.name,
97 "lastname": user.lastname,
97 "lastname": user.lastname,
98 "last_login": h.fmt_date(user.last_login),
98 "last_login": h.fmt_date(user.last_login),
99 "last_login_raw": datetime_to_time(user.last_login),
99 "last_login_raw": datetime_to_time(user.last_login),
100 "active": h.boolicon(user.active),
100 "active": h.boolicon(user.active),
101 "admin": h.boolicon(user.admin),
101 "admin": h.boolicon(user.admin),
102 "ldap": h.boolicon(bool(user.ldap_dn)),
102 "ldap": h.boolicon(bool(user.ldap_dn)),
103 "action": user_actions(user.user_id, user.username),
103 "action": user_actions(user.user_id, user.username),
104 })
104 })
105
105
106 c.data = json.dumps({
106 c.data = json.dumps({
107 "totalRecords": total_records,
107 "totalRecords": total_records,
108 "startIndex": 0,
108 "startIndex": 0,
109 "sort": None,
109 "sort": None,
110 "dir": "asc",
110 "dir": "asc",
111 "records": users_data
111 "records": users_data
112 })
112 })
113
113
114 return render('admin/users/users.html')
114 return render('admin/users/users.html')
115
115
116 def create(self):
116 def create(self):
117 """POST /users: Create a new item"""
117 """POST /users: Create a new item"""
118 # url('users')
118 # url('users')
119
119
120 user_model = UserModel()
120 user_model = UserModel()
121 user_form = UserForm()()
121 user_form = UserForm()()
122 try:
122 try:
123 form_result = user_form.to_python(dict(request.POST))
123 form_result = user_form.to_python(dict(request.POST))
124 user_model.create(form_result)
124 user_model.create(form_result)
125 usr = form_result['username']
125 usr = form_result['username']
126 action_logger(self.rhodecode_user, 'admin_created_user:%s' % usr,
126 action_logger(self.rhodecode_user, 'admin_created_user:%s' % usr,
127 None, self.ip_addr, self.sa)
127 None, self.ip_addr, self.sa)
128 h.flash(_('Created user %s') % usr,
128 h.flash(_('Created user %s') % usr,
129 category='success')
129 category='success')
130 Session().commit()
130 Session().commit()
131 except formencode.Invalid, errors:
131 except formencode.Invalid, errors:
132 return htmlfill.render(
132 return htmlfill.render(
133 render('admin/users/user_add.html'),
133 render('admin/users/user_add.html'),
134 defaults=errors.value,
134 defaults=errors.value,
135 errors=errors.error_dict or {},
135 errors=errors.error_dict or {},
136 prefix_error=False,
136 prefix_error=False,
137 encoding="UTF-8")
137 encoding="UTF-8")
138 except Exception:
138 except Exception:
139 log.error(traceback.format_exc())
139 log.error(traceback.format_exc())
140 h.flash(_('Error occurred during creation of user %s') \
140 h.flash(_('Error occurred during creation of user %s') \
141 % request.POST.get('username'), category='error')
141 % request.POST.get('username'), category='error')
142 return redirect(url('users'))
142 return redirect(url('users'))
143
143
144 def new(self, format='html'):
144 def new(self, format='html'):
145 """GET /users/new: Form to create a new item"""
145 """GET /users/new: Form to create a new item"""
146 # url('new_user')
146 # url('new_user')
147 return render('admin/users/user_add.html')
147 return render('admin/users/user_add.html')
148
148
149 def update(self, id):
149 def update(self, id):
150 """PUT /users/id: Update an existing item"""
150 """PUT /users/id: Update an existing item"""
151 # Forms posted to this method should contain a hidden field:
151 # Forms posted to this method should contain a hidden field:
152 # <input type="hidden" name="_method" value="PUT" />
152 # <input type="hidden" name="_method" value="PUT" />
153 # Or using helpers:
153 # Or using helpers:
154 # h.form(url('update_user', id=ID),
154 # h.form(url('update_user', id=ID),
155 # method='put')
155 # method='put')
156 # url('user', id=ID)
156 # url('user', id=ID)
157 user_model = UserModel()
157 user_model = UserModel()
158 c.user = user_model.get(id)
158 c.user = user_model.get(id)
159 c.ldap_dn = c.user.ldap_dn
159 c.ldap_dn = c.user.ldap_dn
160 c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr)
160 c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr)
161 _form = UserForm(edit=True, old_data={'user_id': id,
161 _form = UserForm(edit=True, old_data={'user_id': id,
162 'email': c.user.email})()
162 'email': c.user.email})()
163 form_result = {}
163 form_result = {}
164 try:
164 try:
165 form_result = _form.to_python(dict(request.POST))
165 form_result = _form.to_python(dict(request.POST))
166 skip_attrs = []
166 skip_attrs = []
167 if c.ldap_dn:
167 if c.ldap_dn:
168 #forbid updating username for ldap accounts
168 #forbid updating username for ldap accounts
169 skip_attrs = ['username']
169 skip_attrs = ['username']
170 user_model.update(id, form_result, skip_attrs=skip_attrs)
170 user_model.update(id, form_result, skip_attrs=skip_attrs)
171 usr = form_result['username']
171 usr = form_result['username']
172 action_logger(self.rhodecode_user, 'admin_updated_user:%s' % usr,
172 action_logger(self.rhodecode_user, 'admin_updated_user:%s' % usr,
173 None, self.ip_addr, self.sa)
173 None, self.ip_addr, self.sa)
174 h.flash(_('User updated successfully'), category='success')
174 h.flash(_('User updated successfully'), category='success')
175 Session().commit()
175 Session().commit()
176 except formencode.Invalid, errors:
176 except formencode.Invalid, errors:
177 c.user_email_map = UserEmailMap.query()\
177 c.user_email_map = UserEmailMap.query()\
178 .filter(UserEmailMap.user == c.user).all()
178 .filter(UserEmailMap.user == c.user).all()
179 c.user_ip_map = UserIpMap.query()\
179 c.user_ip_map = UserIpMap.query()\
180 .filter(UserIpMap.user == c.user).all()
180 .filter(UserIpMap.user == c.user).all()
181 defaults = errors.value
181 defaults = errors.value
182 e = errors.error_dict or {}
182 e = errors.error_dict or {}
183 defaults.update({
183 defaults.update({
184 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'),
184 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'),
185 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'),
185 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'),
186 '_method': 'put'
186 '_method': 'put'
187 })
187 })
188 return htmlfill.render(
188 return htmlfill.render(
189 render('admin/users/user_edit.html'),
189 render('admin/users/user_edit.html'),
190 defaults=defaults,
190 defaults=defaults,
191 errors=e,
191 errors=e,
192 prefix_error=False,
192 prefix_error=False,
193 encoding="UTF-8")
193 encoding="UTF-8")
194 except Exception:
194 except Exception:
195 log.error(traceback.format_exc())
195 log.error(traceback.format_exc())
196 h.flash(_('Error occurred during update of user %s') \
196 h.flash(_('Error occurred during update of user %s') \
197 % form_result.get('username'), category='error')
197 % form_result.get('username'), category='error')
198 return redirect(url('edit_user', id=id))
198 return redirect(url('edit_user', id=id))
199
199
200 def delete(self, id):
200 def delete(self, id):
201 """DELETE /users/id: Delete an existing item"""
201 """DELETE /users/id: Delete an existing item"""
202 # Forms posted to this method should contain a hidden field:
202 # Forms posted to this method should contain a hidden field:
203 # <input type="hidden" name="_method" value="DELETE" />
203 # <input type="hidden" name="_method" value="DELETE" />
204 # Or using helpers:
204 # Or using helpers:
205 # h.form(url('delete_user', id=ID),
205 # h.form(url('delete_user', id=ID),
206 # method='delete')
206 # method='delete')
207 # url('user', id=ID)
207 # url('user', id=ID)
208 usr = User.get_or_404(id)
208 usr = User.get_or_404(id)
209 try:
209 try:
210 UserModel().delete(usr)
210 UserModel().delete(usr)
211 Session().commit()
211 Session().commit()
212 h.flash(_('Successfully deleted user'), category='success')
212 h.flash(_('Successfully deleted user'), category='success')
213 except (UserOwnsReposException, DefaultUserException), e:
213 except (UserOwnsReposException, DefaultUserException), e:
214 h.flash(e, category='warning')
214 h.flash(e, category='warning')
215 except Exception:
215 except Exception:
216 log.error(traceback.format_exc())
216 log.error(traceback.format_exc())
217 h.flash(_('An error occurred during deletion of user'),
217 h.flash(_('An error occurred during deletion of user'),
218 category='error')
218 category='error')
219 return redirect(url('users'))
219 return redirect(url('users'))
220
220
221 def show(self, id, format='html'):
221 def show(self, id, format='html'):
222 """GET /users/id: Show a specific item"""
222 """GET /users/id: Show a specific item"""
223 # url('user', id=ID)
223 # url('user', id=ID)
224 User.get_or_404(-1)
224 User.get_or_404(-1)
225
225
226 def edit(self, id, format='html'):
226 def edit(self, id, format='html'):
227 """GET /users/id/edit: Form to edit an existing item"""
227 """GET /users/id/edit: Form to edit an existing item"""
228 # url('edit_user', id=ID)
228 # url('edit_user', id=ID)
229 c.user = User.get_or_404(id)
229 c.user = User.get_or_404(id)
230
230
231 if c.user.username == 'default':
231 if c.user.username == 'default':
232 h.flash(_("You can't edit this user"), category='warning')
232 h.flash(_("You can't edit this user"), category='warning')
233 return redirect(url('users'))
233 return redirect(url('users'))
234
234
235 c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr)
235 c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr)
236 c.user.permissions = {}
236 c.user.permissions = {}
237 c.granted_permissions = UserModel().fill_perms(c.user)\
237 c.granted_permissions = UserModel().fill_perms(c.user)\
238 .permissions['global']
238 .permissions['global']
239 c.user_email_map = UserEmailMap.query()\
239 c.user_email_map = UserEmailMap.query()\
240 .filter(UserEmailMap.user == c.user).all()
240 .filter(UserEmailMap.user == c.user).all()
241 c.user_ip_map = UserIpMap.query()\
241 c.user_ip_map = UserIpMap.query()\
242 .filter(UserIpMap.user == c.user).all()
242 .filter(UserIpMap.user == c.user).all()
243 user_model = UserModel()
243 umodel = UserModel()
244 c.ldap_dn = c.user.ldap_dn
244 c.ldap_dn = c.user.ldap_dn
245 defaults = c.user.get_dict()
245 defaults = c.user.get_dict()
246 defaults.update({
246 defaults.update({
247 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'),
247 'create_repo_perm': umodel.has_perm(c.user, 'hg.create.repository'),
248 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'),
248 'create_user_group_perm': umodel.has_perm(c.user, 'hg.usergroup.create.true'),
249 'fork_repo_perm': umodel.has_perm(c.user, 'hg.fork.repository'),
249 })
250 })
250
251
251 return htmlfill.render(
252 return htmlfill.render(
252 render('admin/users/user_edit.html'),
253 render('admin/users/user_edit.html'),
253 defaults=defaults,
254 defaults=defaults,
254 encoding="UTF-8",
255 encoding="UTF-8",
255 force_defaults=False
256 force_defaults=False
256 )
257 )
257
258
258 def update_perm(self, id):
259 def update_perm(self, id):
259 """PUT /users_perm/id: Update an existing item"""
260 """PUT /users_perm/id: Update an existing item"""
260 # url('user_perm', id=ID, method='put')
261 # url('user_perm', id=ID, method='put')
261 usr = User.get_or_404(id)
262 user = User.get_or_404(id)
262 grant_create_perm = str2bool(request.POST.get('create_repo_perm'))
263 grant_fork_perm = str2bool(request.POST.get('fork_repo_perm'))
264 inherit_perms = str2bool(request.POST.get('inherit_default_permissions'))
265
266 user_model = UserModel()
267
263
268 try:
264 try:
269 usr.inherit_default_permissions = inherit_perms
265 form = CustomDefaultPermissionsForm()()
270 Session().add(usr)
266 form_result = form.to_python(request.POST)
267
268 inherit_perms = form_result['inherit_default_permissions']
269 user.inherit_default_permissions = inherit_perms
270 Session().add(user)
271 user_model = UserModel()
271
272
272 if grant_create_perm:
273 defs = UserToPerm.query()\
273 user_model.revoke_perm(usr, 'hg.create.none')
274 .filter(UserToPerm.user == user)\
274 user_model.grant_perm(usr, 'hg.create.repository')
275 .all()
275 h.flash(_("Granted 'repository create' permission to user"),
276 for ug in defs:
276 category='success')
277 Session().delete(ug)
278
279 if form_result['create_repo_perm']:
280 user_model.grant_perm(id, 'hg.create.repository')
277 else:
281 else:
278 user_model.revoke_perm(usr, 'hg.create.repository')
282 user_model.grant_perm(id, 'hg.create.none')
279 user_model.grant_perm(usr, 'hg.create.none')
283 if form_result['create_user_group_perm']:
280 h.flash(_("Revoked 'repository create' permission to user"),
284 user_model.grant_perm(id, 'hg.usergroup.create.true')
281 category='success')
282
283 if grant_fork_perm:
284 user_model.revoke_perm(usr, 'hg.fork.none')
285 user_model.grant_perm(usr, 'hg.fork.repository')
286 h.flash(_("Granted 'repository fork' permission to user"),
287 category='success')
288 else:
285 else:
289 user_model.revoke_perm(usr, 'hg.fork.repository')
286 user_model.grant_perm(id, 'hg.usergroup.create.false')
290 user_model.grant_perm(usr, 'hg.fork.none')
287 if form_result['fork_repo_perm']:
291 h.flash(_("Revoked 'repository fork' permission to user"),
288 user_model.grant_perm(id, 'hg.fork.repository')
292 category='success')
289 else:
293
290 user_model.grant_perm(id, 'hg.fork.none')
291 h.flash(_("Updated permissions"), category='success')
294 Session().commit()
292 Session().commit()
295 except Exception:
293 except Exception:
296 log.error(traceback.format_exc())
294 log.error(traceback.format_exc())
297 h.flash(_('An error occurred during permissions saving'),
295 h.flash(_('An error occurred during permissions saving'),
298 category='error')
296 category='error')
299 return redirect(url('edit_user', id=id))
297 return redirect(url('edit_user', id=id))
300
298
301 def add_email(self, id):
299 def add_email(self, id):
302 """POST /user_emails:Add an existing item"""
300 """POST /user_emails:Add an existing item"""
303 # url('user_emails', id=ID, method='put')
301 # url('user_emails', id=ID, method='put')
304
302
305 email = request.POST.get('new_email')
303 email = request.POST.get('new_email')
306 user_model = UserModel()
304 user_model = UserModel()
307
305
308 try:
306 try:
309 user_model.add_extra_email(id, email)
307 user_model.add_extra_email(id, email)
310 Session().commit()
308 Session().commit()
311 h.flash(_("Added email %s to user") % email, category='success')
309 h.flash(_("Added email %s to user") % email, category='success')
312 except formencode.Invalid, error:
310 except formencode.Invalid, error:
313 msg = error.error_dict['email']
311 msg = error.error_dict['email']
314 h.flash(msg, category='error')
312 h.flash(msg, category='error')
315 except Exception:
313 except Exception:
316 log.error(traceback.format_exc())
314 log.error(traceback.format_exc())
317 h.flash(_('An error occurred during email saving'),
315 h.flash(_('An error occurred during email saving'),
318 category='error')
316 category='error')
319 return redirect(url('edit_user', id=id))
317 return redirect(url('edit_user', id=id))
320
318
321 def delete_email(self, id):
319 def delete_email(self, id):
322 """DELETE /user_emails_delete/id: Delete an existing item"""
320 """DELETE /user_emails_delete/id: Delete an existing item"""
323 # url('user_emails_delete', id=ID, method='delete')
321 # url('user_emails_delete', id=ID, method='delete')
324 user_model = UserModel()
322 user_model = UserModel()
325 user_model.delete_extra_email(id, request.POST.get('del_email'))
323 user_model.delete_extra_email(id, request.POST.get('del_email'))
326 Session().commit()
324 Session().commit()
327 h.flash(_("Removed email from user"), category='success')
325 h.flash(_("Removed email from user"), category='success')
328 return redirect(url('edit_user', id=id))
326 return redirect(url('edit_user', id=id))
329
327
330 def add_ip(self, id):
328 def add_ip(self, id):
331 """POST /user_ips:Add an existing item"""
329 """POST /user_ips:Add an existing item"""
332 # url('user_ips', id=ID, method='put')
330 # url('user_ips', id=ID, method='put')
333
331
334 ip = request.POST.get('new_ip')
332 ip = request.POST.get('new_ip')
335 user_model = UserModel()
333 user_model = UserModel()
336
334
337 try:
335 try:
338 user_model.add_extra_ip(id, ip)
336 user_model.add_extra_ip(id, ip)
339 Session().commit()
337 Session().commit()
340 h.flash(_("Added ip %s to user") % ip, category='success')
338 h.flash(_("Added ip %s to user") % ip, category='success')
341 except formencode.Invalid, error:
339 except formencode.Invalid, error:
342 msg = error.error_dict['ip']
340 msg = error.error_dict['ip']
343 h.flash(msg, category='error')
341 h.flash(msg, category='error')
344 except Exception:
342 except Exception:
345 log.error(traceback.format_exc())
343 log.error(traceback.format_exc())
346 h.flash(_('An error occurred during ip saving'),
344 h.flash(_('An error occurred during ip saving'),
347 category='error')
345 category='error')
348 if 'default_user' in request.POST:
346 if 'default_user' in request.POST:
349 return redirect(url('edit_permission', id='default'))
347 return redirect(url('edit_permission', id='default'))
350 return redirect(url('edit_user', id=id))
348 return redirect(url('edit_user', id=id))
351
349
352 def delete_ip(self, id):
350 def delete_ip(self, id):
353 """DELETE /user_ips_delete/id: Delete an existing item"""
351 """DELETE /user_ips_delete/id: Delete an existing item"""
354 # url('user_ips_delete', id=ID, method='delete')
352 # url('user_ips_delete', id=ID, method='delete')
355 user_model = UserModel()
353 user_model = UserModel()
356 user_model.delete_extra_ip(id, request.POST.get('del_ip'))
354 user_model.delete_extra_ip(id, request.POST.get('del_ip'))
357 Session().commit()
355 Session().commit()
358 h.flash(_("Removed ip from user"), category='success')
356 h.flash(_("Removed ip from user"), category='success')
359 if 'default_user' in request.POST:
357 if 'default_user' in request.POST:
360 return redirect(url('edit_permission', id='default'))
358 return redirect(url('edit_permission', id='default'))
361 return redirect(url('edit_user', id=id))
359 return redirect(url('edit_user', id=id))
@@ -1,367 +1,368 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.users_groups
3 rhodecode.controllers.admin.users_groups
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 User Groups crud controller for pylons
6 User Groups crud controller for pylons
7
7
8 :created_on: Jan 25, 2011
8 :created_on: Jan 25, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import formencode
28 import formencode
29
29
30 from formencode import htmlfill
30 from formencode import htmlfill
31 from pylons import request, session, tmpl_context as c, url, config
31 from pylons import request, session, tmpl_context as c, url, config
32 from pylons.controllers.util import abort, redirect
32 from pylons.controllers.util import abort, redirect
33 from pylons.i18n.translation import _
33 from pylons.i18n.translation import _
34
34
35 from rhodecode.lib import helpers as h
35 from rhodecode.lib import helpers as h
36 from rhodecode.lib.exceptions import UserGroupsAssignedException
36 from rhodecode.lib.exceptions import UserGroupsAssignedException
37 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
37 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator,\
38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator,\
39 HasUserGroupPermissionAnyDecorator
39 HasUserGroupPermissionAnyDecorator
40 from rhodecode.lib.base import BaseController, render
40 from rhodecode.lib.base import BaseController, render
41 from rhodecode.model.scm import UserGroupList
41 from rhodecode.model.scm import UserGroupList
42 from rhodecode.model.users_group import UserGroupModel
42 from rhodecode.model.users_group import UserGroupModel
43 from rhodecode.model.repo import RepoModel
43 from rhodecode.model.repo import RepoModel
44 from rhodecode.model.db import User, UserGroup, UserGroupToPerm,\
44 from rhodecode.model.db import User, UserGroup, UserGroupToPerm,\
45 UserGroupRepoToPerm, UserGroupRepoGroupToPerm
45 UserGroupRepoToPerm, UserGroupRepoGroupToPerm
46 from rhodecode.model.forms import UserGroupForm, UserGroupPermsForm
46 from rhodecode.model.forms import UserGroupForm, UserGroupPermsForm,\
47 CustomDefaultPermissionsForm
47 from rhodecode.model.meta import Session
48 from rhodecode.model.meta import Session
48 from rhodecode.lib.utils import action_logger
49 from rhodecode.lib.utils import action_logger
49 from sqlalchemy.orm import joinedload
50 from sqlalchemy.orm import joinedload
50 from webob.exc import HTTPInternalServerError
51 from webob.exc import HTTPInternalServerError
51
52
52 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
53
54
54
55
55 class UsersGroupsController(BaseController):
56 class UsersGroupsController(BaseController):
56 """REST Controller styled on the Atom Publishing Protocol"""
57 """REST Controller styled on the Atom Publishing Protocol"""
57 # To properly map this controller, ensure your config/routing.py
58 # To properly map this controller, ensure your config/routing.py
58 # file has a resource setup:
59 # file has a resource setup:
59 # map.resource('users_group', 'users_groups')
60 # map.resource('users_group', 'users_groups')
60
61
61 @LoginRequired()
62 @LoginRequired()
62 def __before__(self):
63 def __before__(self):
63 super(UsersGroupsController, self).__before__()
64 super(UsersGroupsController, self).__before__()
64 c.available_permissions = config['available_permissions']
65 c.available_permissions = config['available_permissions']
65
66
66 def __load_data(self, user_group_id):
67 def __load_data(self, user_group_id):
67 ugroup_repo_perms = UserGroupRepoToPerm.query()\
68 ugroup_repo_perms = UserGroupRepoToPerm.query()\
68 .options(joinedload(UserGroupRepoToPerm.permission))\
69 .options(joinedload(UserGroupRepoToPerm.permission))\
69 .options(joinedload(UserGroupRepoToPerm.repository))\
70 .options(joinedload(UserGroupRepoToPerm.repository))\
70 .filter(UserGroupRepoToPerm.users_group_id == user_group_id)\
71 .filter(UserGroupRepoToPerm.users_group_id == user_group_id)\
71 .all()
72 .all()
72
73
73 for gr in ugroup_repo_perms:
74 for gr in ugroup_repo_perms:
74 c.users_group.permissions['repositories'][gr.repository.repo_name] \
75 c.users_group.permissions['repositories'][gr.repository.repo_name] \
75 = gr.permission.permission_name
76 = gr.permission.permission_name
76
77
77 ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
78 ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
78 .options(joinedload(UserGroupRepoGroupToPerm.permission))\
79 .options(joinedload(UserGroupRepoGroupToPerm.permission))\
79 .options(joinedload(UserGroupRepoGroupToPerm.group))\
80 .options(joinedload(UserGroupRepoGroupToPerm.group))\
80 .filter(UserGroupRepoGroupToPerm.users_group_id == user_group_id)\
81 .filter(UserGroupRepoGroupToPerm.users_group_id == user_group_id)\
81 .all()
82 .all()
82
83
83 for gr in ugroup_group_perms:
84 for gr in ugroup_group_perms:
84 c.users_group.permissions['repositories_groups'][gr.group.group_name] \
85 c.users_group.permissions['repositories_groups'][gr.group.group_name] \
85 = gr.permission.permission_name
86 = gr.permission.permission_name
86
87
87 c.group_members_obj = sorted((x.user for x in c.users_group.members),
88 c.group_members_obj = sorted((x.user for x in c.users_group.members),
88 key=lambda u: u.username.lower())
89 key=lambda u: u.username.lower())
89
90
90 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
91 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
91 c.available_members = sorted(((x.user_id, x.username) for x in
92 c.available_members = sorted(((x.user_id, x.username) for x in
92 User.query().all()),
93 User.query().all()),
93 key=lambda u: u[1].lower())
94 key=lambda u: u[1].lower())
94 repo_model = RepoModel()
95 repo_model = RepoModel()
95 c.users_array = repo_model.get_users_js()
96 c.users_array = repo_model.get_users_js()
96
97
97 # commented out due to not now supporting assignment for user group
98 # commented out due to not now supporting assignment for user group
98 # on user group
99 # on user group
99 c.users_groups_array = "[]" # repo_model.get_users_groups_js()
100 c.users_groups_array = "[]" # repo_model.get_users_groups_js()
100 c.available_permissions = config['available_permissions']
101 c.available_permissions = config['available_permissions']
101
102
102 def __load_defaults(self, user_group_id):
103 def __load_defaults(self, user_group_id):
103 """
104 """
104 Load defaults settings for edit, and update
105 Load defaults settings for edit, and update
105
106
106 :param user_group_id:
107 :param user_group_id:
107 """
108 """
108 user_group = UserGroup.get_or_404(user_group_id)
109 user_group = UserGroup.get_or_404(user_group_id)
109 data = user_group.get_dict()
110 data = user_group.get_dict()
110
111
111 ug_model = UserGroupModel()
112 ug_model = UserGroupModel()
112
113
113 data.update({
114 data.update({
114 'create_repo_perm': ug_model.has_perm(user_group,
115 'create_repo_perm': ug_model.has_perm(user_group,
115 'hg.create.repository'),
116 'hg.create.repository'),
117 'create_user_group_perm': ug_model.has_perm(user_group,
118 'hg.usergroup.create.true'),
116 'fork_repo_perm': ug_model.has_perm(user_group,
119 'fork_repo_perm': ug_model.has_perm(user_group,
117 'hg.fork.repository'),
120 'hg.fork.repository'),
118 })
121 })
119
122
120 # fill user group users
123 # fill user group users
121 for p in user_group.user_user_group_to_perm:
124 for p in user_group.user_user_group_to_perm:
122 data.update({'u_perm_%s' % p.user.username:
125 data.update({'u_perm_%s' % p.user.username:
123 p.permission.permission_name})
126 p.permission.permission_name})
124
127
125 return data
128 return data
126
129
127 def index(self, format='html'):
130 def index(self, format='html'):
128 """GET /users_groups: All items in the collection"""
131 """GET /users_groups: All items in the collection"""
129 # url('users_groups')
132 # url('users_groups')
130
133
131 group_iter = UserGroupList(UserGroup().query().all(),
134 group_iter = UserGroupList(UserGroup().query().all(),
132 perm_set=['usergroup.admin'])
135 perm_set=['usergroup.admin'])
133 sk = lambda g: g.users_group_name
136 sk = lambda g: g.users_group_name
134 c.users_groups_list = sorted(group_iter, key=sk)
137 c.users_groups_list = sorted(group_iter, key=sk)
135 return render('admin/users_groups/users_groups.html')
138 return render('admin/users_groups/users_groups.html')
136
139
137 @HasPermissionAllDecorator('hg.admin')
140 @HasPermissionAllDecorator('hg.admin')
138 def create(self):
141 def create(self):
139 """POST /users_groups: Create a new item"""
142 """POST /users_groups: Create a new item"""
140 # url('users_groups')
143 # url('users_groups')
141
144
142 users_group_form = UserGroupForm()()
145 users_group_form = UserGroupForm()()
143 try:
146 try:
144 form_result = users_group_form.to_python(dict(request.POST))
147 form_result = users_group_form.to_python(dict(request.POST))
145 UserGroupModel().create(name=form_result['users_group_name'],
148 UserGroupModel().create(name=form_result['users_group_name'],
146 owner=self.rhodecode_user.user_id,
149 owner=self.rhodecode_user.user_id,
147 active=form_result['users_group_active'])
150 active=form_result['users_group_active'])
148
151
149 gr = form_result['users_group_name']
152 gr = form_result['users_group_name']
150 action_logger(self.rhodecode_user,
153 action_logger(self.rhodecode_user,
151 'admin_created_users_group:%s' % gr,
154 'admin_created_users_group:%s' % gr,
152 None, self.ip_addr, self.sa)
155 None, self.ip_addr, self.sa)
153 h.flash(_('Created user group %s') % gr, category='success')
156 h.flash(_('Created user group %s') % gr, category='success')
154 Session().commit()
157 Session().commit()
155 except formencode.Invalid, errors:
158 except formencode.Invalid, errors:
156 return htmlfill.render(
159 return htmlfill.render(
157 render('admin/users_groups/users_group_add.html'),
160 render('admin/users_groups/users_group_add.html'),
158 defaults=errors.value,
161 defaults=errors.value,
159 errors=errors.error_dict or {},
162 errors=errors.error_dict or {},
160 prefix_error=False,
163 prefix_error=False,
161 encoding="UTF-8")
164 encoding="UTF-8")
162 except Exception:
165 except Exception:
163 log.error(traceback.format_exc())
166 log.error(traceback.format_exc())
164 h.flash(_('Error occurred during creation of user group %s') \
167 h.flash(_('Error occurred during creation of user group %s') \
165 % request.POST.get('users_group_name'), category='error')
168 % request.POST.get('users_group_name'), category='error')
166
169
167 return redirect(url('users_groups'))
170 return redirect(url('users_groups'))
168
171
169 @HasPermissionAllDecorator('hg.admin')
172 @HasPermissionAllDecorator('hg.admin')
170 def new(self, format='html'):
173 def new(self, format='html'):
171 """GET /users_groups/new: Form to create a new item"""
174 """GET /users_groups/new: Form to create a new item"""
172 # url('new_users_group')
175 # url('new_users_group')
173 return render('admin/users_groups/users_group_add.html')
176 return render('admin/users_groups/users_group_add.html')
174
177
175 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
178 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
176 def update(self, id):
179 def update(self, id):
177 """PUT /users_groups/id: Update an existing item"""
180 """PUT /users_groups/id: Update an existing item"""
178 # Forms posted to this method should contain a hidden field:
181 # Forms posted to this method should contain a hidden field:
179 # <input type="hidden" name="_method" value="PUT" />
182 # <input type="hidden" name="_method" value="PUT" />
180 # Or using helpers:
183 # Or using helpers:
181 # h.form(url('users_group', id=ID),
184 # h.form(url('users_group', id=ID),
182 # method='put')
185 # method='put')
183 # url('users_group', id=ID)
186 # url('users_group', id=ID)
184
187
185 c.users_group = UserGroup.get_or_404(id)
188 c.users_group = UserGroup.get_or_404(id)
186 self.__load_data(id)
189 self.__load_data(id)
187
190
188 available_members = [safe_unicode(x[0]) for x in c.available_members]
191 available_members = [safe_unicode(x[0]) for x in c.available_members]
189
192
190 users_group_form = UserGroupForm(edit=True,
193 users_group_form = UserGroupForm(edit=True,
191 old_data=c.users_group.get_dict(),
194 old_data=c.users_group.get_dict(),
192 available_members=available_members)()
195 available_members=available_members)()
193
196
194 try:
197 try:
195 form_result = users_group_form.to_python(request.POST)
198 form_result = users_group_form.to_python(request.POST)
196 UserGroupModel().update(c.users_group, form_result)
199 UserGroupModel().update(c.users_group, form_result)
197 gr = form_result['users_group_name']
200 gr = form_result['users_group_name']
198 action_logger(self.rhodecode_user,
201 action_logger(self.rhodecode_user,
199 'admin_updated_users_group:%s' % gr,
202 'admin_updated_users_group:%s' % gr,
200 None, self.ip_addr, self.sa)
203 None, self.ip_addr, self.sa)
201 h.flash(_('Updated user group %s') % gr, category='success')
204 h.flash(_('Updated user group %s') % gr, category='success')
202 Session().commit()
205 Session().commit()
203 except formencode.Invalid, errors:
206 except formencode.Invalid, errors:
204 ug_model = UserGroupModel()
207 ug_model = UserGroupModel()
205 defaults = errors.value
208 defaults = errors.value
206 e = errors.error_dict or {}
209 e = errors.error_dict or {}
207 defaults.update({
210 defaults.update({
208 'create_repo_perm': ug_model.has_perm(id,
211 'create_repo_perm': ug_model.has_perm(id,
209 'hg.create.repository'),
212 'hg.create.repository'),
210 'fork_repo_perm': ug_model.has_perm(id,
213 'fork_repo_perm': ug_model.has_perm(id,
211 'hg.fork.repository'),
214 'hg.fork.repository'),
212 '_method': 'put'
215 '_method': 'put'
213 })
216 })
214
217
215 return htmlfill.render(
218 return htmlfill.render(
216 render('admin/users_groups/users_group_edit.html'),
219 render('admin/users_groups/users_group_edit.html'),
217 defaults=defaults,
220 defaults=defaults,
218 errors=e,
221 errors=e,
219 prefix_error=False,
222 prefix_error=False,
220 encoding="UTF-8")
223 encoding="UTF-8")
221 except Exception:
224 except Exception:
222 log.error(traceback.format_exc())
225 log.error(traceback.format_exc())
223 h.flash(_('Error occurred during update of user group %s') \
226 h.flash(_('Error occurred during update of user group %s') \
224 % request.POST.get('users_group_name'), category='error')
227 % request.POST.get('users_group_name'), category='error')
225
228
226 return redirect(url('edit_users_group', id=id))
229 return redirect(url('edit_users_group', id=id))
227
230
228 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
231 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
229 def delete(self, id):
232 def delete(self, id):
230 """DELETE /users_groups/id: Delete an existing item"""
233 """DELETE /users_groups/id: Delete an existing item"""
231 # Forms posted to this method should contain a hidden field:
234 # Forms posted to this method should contain a hidden field:
232 # <input type="hidden" name="_method" value="DELETE" />
235 # <input type="hidden" name="_method" value="DELETE" />
233 # Or using helpers:
236 # Or using helpers:
234 # h.form(url('users_group', id=ID),
237 # h.form(url('users_group', id=ID),
235 # method='delete')
238 # method='delete')
236 # url('users_group', id=ID)
239 # url('users_group', id=ID)
237 usr_gr = UserGroup.get_or_404(id)
240 usr_gr = UserGroup.get_or_404(id)
238 try:
241 try:
239 UserGroupModel().delete(usr_gr)
242 UserGroupModel().delete(usr_gr)
240 Session().commit()
243 Session().commit()
241 h.flash(_('Successfully deleted user group'), category='success')
244 h.flash(_('Successfully deleted user group'), category='success')
242 except UserGroupsAssignedException, e:
245 except UserGroupsAssignedException, e:
243 h.flash(e, category='error')
246 h.flash(e, category='error')
244 except Exception:
247 except Exception:
245 log.error(traceback.format_exc())
248 log.error(traceback.format_exc())
246 h.flash(_('An error occurred during deletion of user group'),
249 h.flash(_('An error occurred during deletion of user group'),
247 category='error')
250 category='error')
248 return redirect(url('users_groups'))
251 return redirect(url('users_groups'))
249
252
250 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
253 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
251 def set_user_group_perm_member(self, id):
254 def set_user_group_perm_member(self, id):
252 """
255 """
253 grant permission for given usergroup
256 grant permission for given usergroup
254
257
255 :param id:
258 :param id:
256 """
259 """
257 user_group = UserGroup.get_or_404(id)
260 user_group = UserGroup.get_or_404(id)
258 form = UserGroupPermsForm()().to_python(request.POST)
261 form = UserGroupPermsForm()().to_python(request.POST)
259
262
260 # set the permissions !
263 # set the permissions !
261 UserGroupModel()._update_permissions(user_group, form['perms_new'],
264 UserGroupModel()._update_permissions(user_group, form['perms_new'],
262 form['perms_updates'])
265 form['perms_updates'])
263 #TODO: implement this
266 #TODO: implement this
264 #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions',
267 #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions',
265 # repo_name, self.ip_addr, self.sa)
268 # repo_name, self.ip_addr, self.sa)
266 Session().commit()
269 Session().commit()
267 h.flash(_('User Group permissions updated'), category='success')
270 h.flash(_('User Group permissions updated'), category='success')
268 return redirect(url('edit_users_group', id=id))
271 return redirect(url('edit_users_group', id=id))
269
272
270 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
273 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
271 def delete_user_group_perm_member(self, id):
274 def delete_user_group_perm_member(self, id):
272 """
275 """
273 DELETE an existing repository group permission user
276 DELETE an existing repository group permission user
274
277
275 :param group_name:
278 :param group_name:
276 """
279 """
277 try:
280 try:
278 obj_type = request.POST.get('obj_type')
281 obj_type = request.POST.get('obj_type')
279 obj_id = None
282 obj_id = None
280 if obj_type == 'user':
283 if obj_type == 'user':
281 obj_id = safe_int(request.POST.get('user_id'))
284 obj_id = safe_int(request.POST.get('user_id'))
282 elif obj_type == 'user_group':
285 elif obj_type == 'user_group':
283 obj_id = safe_int(request.POST.get('user_group_id'))
286 obj_id = safe_int(request.POST.get('user_group_id'))
284
287
285 if not c.rhodecode_user.is_admin:
288 if not c.rhodecode_user.is_admin:
286 if obj_type == 'user' and c.rhodecode_user.user_id == obj_id:
289 if obj_type == 'user' and c.rhodecode_user.user_id == obj_id:
287 msg = _('Cannot revoke permission for yourself as admin')
290 msg = _('Cannot revoke permission for yourself as admin')
288 h.flash(msg, category='warning')
291 h.flash(msg, category='warning')
289 raise Exception('revoke admin permission on self')
292 raise Exception('revoke admin permission on self')
290 if obj_type == 'user':
293 if obj_type == 'user':
291 UserGroupModel().revoke_user_permission(user_group=id,
294 UserGroupModel().revoke_user_permission(user_group=id,
292 user=obj_id)
295 user=obj_id)
293 elif obj_type == 'user_group':
296 elif obj_type == 'user_group':
294 pass
297 pass
295 Session().commit()
298 Session().commit()
296 except Exception:
299 except Exception:
297 log.error(traceback.format_exc())
300 log.error(traceback.format_exc())
298 h.flash(_('An error occurred during revoking of permission'),
301 h.flash(_('An error occurred during revoking of permission'),
299 category='error')
302 category='error')
300 raise HTTPInternalServerError()
303 raise HTTPInternalServerError()
301
304
302 def show(self, id, format='html'):
305 def show(self, id, format='html'):
303 """GET /users_groups/id: Show a specific item"""
306 """GET /users_groups/id: Show a specific item"""
304 # url('users_group', id=ID)
307 # url('users_group', id=ID)
305
308
306 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
309 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
307 def edit(self, id, format='html'):
310 def edit(self, id, format='html'):
308 """GET /users_groups/id/edit: Form to edit an existing item"""
311 """GET /users_groups/id/edit: Form to edit an existing item"""
309 # url('edit_users_group', id=ID)
312 # url('edit_users_group', id=ID)
310
313
311 c.users_group = UserGroup.get_or_404(id)
314 c.users_group = UserGroup.get_or_404(id)
312 self.__load_data(id)
315 self.__load_data(id)
313
316
314 defaults = self.__load_defaults(id)
317 defaults = self.__load_defaults(id)
315
318
316 return htmlfill.render(
319 return htmlfill.render(
317 render('admin/users_groups/users_group_edit.html'),
320 render('admin/users_groups/users_group_edit.html'),
318 defaults=defaults,
321 defaults=defaults,
319 encoding="UTF-8",
322 encoding="UTF-8",
320 force_defaults=False
323 force_defaults=False
321 )
324 )
322
325
323 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
326 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
324 def update_perm(self, id):
327 def update_perm(self, id):
325 """PUT /users_perm/id: Update an existing item"""
328 """PUT /users_perm/id: Update an existing item"""
326 # url('users_group_perm', id=ID, method='put')
329 # url('users_group_perm', id=ID, method='put')
327
330
328 users_group = UserGroup.get_or_404(id)
331 users_group = UserGroup.get_or_404(id)
329 grant_create_perm = str2bool(request.POST.get('create_repo_perm'))
330 grant_fork_perm = str2bool(request.POST.get('fork_repo_perm'))
331 inherit_perms = str2bool(request.POST.get('inherit_default_permissions'))
332
333 usergroup_model = UserGroupModel()
334
332
335 try:
333 try:
334 form = CustomDefaultPermissionsForm()()
335 form_result = form.to_python(request.POST)
336
337 inherit_perms = form_result['inherit_default_permissions']
336 users_group.inherit_default_permissions = inherit_perms
338 users_group.inherit_default_permissions = inherit_perms
337 Session().add(users_group)
339 Session().add(users_group)
340 usergroup_model = UserGroupModel()
338
341
339 if grant_create_perm:
342 defs = UserGroupToPerm.query()\
340 usergroup_model.revoke_perm(id, 'hg.create.none')
343 .filter(UserGroupToPerm.users_group == users_group)\
341 usergroup_model.grant_perm(id, 'hg.create.repository')
344 .all()
342 h.flash(_("Granted 'repository create' permission to user group"),
345 for ug in defs:
343 category='success')
346 Session().delete(ug)
344 else:
345 usergroup_model.revoke_perm(id, 'hg.create.repository')
346 usergroup_model.grant_perm(id, 'hg.create.none')
347 h.flash(_("Revoked 'repository create' permission to user group"),
348 category='success')
349
347
350 if grant_fork_perm:
348 if form_result['create_repo_perm']:
351 usergroup_model.revoke_perm(id, 'hg.fork.none')
349 usergroup_model.grant_perm(id, 'hg.create.repository')
352 usergroup_model.grant_perm(id, 'hg.fork.repository')
350 else:
353 h.flash(_("Granted 'repository fork' permission to user group"),
351 usergroup_model.grant_perm(id, 'hg.create.none')
354 category='success')
352 if form_result['create_user_group_perm']:
353 usergroup_model.grant_perm(id, 'hg.usergroup.create.true')
355 else:
354 else:
356 usergroup_model.revoke_perm(id, 'hg.fork.repository')
355 usergroup_model.grant_perm(id, 'hg.usergroup.create.false')
356 if form_result['fork_repo_perm']:
357 usergroup_model.grant_perm(id, 'hg.fork.repository')
358 else:
357 usergroup_model.grant_perm(id, 'hg.fork.none')
359 usergroup_model.grant_perm(id, 'hg.fork.none')
358 h.flash(_("Revoked 'repository fork' permission to user group"),
359 category='success')
360
360
361 h.flash(_("Updated permissions"), category='success')
361 Session().commit()
362 Session().commit()
362 except Exception:
363 except Exception:
363 log.error(traceback.format_exc())
364 log.error(traceback.format_exc())
364 h.flash(_('An error occurred during permissions saving'),
365 h.flash(_('An error occurred during permissions saving'),
365 category='error')
366 category='error')
366
367
367 return redirect(url('edit_users_group', id=id))
368 return redirect(url('edit_users_group', id=id))
@@ -1,406 +1,421 b''
1 """ this is forms validation classes
1 """ this is forms validation classes
2 http://formencode.org/module-formencode.validators.html
2 http://formencode.org/module-formencode.validators.html
3 for list off all availible validators
3 for list off all availible validators
4
4
5 we can create our own validators
5 we can create our own validators
6
6
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 pre_validators [] These validators will be applied before the schema
8 pre_validators [] These validators will be applied before the schema
9 chained_validators [] These validators will be applied after the schema
9 chained_validators [] These validators will be applied after the schema
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14
14
15
15
16 <name> = formencode.validators.<name of validator>
16 <name> = formencode.validators.<name of validator>
17 <name> must equal form name
17 <name> must equal form name
18 list=[1,2,3,4,5]
18 list=[1,2,3,4,5]
19 for SELECT use formencode.All(OneOf(list), Int())
19 for SELECT use formencode.All(OneOf(list), Int())
20
20
21 """
21 """
22 import logging
22 import logging
23
23
24 import formencode
24 import formencode
25 from formencode import All
25 from formencode import All
26
26
27 from pylons.i18n.translation import _
27 from pylons.i18n.translation import _
28
28
29 from rhodecode.model import validators as v
29 from rhodecode.model import validators as v
30 from rhodecode import BACKENDS
30 from rhodecode import BACKENDS
31
31
32 log = logging.getLogger(__name__)
32 log = logging.getLogger(__name__)
33
33
34
34
35 class LoginForm(formencode.Schema):
35 class LoginForm(formencode.Schema):
36 allow_extra_fields = True
36 allow_extra_fields = True
37 filter_extra_fields = True
37 filter_extra_fields = True
38 username = v.UnicodeString(
38 username = v.UnicodeString(
39 strip=True,
39 strip=True,
40 min=1,
40 min=1,
41 not_empty=True,
41 not_empty=True,
42 messages={
42 messages={
43 'empty': _(u'Please enter a login'),
43 'empty': _(u'Please enter a login'),
44 'tooShort': _(u'Enter a value %(min)i characters long or more')}
44 'tooShort': _(u'Enter a value %(min)i characters long or more')}
45 )
45 )
46
46
47 password = v.UnicodeString(
47 password = v.UnicodeString(
48 strip=False,
48 strip=False,
49 min=3,
49 min=3,
50 not_empty=True,
50 not_empty=True,
51 messages={
51 messages={
52 'empty': _(u'Please enter a password'),
52 'empty': _(u'Please enter a password'),
53 'tooShort': _(u'Enter %(min)i characters or more')}
53 'tooShort': _(u'Enter %(min)i characters or more')}
54 )
54 )
55
55
56 remember = v.StringBoolean(if_missing=False)
56 remember = v.StringBoolean(if_missing=False)
57
57
58 chained_validators = [v.ValidAuth()]
58 chained_validators = [v.ValidAuth()]
59
59
60
60
61 def UserForm(edit=False, old_data={}):
61 def UserForm(edit=False, old_data={}):
62 class _UserForm(formencode.Schema):
62 class _UserForm(formencode.Schema):
63 allow_extra_fields = True
63 allow_extra_fields = True
64 filter_extra_fields = True
64 filter_extra_fields = True
65 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
65 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
66 v.ValidUsername(edit, old_data))
66 v.ValidUsername(edit, old_data))
67 if edit:
67 if edit:
68 new_password = All(
68 new_password = All(
69 v.ValidPassword(),
69 v.ValidPassword(),
70 v.UnicodeString(strip=False, min=6, not_empty=False)
70 v.UnicodeString(strip=False, min=6, not_empty=False)
71 )
71 )
72 password_confirmation = All(
72 password_confirmation = All(
73 v.ValidPassword(),
73 v.ValidPassword(),
74 v.UnicodeString(strip=False, min=6, not_empty=False),
74 v.UnicodeString(strip=False, min=6, not_empty=False),
75 )
75 )
76 admin = v.StringBoolean(if_missing=False)
76 admin = v.StringBoolean(if_missing=False)
77 else:
77 else:
78 password = All(
78 password = All(
79 v.ValidPassword(),
79 v.ValidPassword(),
80 v.UnicodeString(strip=False, min=6, not_empty=True)
80 v.UnicodeString(strip=False, min=6, not_empty=True)
81 )
81 )
82 password_confirmation = All(
82 password_confirmation = All(
83 v.ValidPassword(),
83 v.ValidPassword(),
84 v.UnicodeString(strip=False, min=6, not_empty=False)
84 v.UnicodeString(strip=False, min=6, not_empty=False)
85 )
85 )
86
86
87 active = v.StringBoolean(if_missing=False)
87 active = v.StringBoolean(if_missing=False)
88 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
88 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
89 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
89 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
90 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
90 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
91
91
92 chained_validators = [v.ValidPasswordsMatch()]
92 chained_validators = [v.ValidPasswordsMatch()]
93
93
94 return _UserForm
94 return _UserForm
95
95
96
96
97 def UserGroupForm(edit=False, old_data={}, available_members=[]):
97 def UserGroupForm(edit=False, old_data={}, available_members=[]):
98 class _UserGroupForm(formencode.Schema):
98 class _UserGroupForm(formencode.Schema):
99 allow_extra_fields = True
99 allow_extra_fields = True
100 filter_extra_fields = True
100 filter_extra_fields = True
101
101
102 users_group_name = All(
102 users_group_name = All(
103 v.UnicodeString(strip=True, min=1, not_empty=True),
103 v.UnicodeString(strip=True, min=1, not_empty=True),
104 v.ValidUserGroup(edit, old_data)
104 v.ValidUserGroup(edit, old_data)
105 )
105 )
106
106
107 users_group_active = v.StringBoolean(if_missing=False)
107 users_group_active = v.StringBoolean(if_missing=False)
108
108
109 if edit:
109 if edit:
110 users_group_members = v.OneOf(
110 users_group_members = v.OneOf(
111 available_members, hideList=False, testValueList=True,
111 available_members, hideList=False, testValueList=True,
112 if_missing=None, not_empty=False
112 if_missing=None, not_empty=False
113 )
113 )
114
114
115 return _UserGroupForm
115 return _UserGroupForm
116
116
117
117
118 def ReposGroupForm(edit=False, old_data={}, available_groups=[],
118 def ReposGroupForm(edit=False, old_data={}, available_groups=[],
119 can_create_in_root=False):
119 can_create_in_root=False):
120 class _ReposGroupForm(formencode.Schema):
120 class _ReposGroupForm(formencode.Schema):
121 allow_extra_fields = True
121 allow_extra_fields = True
122 filter_extra_fields = False
122 filter_extra_fields = False
123
123
124 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
124 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
125 v.SlugifyName())
125 v.SlugifyName())
126 group_description = v.UnicodeString(strip=True, min=1,
126 group_description = v.UnicodeString(strip=True, min=1,
127 not_empty=False)
127 not_empty=False)
128 if edit:
128 if edit:
129 #FIXME: do a special check that we cannot move a group to one of
129 #FIXME: do a special check that we cannot move a group to one of
130 #it's children
130 #it's children
131 pass
131 pass
132 group_parent_id = All(v.CanCreateGroup(can_create_in_root),
132 group_parent_id = All(v.CanCreateGroup(can_create_in_root),
133 v.OneOf(available_groups, hideList=False,
133 v.OneOf(available_groups, hideList=False,
134 testValueList=True,
134 testValueList=True,
135 if_missing=None, not_empty=True))
135 if_missing=None, not_empty=True))
136 enable_locking = v.StringBoolean(if_missing=False)
136 enable_locking = v.StringBoolean(if_missing=False)
137 chained_validators = [v.ValidReposGroup(edit, old_data)]
137 chained_validators = [v.ValidReposGroup(edit, old_data)]
138
138
139 return _ReposGroupForm
139 return _ReposGroupForm
140
140
141
141
142 def RegisterForm(edit=False, old_data={}):
142 def RegisterForm(edit=False, old_data={}):
143 class _RegisterForm(formencode.Schema):
143 class _RegisterForm(formencode.Schema):
144 allow_extra_fields = True
144 allow_extra_fields = True
145 filter_extra_fields = True
145 filter_extra_fields = True
146 username = All(
146 username = All(
147 v.ValidUsername(edit, old_data),
147 v.ValidUsername(edit, old_data),
148 v.UnicodeString(strip=True, min=1, not_empty=True)
148 v.UnicodeString(strip=True, min=1, not_empty=True)
149 )
149 )
150 password = All(
150 password = All(
151 v.ValidPassword(),
151 v.ValidPassword(),
152 v.UnicodeString(strip=False, min=6, not_empty=True)
152 v.UnicodeString(strip=False, min=6, not_empty=True)
153 )
153 )
154 password_confirmation = All(
154 password_confirmation = All(
155 v.ValidPassword(),
155 v.ValidPassword(),
156 v.UnicodeString(strip=False, min=6, not_empty=True)
156 v.UnicodeString(strip=False, min=6, not_empty=True)
157 )
157 )
158 active = v.StringBoolean(if_missing=False)
158 active = v.StringBoolean(if_missing=False)
159 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
159 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
160 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
160 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
161 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
161 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
162
162
163 chained_validators = [v.ValidPasswordsMatch()]
163 chained_validators = [v.ValidPasswordsMatch()]
164
164
165 return _RegisterForm
165 return _RegisterForm
166
166
167
167
168 def PasswordResetForm():
168 def PasswordResetForm():
169 class _PasswordResetForm(formencode.Schema):
169 class _PasswordResetForm(formencode.Schema):
170 allow_extra_fields = True
170 allow_extra_fields = True
171 filter_extra_fields = True
171 filter_extra_fields = True
172 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
172 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
173 return _PasswordResetForm
173 return _PasswordResetForm
174
174
175
175
176 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
176 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
177 repo_groups=[], landing_revs=[]):
177 repo_groups=[], landing_revs=[]):
178 class _RepoForm(formencode.Schema):
178 class _RepoForm(formencode.Schema):
179 allow_extra_fields = True
179 allow_extra_fields = True
180 filter_extra_fields = False
180 filter_extra_fields = False
181 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
181 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
182 v.SlugifyName())
182 v.SlugifyName())
183 repo_group = All(v.CanWriteGroup(old_data),
183 repo_group = All(v.CanWriteGroup(old_data),
184 v.OneOf(repo_groups, hideList=True))
184 v.OneOf(repo_groups, hideList=True))
185 repo_type = v.OneOf(supported_backends)
185 repo_type = v.OneOf(supported_backends)
186 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
186 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
187 repo_private = v.StringBoolean(if_missing=False)
187 repo_private = v.StringBoolean(if_missing=False)
188 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
188 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
189 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
189 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
190
190
191 repo_enable_statistics = v.StringBoolean(if_missing=False)
191 repo_enable_statistics = v.StringBoolean(if_missing=False)
192 repo_enable_downloads = v.StringBoolean(if_missing=False)
192 repo_enable_downloads = v.StringBoolean(if_missing=False)
193 repo_enable_locking = v.StringBoolean(if_missing=False)
193 repo_enable_locking = v.StringBoolean(if_missing=False)
194
194
195 if edit:
195 if edit:
196 #this is repo owner
196 #this is repo owner
197 user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
197 user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
198
198
199 chained_validators = [v.ValidCloneUri(),
199 chained_validators = [v.ValidCloneUri(),
200 v.ValidRepoName(edit, old_data)]
200 v.ValidRepoName(edit, old_data)]
201 return _RepoForm
201 return _RepoForm
202
202
203
203
204 def RepoPermsForm():
204 def RepoPermsForm():
205 class _RepoPermsForm(formencode.Schema):
205 class _RepoPermsForm(formencode.Schema):
206 allow_extra_fields = True
206 allow_extra_fields = True
207 filter_extra_fields = False
207 filter_extra_fields = False
208 chained_validators = [v.ValidPerms(type_='repo')]
208 chained_validators = [v.ValidPerms(type_='repo')]
209 return _RepoPermsForm
209 return _RepoPermsForm
210
210
211
211
212 def RepoGroupPermsForm():
212 def RepoGroupPermsForm():
213 class _RepoGroupPermsForm(formencode.Schema):
213 class _RepoGroupPermsForm(formencode.Schema):
214 allow_extra_fields = True
214 allow_extra_fields = True
215 filter_extra_fields = False
215 filter_extra_fields = False
216 recursive = v.StringBoolean(if_missing=False)
216 recursive = v.StringBoolean(if_missing=False)
217 chained_validators = [v.ValidPerms(type_='repo_group')]
217 chained_validators = [v.ValidPerms(type_='repo_group')]
218 return _RepoGroupPermsForm
218 return _RepoGroupPermsForm
219
219
220
220
221 def UserGroupPermsForm():
221 def UserGroupPermsForm():
222 class _UserPermsForm(formencode.Schema):
222 class _UserPermsForm(formencode.Schema):
223 allow_extra_fields = True
223 allow_extra_fields = True
224 filter_extra_fields = False
224 filter_extra_fields = False
225 chained_validators = [v.ValidPerms(type_='user_group')]
225 chained_validators = [v.ValidPerms(type_='user_group')]
226 return _UserPermsForm
226 return _UserPermsForm
227
227
228
228
229 def RepoFieldForm():
229 def RepoFieldForm():
230 class _RepoFieldForm(formencode.Schema):
230 class _RepoFieldForm(formencode.Schema):
231 filter_extra_fields = True
231 filter_extra_fields = True
232 allow_extra_fields = True
232 allow_extra_fields = True
233
233
234 new_field_key = All(v.FieldKey(),
234 new_field_key = All(v.FieldKey(),
235 v.UnicodeString(strip=True, min=3, not_empty=True))
235 v.UnicodeString(strip=True, min=3, not_empty=True))
236 new_field_value = v.UnicodeString(not_empty=False, if_missing='')
236 new_field_value = v.UnicodeString(not_empty=False, if_missing='')
237 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
237 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
238 if_missing='str')
238 if_missing='str')
239 new_field_label = v.UnicodeString(not_empty=False)
239 new_field_label = v.UnicodeString(not_empty=False)
240 new_field_desc = v.UnicodeString(not_empty=False)
240 new_field_desc = v.UnicodeString(not_empty=False)
241
241
242 return _RepoFieldForm
242 return _RepoFieldForm
243
243
244
244
245 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
245 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
246 repo_groups=[], landing_revs=[]):
246 repo_groups=[], landing_revs=[]):
247 class _RepoForkForm(formencode.Schema):
247 class _RepoForkForm(formencode.Schema):
248 allow_extra_fields = True
248 allow_extra_fields = True
249 filter_extra_fields = False
249 filter_extra_fields = False
250 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
250 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
251 v.SlugifyName())
251 v.SlugifyName())
252 repo_group = All(v.CanWriteGroup(),
252 repo_group = All(v.CanWriteGroup(),
253 v.OneOf(repo_groups, hideList=True))
253 v.OneOf(repo_groups, hideList=True))
254 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
254 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
255 description = v.UnicodeString(strip=True, min=1, not_empty=True)
255 description = v.UnicodeString(strip=True, min=1, not_empty=True)
256 private = v.StringBoolean(if_missing=False)
256 private = v.StringBoolean(if_missing=False)
257 copy_permissions = v.StringBoolean(if_missing=False)
257 copy_permissions = v.StringBoolean(if_missing=False)
258 update_after_clone = v.StringBoolean(if_missing=False)
258 update_after_clone = v.StringBoolean(if_missing=False)
259 fork_parent_id = v.UnicodeString()
259 fork_parent_id = v.UnicodeString()
260 chained_validators = [v.ValidForkName(edit, old_data)]
260 chained_validators = [v.ValidForkName(edit, old_data)]
261 landing_rev = v.OneOf(landing_revs, hideList=True)
261 landing_rev = v.OneOf(landing_revs, hideList=True)
262
262
263 return _RepoForkForm
263 return _RepoForkForm
264
264
265
265
266 def ApplicationSettingsForm():
266 def ApplicationSettingsForm():
267 class _ApplicationSettingsForm(formencode.Schema):
267 class _ApplicationSettingsForm(formencode.Schema):
268 allow_extra_fields = True
268 allow_extra_fields = True
269 filter_extra_fields = False
269 filter_extra_fields = False
270 rhodecode_title = v.UnicodeString(strip=True, min=1, not_empty=True)
270 rhodecode_title = v.UnicodeString(strip=True, min=1, not_empty=True)
271 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
271 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
272 rhodecode_ga_code = v.UnicodeString(strip=True, min=1, not_empty=False)
272 rhodecode_ga_code = v.UnicodeString(strip=True, min=1, not_empty=False)
273
273
274 return _ApplicationSettingsForm
274 return _ApplicationSettingsForm
275
275
276
276
277 def ApplicationVisualisationForm():
277 def ApplicationVisualisationForm():
278 class _ApplicationVisualisationForm(formencode.Schema):
278 class _ApplicationVisualisationForm(formencode.Schema):
279 allow_extra_fields = True
279 allow_extra_fields = True
280 filter_extra_fields = False
280 filter_extra_fields = False
281 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
281 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
282 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
282 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
283 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
283 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
284
284
285 rhodecode_lightweight_dashboard = v.StringBoolean(if_missing=False)
285 rhodecode_lightweight_dashboard = v.StringBoolean(if_missing=False)
286 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
286 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
287 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
287 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
288
288
289 return _ApplicationVisualisationForm
289 return _ApplicationVisualisationForm
290
290
291
291
292 def ApplicationUiSettingsForm():
292 def ApplicationUiSettingsForm():
293 class _ApplicationUiSettingsForm(formencode.Schema):
293 class _ApplicationUiSettingsForm(formencode.Schema):
294 allow_extra_fields = True
294 allow_extra_fields = True
295 filter_extra_fields = False
295 filter_extra_fields = False
296 web_push_ssl = v.StringBoolean(if_missing=False)
296 web_push_ssl = v.StringBoolean(if_missing=False)
297 paths_root_path = All(
297 paths_root_path = All(
298 v.ValidPath(),
298 v.ValidPath(),
299 v.UnicodeString(strip=True, min=1, not_empty=True)
299 v.UnicodeString(strip=True, min=1, not_empty=True)
300 )
300 )
301 hooks_changegroup_update = v.StringBoolean(if_missing=False)
301 hooks_changegroup_update = v.StringBoolean(if_missing=False)
302 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
302 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
303 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
303 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
304 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
304 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
305
305
306 extensions_largefiles = v.StringBoolean(if_missing=False)
306 extensions_largefiles = v.StringBoolean(if_missing=False)
307 extensions_hgsubversion = v.StringBoolean(if_missing=False)
307 extensions_hgsubversion = v.StringBoolean(if_missing=False)
308 extensions_hggit = v.StringBoolean(if_missing=False)
308 extensions_hggit = v.StringBoolean(if_missing=False)
309
309
310 return _ApplicationUiSettingsForm
310 return _ApplicationUiSettingsForm
311
311
312
312
313 def DefaultPermissionsForm(repo_perms_choices, group_perms_choices,
313 def DefaultPermissionsForm(repo_perms_choices, group_perms_choices,
314 user_group_perms_choices, create_choices,
314 user_group_perms_choices, create_choices,
315 repo_group_create_choices, user_group_create_choices,
315 repo_group_create_choices, user_group_create_choices,
316 fork_choices, register_choices):
316 fork_choices, register_choices):
317 class _DefaultPermissionsForm(formencode.Schema):
317 class _DefaultPermissionsForm(formencode.Schema):
318 allow_extra_fields = True
318 allow_extra_fields = True
319 filter_extra_fields = True
319 filter_extra_fields = True
320 overwrite_default_repo = v.StringBoolean(if_missing=False)
320 overwrite_default_repo = v.StringBoolean(if_missing=False)
321 overwrite_default_group = v.StringBoolean(if_missing=False)
321 overwrite_default_group = v.StringBoolean(if_missing=False)
322 overwrite_default_user_group = v.StringBoolean(if_missing=False)
322 overwrite_default_user_group = v.StringBoolean(if_missing=False)
323 anonymous = v.StringBoolean(if_missing=False)
323 anonymous = v.StringBoolean(if_missing=False)
324 default_repo_perm = v.OneOf(repo_perms_choices)
324 default_repo_perm = v.OneOf(repo_perms_choices)
325 default_group_perm = v.OneOf(group_perms_choices)
325 default_group_perm = v.OneOf(group_perms_choices)
326 default_user_group_perm = v.OneOf(user_group_perms_choices)
326 default_user_group_perm = v.OneOf(user_group_perms_choices)
327
327
328 default_repo_create = v.OneOf(create_choices)
328 default_repo_create = v.OneOf(create_choices)
329 default_user_group_create = v.OneOf(user_group_create_choices)
329 default_user_group_create = v.OneOf(user_group_create_choices)
330 #default_repo_group_create = v.OneOf(repo_group_create_choices) #not impl. yet
330 #default_repo_group_create = v.OneOf(repo_group_create_choices) #not impl. yet
331 default_fork = v.OneOf(fork_choices)
331 default_fork = v.OneOf(fork_choices)
332
332
333 default_register = v.OneOf(register_choices)
333 default_register = v.OneOf(register_choices)
334 return _DefaultPermissionsForm
334 return _DefaultPermissionsForm
335
335
336
336
337 def CustomDefaultPermissionsForm():
338 class _CustomDefaultPermissionsForm(formencode.Schema):
339 filter_extra_fields = True
340 allow_extra_fields = True
341 inherit_default_permissions = v.StringBoolean(if_missing=False)
342
343 create_repo_perm = v.StringBoolean(if_missing=False)
344 create_user_group_perm = v.StringBoolean(if_missing=False)
345 #create_repo_group_perm Impl. later
346
347 fork_repo_perm = v.StringBoolean(if_missing=False)
348
349 return _CustomDefaultPermissionsForm
350
351
337 def DefaultsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
352 def DefaultsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
338 class _DefaultsForm(formencode.Schema):
353 class _DefaultsForm(formencode.Schema):
339 allow_extra_fields = True
354 allow_extra_fields = True
340 filter_extra_fields = True
355 filter_extra_fields = True
341 default_repo_type = v.OneOf(supported_backends)
356 default_repo_type = v.OneOf(supported_backends)
342 default_repo_private = v.StringBoolean(if_missing=False)
357 default_repo_private = v.StringBoolean(if_missing=False)
343 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
358 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
344 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
359 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
345 default_repo_enable_locking = v.StringBoolean(if_missing=False)
360 default_repo_enable_locking = v.StringBoolean(if_missing=False)
346
361
347 return _DefaultsForm
362 return _DefaultsForm
348
363
349
364
350 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices,
365 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices,
351 tls_kind_choices):
366 tls_kind_choices):
352 class _LdapSettingsForm(formencode.Schema):
367 class _LdapSettingsForm(formencode.Schema):
353 allow_extra_fields = True
368 allow_extra_fields = True
354 filter_extra_fields = True
369 filter_extra_fields = True
355 #pre_validators = [LdapLibValidator]
370 #pre_validators = [LdapLibValidator]
356 ldap_active = v.StringBoolean(if_missing=False)
371 ldap_active = v.StringBoolean(if_missing=False)
357 ldap_host = v.UnicodeString(strip=True,)
372 ldap_host = v.UnicodeString(strip=True,)
358 ldap_port = v.Number(strip=True,)
373 ldap_port = v.Number(strip=True,)
359 ldap_tls_kind = v.OneOf(tls_kind_choices)
374 ldap_tls_kind = v.OneOf(tls_kind_choices)
360 ldap_tls_reqcert = v.OneOf(tls_reqcert_choices)
375 ldap_tls_reqcert = v.OneOf(tls_reqcert_choices)
361 ldap_dn_user = v.UnicodeString(strip=True,)
376 ldap_dn_user = v.UnicodeString(strip=True,)
362 ldap_dn_pass = v.UnicodeString(strip=True,)
377 ldap_dn_pass = v.UnicodeString(strip=True,)
363 ldap_base_dn = v.UnicodeString(strip=True,)
378 ldap_base_dn = v.UnicodeString(strip=True,)
364 ldap_filter = v.UnicodeString(strip=True,)
379 ldap_filter = v.UnicodeString(strip=True,)
365 ldap_search_scope = v.OneOf(search_scope_choices)
380 ldap_search_scope = v.OneOf(search_scope_choices)
366 ldap_attr_login = v.AttrLoginValidator()(not_empty=True)
381 ldap_attr_login = v.AttrLoginValidator()(not_empty=True)
367 ldap_attr_firstname = v.UnicodeString(strip=True,)
382 ldap_attr_firstname = v.UnicodeString(strip=True,)
368 ldap_attr_lastname = v.UnicodeString(strip=True,)
383 ldap_attr_lastname = v.UnicodeString(strip=True,)
369 ldap_attr_email = v.UnicodeString(strip=True,)
384 ldap_attr_email = v.UnicodeString(strip=True,)
370
385
371 return _LdapSettingsForm
386 return _LdapSettingsForm
372
387
373
388
374 def UserExtraEmailForm():
389 def UserExtraEmailForm():
375 class _UserExtraEmailForm(formencode.Schema):
390 class _UserExtraEmailForm(formencode.Schema):
376 email = All(v.UniqSystemEmail(), v.Email(not_empty=True))
391 email = All(v.UniqSystemEmail(), v.Email(not_empty=True))
377 return _UserExtraEmailForm
392 return _UserExtraEmailForm
378
393
379
394
380 def UserExtraIpForm():
395 def UserExtraIpForm():
381 class _UserExtraIpForm(formencode.Schema):
396 class _UserExtraIpForm(formencode.Schema):
382 ip = v.ValidIp()(not_empty=True)
397 ip = v.ValidIp()(not_empty=True)
383 return _UserExtraIpForm
398 return _UserExtraIpForm
384
399
385
400
386 def PullRequestForm(repo_id):
401 def PullRequestForm(repo_id):
387 class _PullRequestForm(formencode.Schema):
402 class _PullRequestForm(formencode.Schema):
388 allow_extra_fields = True
403 allow_extra_fields = True
389 filter_extra_fields = True
404 filter_extra_fields = True
390
405
391 user = v.UnicodeString(strip=True, required=True)
406 user = v.UnicodeString(strip=True, required=True)
392 org_repo = v.UnicodeString(strip=True, required=True)
407 org_repo = v.UnicodeString(strip=True, required=True)
393 org_ref = v.UnicodeString(strip=True, required=True)
408 org_ref = v.UnicodeString(strip=True, required=True)
394 other_repo = v.UnicodeString(strip=True, required=True)
409 other_repo = v.UnicodeString(strip=True, required=True)
395 other_ref = v.UnicodeString(strip=True, required=True)
410 other_ref = v.UnicodeString(strip=True, required=True)
396 revisions = All(#v.NotReviewedRevisions(repo_id)(),
411 revisions = All(#v.NotReviewedRevisions(repo_id)(),
397 v.UniqueList(not_empty=True))
412 v.UniqueList(not_empty=True))
398 review_members = v.UniqueList(not_empty=True)
413 review_members = v.UniqueList(not_empty=True)
399
414
400 pullrequest_title = v.UnicodeString(strip=True, required=True, min=3)
415 pullrequest_title = v.UnicodeString(strip=True, required=True, min=3)
401 pullrequest_desc = v.UnicodeString(strip=True, required=False)
416 pullrequest_desc = v.UnicodeString(strip=True, required=False)
402
417
403 ancestor_rev = v.UnicodeString(strip=True, required=True)
418 ancestor_rev = v.UnicodeString(strip=True, required=True)
404 merge_rev = v.UnicodeString(strip=True, required=True)
419 merge_rev = v.UnicodeString(strip=True, required=True)
405
420
406 return _PullRequestForm
421 return _PullRequestForm
@@ -1,777 +1,782 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.user
3 rhodecode.model.user
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 users model for RhodeCode
6 users model for RhodeCode
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import itertools
28 import itertools
29 import collections
29 import collections
30 from pylons import url
30 from pylons import url
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32
32
33 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.exc import DatabaseError
34 from sqlalchemy.orm import joinedload
34 from sqlalchemy.orm import joinedload
35
35
36 from rhodecode.lib.utils2 import safe_unicode, generate_api_key
36 from rhodecode.lib.utils2 import safe_unicode, generate_api_key
37 from rhodecode.lib.caching_query import FromCache
37 from rhodecode.lib.caching_query import FromCache
38 from rhodecode.model import BaseModel
38 from rhodecode.model import BaseModel
39 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
39 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
40 UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \
40 UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \
41 Notification, RepoGroup, UserRepoGroupToPerm, UserGroupRepoGroupToPerm, \
41 Notification, RepoGroup, UserRepoGroupToPerm, UserGroupRepoGroupToPerm, \
42 UserEmailMap, UserIpMap
42 UserEmailMap, UserIpMap
43 from rhodecode.lib.exceptions import DefaultUserException, \
43 from rhodecode.lib.exceptions import DefaultUserException, \
44 UserOwnsReposException
44 UserOwnsReposException
45 from rhodecode.model.meta import Session
45 from rhodecode.model.meta import Session
46
46
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50 PERM_WEIGHTS = Permission.PERM_WEIGHTS
50 PERM_WEIGHTS = Permission.PERM_WEIGHTS
51
51
52
52
53 class UserModel(BaseModel):
53 class UserModel(BaseModel):
54 cls = User
54 cls = User
55
55
56 def get(self, user_id, cache=False):
56 def get(self, user_id, cache=False):
57 user = self.sa.query(User)
57 user = self.sa.query(User)
58 if cache:
58 if cache:
59 user = user.options(FromCache("sql_cache_short",
59 user = user.options(FromCache("sql_cache_short",
60 "get_user_%s" % user_id))
60 "get_user_%s" % user_id))
61 return user.get(user_id)
61 return user.get(user_id)
62
62
63 def get_user(self, user):
63 def get_user(self, user):
64 return self._get_user(user)
64 return self._get_user(user)
65
65
66 def get_by_username(self, username, cache=False, case_insensitive=False):
66 def get_by_username(self, username, cache=False, case_insensitive=False):
67
67
68 if case_insensitive:
68 if case_insensitive:
69 user = self.sa.query(User).filter(User.username.ilike(username))
69 user = self.sa.query(User).filter(User.username.ilike(username))
70 else:
70 else:
71 user = self.sa.query(User)\
71 user = self.sa.query(User)\
72 .filter(User.username == username)
72 .filter(User.username == username)
73 if cache:
73 if cache:
74 user = user.options(FromCache("sql_cache_short",
74 user = user.options(FromCache("sql_cache_short",
75 "get_user_%s" % username))
75 "get_user_%s" % username))
76 return user.scalar()
76 return user.scalar()
77
77
78 def get_by_email(self, email, cache=False, case_insensitive=False):
78 def get_by_email(self, email, cache=False, case_insensitive=False):
79 return User.get_by_email(email, case_insensitive, cache)
79 return User.get_by_email(email, case_insensitive, cache)
80
80
81 def get_by_api_key(self, api_key, cache=False):
81 def get_by_api_key(self, api_key, cache=False):
82 return User.get_by_api_key(api_key, cache)
82 return User.get_by_api_key(api_key, cache)
83
83
84 def create(self, form_data):
84 def create(self, form_data):
85 from rhodecode.lib.auth import get_crypt_password
85 from rhodecode.lib.auth import get_crypt_password
86 try:
86 try:
87 new_user = User()
87 new_user = User()
88 for k, v in form_data.items():
88 for k, v in form_data.items():
89 if k == 'password':
89 if k == 'password':
90 v = get_crypt_password(v)
90 v = get_crypt_password(v)
91 if k == 'firstname':
91 if k == 'firstname':
92 k = 'name'
92 k = 'name'
93 setattr(new_user, k, v)
93 setattr(new_user, k, v)
94
94
95 new_user.api_key = generate_api_key(form_data['username'])
95 new_user.api_key = generate_api_key(form_data['username'])
96 self.sa.add(new_user)
96 self.sa.add(new_user)
97 return new_user
97 return new_user
98 except Exception:
98 except Exception:
99 log.error(traceback.format_exc())
99 log.error(traceback.format_exc())
100 raise
100 raise
101
101
102 def create_or_update(self, username, password, email, firstname='',
102 def create_or_update(self, username, password, email, firstname='',
103 lastname='', active=True, admin=False, ldap_dn=None):
103 lastname='', active=True, admin=False, ldap_dn=None):
104 """
104 """
105 Creates a new instance if not found, or updates current one
105 Creates a new instance if not found, or updates current one
106
106
107 :param username:
107 :param username:
108 :param password:
108 :param password:
109 :param email:
109 :param email:
110 :param active:
110 :param active:
111 :param firstname:
111 :param firstname:
112 :param lastname:
112 :param lastname:
113 :param active:
113 :param active:
114 :param admin:
114 :param admin:
115 :param ldap_dn:
115 :param ldap_dn:
116 """
116 """
117
117
118 from rhodecode.lib.auth import get_crypt_password
118 from rhodecode.lib.auth import get_crypt_password
119
119
120 log.debug('Checking for %s account in RhodeCode database' % username)
120 log.debug('Checking for %s account in RhodeCode database' % username)
121 user = User.get_by_username(username, case_insensitive=True)
121 user = User.get_by_username(username, case_insensitive=True)
122 if user is None:
122 if user is None:
123 log.debug('creating new user %s' % username)
123 log.debug('creating new user %s' % username)
124 new_user = User()
124 new_user = User()
125 edit = False
125 edit = False
126 else:
126 else:
127 log.debug('updating user %s' % username)
127 log.debug('updating user %s' % username)
128 new_user = user
128 new_user = user
129 edit = True
129 edit = True
130
130
131 try:
131 try:
132 new_user.username = username
132 new_user.username = username
133 new_user.admin = admin
133 new_user.admin = admin
134 # set password only if creating an user or password is changed
134 # set password only if creating an user or password is changed
135 if not edit or user.password != password:
135 if not edit or user.password != password:
136 new_user.password = get_crypt_password(password)
136 new_user.password = get_crypt_password(password)
137 new_user.api_key = generate_api_key(username)
137 new_user.api_key = generate_api_key(username)
138 new_user.email = email
138 new_user.email = email
139 new_user.active = active
139 new_user.active = active
140 new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None
140 new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None
141 new_user.name = firstname
141 new_user.name = firstname
142 new_user.lastname = lastname
142 new_user.lastname = lastname
143 self.sa.add(new_user)
143 self.sa.add(new_user)
144 return new_user
144 return new_user
145 except (DatabaseError,):
145 except (DatabaseError,):
146 log.error(traceback.format_exc())
146 log.error(traceback.format_exc())
147 raise
147 raise
148
148
149 def create_for_container_auth(self, username, attrs):
149 def create_for_container_auth(self, username, attrs):
150 """
150 """
151 Creates the given user if it's not already in the database
151 Creates the given user if it's not already in the database
152
152
153 :param username:
153 :param username:
154 :param attrs:
154 :param attrs:
155 """
155 """
156 if self.get_by_username(username, case_insensitive=True) is None:
156 if self.get_by_username(username, case_insensitive=True) is None:
157
157
158 # autogenerate email for container account without one
158 # autogenerate email for container account without one
159 generate_email = lambda usr: '%s@container_auth.account' % usr
159 generate_email = lambda usr: '%s@container_auth.account' % usr
160
160
161 try:
161 try:
162 new_user = User()
162 new_user = User()
163 new_user.username = username
163 new_user.username = username
164 new_user.password = None
164 new_user.password = None
165 new_user.api_key = generate_api_key(username)
165 new_user.api_key = generate_api_key(username)
166 new_user.email = attrs['email']
166 new_user.email = attrs['email']
167 new_user.active = attrs.get('active', True)
167 new_user.active = attrs.get('active', True)
168 new_user.name = attrs['name'] or generate_email(username)
168 new_user.name = attrs['name'] or generate_email(username)
169 new_user.lastname = attrs['lastname']
169 new_user.lastname = attrs['lastname']
170
170
171 self.sa.add(new_user)
171 self.sa.add(new_user)
172 return new_user
172 return new_user
173 except (DatabaseError,):
173 except (DatabaseError,):
174 log.error(traceback.format_exc())
174 log.error(traceback.format_exc())
175 self.sa.rollback()
175 self.sa.rollback()
176 raise
176 raise
177 log.debug('User %s already exists. Skipping creation of account'
177 log.debug('User %s already exists. Skipping creation of account'
178 ' for container auth.', username)
178 ' for container auth.', username)
179 return None
179 return None
180
180
181 def create_ldap(self, username, password, user_dn, attrs):
181 def create_ldap(self, username, password, user_dn, attrs):
182 """
182 """
183 Checks if user is in database, if not creates this user marked
183 Checks if user is in database, if not creates this user marked
184 as ldap user
184 as ldap user
185
185
186 :param username:
186 :param username:
187 :param password:
187 :param password:
188 :param user_dn:
188 :param user_dn:
189 :param attrs:
189 :param attrs:
190 """
190 """
191 from rhodecode.lib.auth import get_crypt_password
191 from rhodecode.lib.auth import get_crypt_password
192 log.debug('Checking for such ldap account in RhodeCode database')
192 log.debug('Checking for such ldap account in RhodeCode database')
193 if self.get_by_username(username, case_insensitive=True) is None:
193 if self.get_by_username(username, case_insensitive=True) is None:
194
194
195 # autogenerate email for ldap account without one
195 # autogenerate email for ldap account without one
196 generate_email = lambda usr: '%s@ldap.account' % usr
196 generate_email = lambda usr: '%s@ldap.account' % usr
197
197
198 try:
198 try:
199 new_user = User()
199 new_user = User()
200 username = username.lower()
200 username = username.lower()
201 # add ldap account always lowercase
201 # add ldap account always lowercase
202 new_user.username = username
202 new_user.username = username
203 new_user.password = get_crypt_password(password)
203 new_user.password = get_crypt_password(password)
204 new_user.api_key = generate_api_key(username)
204 new_user.api_key = generate_api_key(username)
205 new_user.email = attrs['email'] or generate_email(username)
205 new_user.email = attrs['email'] or generate_email(username)
206 new_user.active = attrs.get('active', True)
206 new_user.active = attrs.get('active', True)
207 new_user.ldap_dn = safe_unicode(user_dn)
207 new_user.ldap_dn = safe_unicode(user_dn)
208 new_user.name = attrs['name']
208 new_user.name = attrs['name']
209 new_user.lastname = attrs['lastname']
209 new_user.lastname = attrs['lastname']
210
210
211 self.sa.add(new_user)
211 self.sa.add(new_user)
212 return new_user
212 return new_user
213 except (DatabaseError,):
213 except (DatabaseError,):
214 log.error(traceback.format_exc())
214 log.error(traceback.format_exc())
215 self.sa.rollback()
215 self.sa.rollback()
216 raise
216 raise
217 log.debug('this %s user exists skipping creation of ldap account',
217 log.debug('this %s user exists skipping creation of ldap account',
218 username)
218 username)
219 return None
219 return None
220
220
221 def create_registration(self, form_data):
221 def create_registration(self, form_data):
222 from rhodecode.model.notification import NotificationModel
222 from rhodecode.model.notification import NotificationModel
223
223
224 try:
224 try:
225 form_data['admin'] = False
225 form_data['admin'] = False
226 new_user = self.create(form_data)
226 new_user = self.create(form_data)
227
227
228 self.sa.add(new_user)
228 self.sa.add(new_user)
229 self.sa.flush()
229 self.sa.flush()
230
230
231 # notification to admins
231 # notification to admins
232 subject = _('New user registration')
232 subject = _('New user registration')
233 body = ('New user registration\n'
233 body = ('New user registration\n'
234 '---------------------\n'
234 '---------------------\n'
235 '- Username: %s\n'
235 '- Username: %s\n'
236 '- Full Name: %s\n'
236 '- Full Name: %s\n'
237 '- Email: %s\n')
237 '- Email: %s\n')
238 body = body % (new_user.username, new_user.full_name,
238 body = body % (new_user.username, new_user.full_name,
239 new_user.email)
239 new_user.email)
240 edit_url = url('edit_user', id=new_user.user_id, qualified=True)
240 edit_url = url('edit_user', id=new_user.user_id, qualified=True)
241 kw = {'registered_user_url': edit_url}
241 kw = {'registered_user_url': edit_url}
242 NotificationModel().create(created_by=new_user, subject=subject,
242 NotificationModel().create(created_by=new_user, subject=subject,
243 body=body, recipients=None,
243 body=body, recipients=None,
244 type_=Notification.TYPE_REGISTRATION,
244 type_=Notification.TYPE_REGISTRATION,
245 email_kwargs=kw)
245 email_kwargs=kw)
246
246
247 except Exception:
247 except Exception:
248 log.error(traceback.format_exc())
248 log.error(traceback.format_exc())
249 raise
249 raise
250
250
251 def update(self, user_id, form_data, skip_attrs=[]):
251 def update(self, user_id, form_data, skip_attrs=[]):
252 from rhodecode.lib.auth import get_crypt_password
252 from rhodecode.lib.auth import get_crypt_password
253 try:
253 try:
254 user = self.get(user_id, cache=False)
254 user = self.get(user_id, cache=False)
255 if user.username == 'default':
255 if user.username == 'default':
256 raise DefaultUserException(
256 raise DefaultUserException(
257 _("You can't Edit this user since it's"
257 _("You can't Edit this user since it's"
258 " crucial for entire application"))
258 " crucial for entire application"))
259
259
260 for k, v in form_data.items():
260 for k, v in form_data.items():
261 if k in skip_attrs:
261 if k in skip_attrs:
262 continue
262 continue
263 if k == 'new_password' and v:
263 if k == 'new_password' and v:
264 user.password = get_crypt_password(v)
264 user.password = get_crypt_password(v)
265 user.api_key = generate_api_key(user.username)
265 user.api_key = generate_api_key(user.username)
266 else:
266 else:
267 if k == 'firstname':
267 if k == 'firstname':
268 k = 'name'
268 k = 'name'
269 setattr(user, k, v)
269 setattr(user, k, v)
270 self.sa.add(user)
270 self.sa.add(user)
271 except Exception:
271 except Exception:
272 log.error(traceback.format_exc())
272 log.error(traceback.format_exc())
273 raise
273 raise
274
274
275 def update_user(self, user, **kwargs):
275 def update_user(self, user, **kwargs):
276 from rhodecode.lib.auth import get_crypt_password
276 from rhodecode.lib.auth import get_crypt_password
277 try:
277 try:
278 user = self._get_user(user)
278 user = self._get_user(user)
279 if user.username == 'default':
279 if user.username == 'default':
280 raise DefaultUserException(
280 raise DefaultUserException(
281 _("You can't Edit this user since it's"
281 _("You can't Edit this user since it's"
282 " crucial for entire application")
282 " crucial for entire application")
283 )
283 )
284
284
285 for k, v in kwargs.items():
285 for k, v in kwargs.items():
286 if k == 'password' and v:
286 if k == 'password' and v:
287 v = get_crypt_password(v)
287 v = get_crypt_password(v)
288 user.api_key = generate_api_key(user.username)
288 user.api_key = generate_api_key(user.username)
289
289
290 setattr(user, k, v)
290 setattr(user, k, v)
291 self.sa.add(user)
291 self.sa.add(user)
292 return user
292 return user
293 except Exception:
293 except Exception:
294 log.error(traceback.format_exc())
294 log.error(traceback.format_exc())
295 raise
295 raise
296
296
297 def delete(self, user):
297 def delete(self, user):
298 user = self._get_user(user)
298 user = self._get_user(user)
299
299
300 try:
300 try:
301 if user.username == 'default':
301 if user.username == 'default':
302 raise DefaultUserException(
302 raise DefaultUserException(
303 _(u"You can't remove this user since it's"
303 _(u"You can't remove this user since it's"
304 " crucial for entire application")
304 " crucial for entire application")
305 )
305 )
306 if user.repositories:
306 if user.repositories:
307 repos = [x.repo_name for x in user.repositories]
307 repos = [x.repo_name for x in user.repositories]
308 raise UserOwnsReposException(
308 raise UserOwnsReposException(
309 _(u'user "%s" still owns %s repositories and cannot be '
309 _(u'user "%s" still owns %s repositories and cannot be '
310 'removed. Switch owners or remove those repositories. %s')
310 'removed. Switch owners or remove those repositories. %s')
311 % (user.username, len(repos), ', '.join(repos))
311 % (user.username, len(repos), ', '.join(repos))
312 )
312 )
313 self.sa.delete(user)
313 self.sa.delete(user)
314 except Exception:
314 except Exception:
315 log.error(traceback.format_exc())
315 log.error(traceback.format_exc())
316 raise
316 raise
317
317
318 def reset_password_link(self, data):
318 def reset_password_link(self, data):
319 from rhodecode.lib.celerylib import tasks, run_task
319 from rhodecode.lib.celerylib import tasks, run_task
320 from rhodecode.model.notification import EmailNotificationModel
320 from rhodecode.model.notification import EmailNotificationModel
321 user_email = data['email']
321 user_email = data['email']
322 try:
322 try:
323 user = User.get_by_email(user_email)
323 user = User.get_by_email(user_email)
324 if user:
324 if user:
325 log.debug('password reset user found %s' % user)
325 log.debug('password reset user found %s' % user)
326 link = url('reset_password_confirmation', key=user.api_key,
326 link = url('reset_password_confirmation', key=user.api_key,
327 qualified=True)
327 qualified=True)
328 reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
328 reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
329 body = EmailNotificationModel().get_email_tmpl(reg_type,
329 body = EmailNotificationModel().get_email_tmpl(reg_type,
330 **{'user': user.short_contact,
330 **{'user': user.short_contact,
331 'reset_url': link})
331 'reset_url': link})
332 log.debug('sending email')
332 log.debug('sending email')
333 run_task(tasks.send_email, user_email,
333 run_task(tasks.send_email, user_email,
334 _("Password reset link"), body, body)
334 _("Password reset link"), body, body)
335 log.info('send new password mail to %s' % user_email)
335 log.info('send new password mail to %s' % user_email)
336 else:
336 else:
337 log.debug("password reset email %s not found" % user_email)
337 log.debug("password reset email %s not found" % user_email)
338 except Exception:
338 except Exception:
339 log.error(traceback.format_exc())
339 log.error(traceback.format_exc())
340 return False
340 return False
341
341
342 return True
342 return True
343
343
344 def reset_password(self, data):
344 def reset_password(self, data):
345 from rhodecode.lib.celerylib import tasks, run_task
345 from rhodecode.lib.celerylib import tasks, run_task
346 from rhodecode.lib import auth
346 from rhodecode.lib import auth
347 user_email = data['email']
347 user_email = data['email']
348 try:
348 try:
349 try:
349 try:
350 user = User.get_by_email(user_email)
350 user = User.get_by_email(user_email)
351 new_passwd = auth.PasswordGenerator().gen_password(8,
351 new_passwd = auth.PasswordGenerator().gen_password(8,
352 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
352 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
353 if user:
353 if user:
354 user.password = auth.get_crypt_password(new_passwd)
354 user.password = auth.get_crypt_password(new_passwd)
355 user.api_key = auth.generate_api_key(user.username)
355 user.api_key = auth.generate_api_key(user.username)
356 Session().add(user)
356 Session().add(user)
357 Session().commit()
357 Session().commit()
358 log.info('change password for %s' % user_email)
358 log.info('change password for %s' % user_email)
359 if new_passwd is None:
359 if new_passwd is None:
360 raise Exception('unable to generate new password')
360 raise Exception('unable to generate new password')
361 except Exception:
361 except Exception:
362 log.error(traceback.format_exc())
362 log.error(traceback.format_exc())
363 Session().rollback()
363 Session().rollback()
364
364
365 run_task(tasks.send_email, user_email,
365 run_task(tasks.send_email, user_email,
366 _('Your new password'),
366 _('Your new password'),
367 _('Your new RhodeCode password:%s') % (new_passwd))
367 _('Your new RhodeCode password:%s') % (new_passwd))
368 log.info('send new password mail to %s' % user_email)
368 log.info('send new password mail to %s' % user_email)
369
369
370 except Exception:
370 except Exception:
371 log.error('Failed to update user password')
371 log.error('Failed to update user password')
372 log.error(traceback.format_exc())
372 log.error(traceback.format_exc())
373
373
374 return True
374 return True
375
375
376 def fill_data(self, auth_user, user_id=None, api_key=None):
376 def fill_data(self, auth_user, user_id=None, api_key=None):
377 """
377 """
378 Fetches auth_user by user_id,or api_key if present.
378 Fetches auth_user by user_id,or api_key if present.
379 Fills auth_user attributes with those taken from database.
379 Fills auth_user attributes with those taken from database.
380 Additionally set's is_authenitated if lookup fails
380 Additionally set's is_authenitated if lookup fails
381 present in database
381 present in database
382
382
383 :param auth_user: instance of user to set attributes
383 :param auth_user: instance of user to set attributes
384 :param user_id: user id to fetch by
384 :param user_id: user id to fetch by
385 :param api_key: api key to fetch by
385 :param api_key: api key to fetch by
386 """
386 """
387 if user_id is None and api_key is None:
387 if user_id is None and api_key is None:
388 raise Exception('You need to pass user_id or api_key')
388 raise Exception('You need to pass user_id or api_key')
389
389
390 try:
390 try:
391 if api_key:
391 if api_key:
392 dbuser = self.get_by_api_key(api_key)
392 dbuser = self.get_by_api_key(api_key)
393 else:
393 else:
394 dbuser = self.get(user_id)
394 dbuser = self.get(user_id)
395
395
396 if dbuser is not None and dbuser.active:
396 if dbuser is not None and dbuser.active:
397 log.debug('filling %s data' % dbuser)
397 log.debug('filling %s data' % dbuser)
398 for k, v in dbuser.get_dict().items():
398 for k, v in dbuser.get_dict().items():
399 setattr(auth_user, k, v)
399 setattr(auth_user, k, v)
400 else:
400 else:
401 return False
401 return False
402
402
403 except Exception:
403 except Exception:
404 log.error(traceback.format_exc())
404 log.error(traceback.format_exc())
405 auth_user.is_authenticated = False
405 auth_user.is_authenticated = False
406 return False
406 return False
407
407
408 return True
408 return True
409
409
410 def fill_perms(self, user, explicit=True, algo='higherwin'):
410 def fill_perms(self, user, explicit=True, algo='higherwin'):
411 """
411 """
412 Fills user permission attribute with permissions taken from database
412 Fills user permission attribute with permissions taken from database
413 works for permissions given for repositories, and for permissions that
413 works for permissions given for repositories, and for permissions that
414 are granted to groups
414 are granted to groups
415
415
416 :param user: user instance to fill his perms
416 :param user: user instance to fill his perms
417 :param explicit: In case there are permissions both for user and a group
417 :param explicit: In case there are permissions both for user and a group
418 that user is part of, explicit flag will defiine if user will
418 that user is part of, explicit flag will defiine if user will
419 explicitly override permissions from group, if it's False it will
419 explicitly override permissions from group, if it's False it will
420 make decision based on the algo
420 make decision based on the algo
421 :param algo: algorithm to decide what permission should be choose if
421 :param algo: algorithm to decide what permission should be choose if
422 it's multiple defined, eg user in two different groups. It also
422 it's multiple defined, eg user in two different groups. It also
423 decides if explicit flag is turned off how to specify the permission
423 decides if explicit flag is turned off how to specify the permission
424 for case when user is in a group + have defined separate permission
424 for case when user is in a group + have defined separate permission
425 """
425 """
426 RK = 'repositories'
426 RK = 'repositories'
427 GK = 'repositories_groups'
427 GK = 'repositories_groups'
428 UK = 'user_groups'
428 UK = 'user_groups'
429 GLOBAL = 'global'
429 GLOBAL = 'global'
430 user.permissions[RK] = {}
430 user.permissions[RK] = {}
431 user.permissions[GK] = {}
431 user.permissions[GK] = {}
432 user.permissions[UK] = {}
432 user.permissions[UK] = {}
433 user.permissions[GLOBAL] = set()
433 user.permissions[GLOBAL] = set()
434
434
435 def _choose_perm(new_perm, cur_perm):
435 def _choose_perm(new_perm, cur_perm):
436 new_perm_val = PERM_WEIGHTS[new_perm]
436 new_perm_val = PERM_WEIGHTS[new_perm]
437 cur_perm_val = PERM_WEIGHTS[cur_perm]
437 cur_perm_val = PERM_WEIGHTS[cur_perm]
438 if algo == 'higherwin':
438 if algo == 'higherwin':
439 if new_perm_val > cur_perm_val:
439 if new_perm_val > cur_perm_val:
440 return new_perm
440 return new_perm
441 return cur_perm
441 return cur_perm
442 elif algo == 'lowerwin':
442 elif algo == 'lowerwin':
443 if new_perm_val < cur_perm_val:
443 if new_perm_val < cur_perm_val:
444 return new_perm
444 return new_perm
445 return cur_perm
445 return cur_perm
446
446
447 #======================================================================
447 #======================================================================
448 # fetch default permissions
448 # fetch default permissions
449 #======================================================================
449 #======================================================================
450 default_user = User.get_by_username('default', cache=True)
450 default_user = User.get_by_username('default', cache=True)
451 default_user_id = default_user.user_id
451 default_user_id = default_user.user_id
452
452
453 default_repo_perms = Permission.get_default_perms(default_user_id)
453 default_repo_perms = Permission.get_default_perms(default_user_id)
454 default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
454 default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
455 default_user_group_perms = Permission.get_default_user_group_perms(default_user_id)
455 default_user_group_perms = Permission.get_default_user_group_perms(default_user_id)
456
456
457 if user.is_admin:
457 if user.is_admin:
458 #==================================================================
458 #==================================================================
459 # admin user have all default rights for repositories
459 # admin user have all default rights for repositories
460 # and groups set to admin
460 # and groups set to admin
461 #==================================================================
461 #==================================================================
462 user.permissions[GLOBAL].add('hg.admin')
462 user.permissions[GLOBAL].add('hg.admin')
463
463
464 # repositories
464 # repositories
465 for perm in default_repo_perms:
465 for perm in default_repo_perms:
466 r_k = perm.UserRepoToPerm.repository.repo_name
466 r_k = perm.UserRepoToPerm.repository.repo_name
467 p = 'repository.admin'
467 p = 'repository.admin'
468 user.permissions[RK][r_k] = p
468 user.permissions[RK][r_k] = p
469
469
470 # repository groups
470 # repository groups
471 for perm in default_repo_groups_perms:
471 for perm in default_repo_groups_perms:
472 rg_k = perm.UserRepoGroupToPerm.group.group_name
472 rg_k = perm.UserRepoGroupToPerm.group.group_name
473 p = 'group.admin'
473 p = 'group.admin'
474 user.permissions[GK][rg_k] = p
474 user.permissions[GK][rg_k] = p
475
475
476 # user groups
476 # user groups
477 for perm in default_user_group_perms:
477 for perm in default_user_group_perms:
478 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
478 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
479 p = 'usergroup.admin'
479 p = 'usergroup.admin'
480 user.permissions[UK][u_k] = p
480 user.permissions[UK][u_k] = p
481 return user
481 return user
482
482
483 #==================================================================
483 #==================================================================
484 # SET DEFAULTS GLOBAL, REPOS, REPOSITORY GROUPS
484 # SET DEFAULTS GLOBAL, REPOS, REPOSITORY GROUPS
485 #==================================================================
485 #==================================================================
486 uid = user.user_id
486 uid = user.user_id
487
487
488 # default global permissions taken fron the default user
488 # default global permissions taken fron the default user
489 default_global_perms = self.sa.query(UserToPerm)\
489 default_global_perms = self.sa.query(UserToPerm)\
490 .filter(UserToPerm.user_id == default_user_id)
490 .filter(UserToPerm.user_id == default_user_id)
491
491
492 for perm in default_global_perms:
492 for perm in default_global_perms:
493 user.permissions[GLOBAL].add(perm.permission.permission_name)
493 user.permissions[GLOBAL].add(perm.permission.permission_name)
494
494
495 # defaults for repositories, taken from default user
495 # defaults for repositories, taken from default user
496 for perm in default_repo_perms:
496 for perm in default_repo_perms:
497 r_k = perm.UserRepoToPerm.repository.repo_name
497 r_k = perm.UserRepoToPerm.repository.repo_name
498 if perm.Repository.private and not (perm.Repository.user_id == uid):
498 if perm.Repository.private and not (perm.Repository.user_id == uid):
499 # disable defaults for private repos,
499 # disable defaults for private repos,
500 p = 'repository.none'
500 p = 'repository.none'
501 elif perm.Repository.user_id == uid:
501 elif perm.Repository.user_id == uid:
502 # set admin if owner
502 # set admin if owner
503 p = 'repository.admin'
503 p = 'repository.admin'
504 else:
504 else:
505 p = perm.Permission.permission_name
505 p = perm.Permission.permission_name
506
506
507 user.permissions[RK][r_k] = p
507 user.permissions[RK][r_k] = p
508
508
509 # defaults for repository groups taken from default user permission
509 # defaults for repository groups taken from default user permission
510 # on given group
510 # on given group
511 for perm in default_repo_groups_perms:
511 for perm in default_repo_groups_perms:
512 rg_k = perm.UserRepoGroupToPerm.group.group_name
512 rg_k = perm.UserRepoGroupToPerm.group.group_name
513 p = perm.Permission.permission_name
513 p = perm.Permission.permission_name
514 user.permissions[GK][rg_k] = p
514 user.permissions[GK][rg_k] = p
515
515
516 # defaults for user groups taken from default user permission
516 # defaults for user groups taken from default user permission
517 # on given user group
517 # on given user group
518 for perm in default_user_group_perms:
518 for perm in default_user_group_perms:
519 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
519 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
520 p = perm.Permission.permission_name
520 p = perm.Permission.permission_name
521 user.permissions[UK][u_k] = p
521 user.permissions[UK][u_k] = p
522
522
523 #======================================================================
523 #======================================================================
524 # !! OVERRIDE GLOBALS !! with user permissions if any found
524 # !! OVERRIDE GLOBALS !! with user permissions if any found
525 #======================================================================
525 #======================================================================
526 # those can be configured from groups or users explicitly
526 # those can be configured from groups or users explicitly
527 _configurable = set(['hg.fork.none', 'hg.fork.repository',
527 _configurable = set([
528 'hg.create.none', 'hg.create.repository'])
528 'hg.fork.none', 'hg.fork.repository',
529 'hg.create.none', 'hg.create.repository',
530 'hg.usergroup.create.false', 'hg.usergroup.create.true'
531 ])
529
532
530 # USER GROUPS comes first
533 # USER GROUPS comes first
531 # user group global permissions
534 # user group global permissions
532 user_perms_from_users_groups = self.sa.query(UserGroupToPerm)\
535 user_perms_from_users_groups = self.sa.query(UserGroupToPerm)\
533 .options(joinedload(UserGroupToPerm.permission))\
536 .options(joinedload(UserGroupToPerm.permission))\
534 .join((UserGroupMember, UserGroupToPerm.users_group_id ==
537 .join((UserGroupMember, UserGroupToPerm.users_group_id ==
535 UserGroupMember.users_group_id))\
538 UserGroupMember.users_group_id))\
536 .filter(UserGroupMember.user_id == uid)\
539 .filter(UserGroupMember.user_id == uid)\
537 .order_by(UserGroupToPerm.users_group_id)\
540 .order_by(UserGroupToPerm.users_group_id)\
538 .all()
541 .all()
539 #need to group here by groups since user can be in more than one group
542 #need to group here by groups since user can be in more than one group
540 _grouped = [[x, list(y)] for x, y in
543 _grouped = [[x, list(y)] for x, y in
541 itertools.groupby(user_perms_from_users_groups,
544 itertools.groupby(user_perms_from_users_groups,
542 lambda x:x.users_group)]
545 lambda x:x.users_group)]
543 for gr, perms in _grouped:
546 for gr, perms in _grouped:
544 # since user can be in multiple groups iterate over them and
547 # since user can be in multiple groups iterate over them and
545 # select the lowest permissions first (more explicit)
548 # select the lowest permissions first (more explicit)
546 ##TODO: do this^^
549 ##TODO: do this^^
547 if not gr.inherit_default_permissions:
550 if not gr.inherit_default_permissions:
548 # NEED TO IGNORE all configurable permissions and
551 # NEED TO IGNORE all configurable permissions and
549 # replace them with explicitly set
552 # replace them with explicitly set
550 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
553 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
551 .difference(_configurable)
554 .difference(_configurable)
552 for perm in perms:
555 for perm in perms:
553 user.permissions[GLOBAL].add(perm.permission.permission_name)
556 user.permissions[GLOBAL].add(perm.permission.permission_name)
554
557
555 # user specific global permissions
558 # user specific global permissions
556 user_perms = self.sa.query(UserToPerm)\
559 user_perms = self.sa.query(UserToPerm)\
557 .options(joinedload(UserToPerm.permission))\
560 .options(joinedload(UserToPerm.permission))\
558 .filter(UserToPerm.user_id == uid).all()
561 .filter(UserToPerm.user_id == uid).all()
559
562
560 if not user.inherit_default_permissions:
563 if not user.inherit_default_permissions:
561 # NEED TO IGNORE all configurable permissions and
564 # NEED TO IGNORE all configurable permissions and
562 # replace them with explicitly set
565 # replace them with explicitly set
563 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
566 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
564 .difference(_configurable)
567 .difference(_configurable)
565
568
566 for perm in user_perms:
569 for perm in user_perms:
567 user.permissions[GLOBAL].add(perm.permission.permission_name)
570 user.permissions[GLOBAL].add(perm.permission.permission_name)
571 ## END GLOBAL PERMISSIONS
572
568
573
569 #======================================================================
574 #======================================================================
570 # !! PERMISSIONS FOR REPOSITORIES !!
575 # !! PERMISSIONS FOR REPOSITORIES !!
571 #======================================================================
576 #======================================================================
572 #======================================================================
577 #======================================================================
573 # check if user is part of user groups for this repository and
578 # check if user is part of user groups for this repository and
574 # fill in his permission from it. _choose_perm decides of which
579 # fill in his permission from it. _choose_perm decides of which
575 # permission should be selected based on selected method
580 # permission should be selected based on selected method
576 #======================================================================
581 #======================================================================
577
582
578 # user group for repositories permissions
583 # user group for repositories permissions
579 user_repo_perms_from_users_groups = \
584 user_repo_perms_from_users_groups = \
580 self.sa.query(UserGroupRepoToPerm, Permission, Repository,)\
585 self.sa.query(UserGroupRepoToPerm, Permission, Repository,)\
581 .join((Repository, UserGroupRepoToPerm.repository_id ==
586 .join((Repository, UserGroupRepoToPerm.repository_id ==
582 Repository.repo_id))\
587 Repository.repo_id))\
583 .join((Permission, UserGroupRepoToPerm.permission_id ==
588 .join((Permission, UserGroupRepoToPerm.permission_id ==
584 Permission.permission_id))\
589 Permission.permission_id))\
585 .join((UserGroupMember, UserGroupRepoToPerm.users_group_id ==
590 .join((UserGroupMember, UserGroupRepoToPerm.users_group_id ==
586 UserGroupMember.users_group_id))\
591 UserGroupMember.users_group_id))\
587 .filter(UserGroupMember.user_id == uid)\
592 .filter(UserGroupMember.user_id == uid)\
588 .all()
593 .all()
589
594
590 multiple_counter = collections.defaultdict(int)
595 multiple_counter = collections.defaultdict(int)
591 for perm in user_repo_perms_from_users_groups:
596 for perm in user_repo_perms_from_users_groups:
592 r_k = perm.UserGroupRepoToPerm.repository.repo_name
597 r_k = perm.UserGroupRepoToPerm.repository.repo_name
593 multiple_counter[r_k] += 1
598 multiple_counter[r_k] += 1
594 p = perm.Permission.permission_name
599 p = perm.Permission.permission_name
595 cur_perm = user.permissions[RK][r_k]
600 cur_perm = user.permissions[RK][r_k]
596
601
597 if perm.Repository.user_id == uid:
602 if perm.Repository.user_id == uid:
598 # set admin if owner
603 # set admin if owner
599 p = 'repository.admin'
604 p = 'repository.admin'
600 else:
605 else:
601 if multiple_counter[r_k] > 1:
606 if multiple_counter[r_k] > 1:
602 p = _choose_perm(p, cur_perm)
607 p = _choose_perm(p, cur_perm)
603 user.permissions[RK][r_k] = p
608 user.permissions[RK][r_k] = p
604
609
605 # user explicit permissions for repositories, overrides any specified
610 # user explicit permissions for repositories, overrides any specified
606 # by the group permission
611 # by the group permission
607 user_repo_perms = Permission.get_default_perms(uid)
612 user_repo_perms = Permission.get_default_perms(uid)
608 for perm in user_repo_perms:
613 for perm in user_repo_perms:
609 r_k = perm.UserRepoToPerm.repository.repo_name
614 r_k = perm.UserRepoToPerm.repository.repo_name
610 cur_perm = user.permissions[RK][r_k]
615 cur_perm = user.permissions[RK][r_k]
611 # set admin if owner
616 # set admin if owner
612 if perm.Repository.user_id == uid:
617 if perm.Repository.user_id == uid:
613 p = 'repository.admin'
618 p = 'repository.admin'
614 else:
619 else:
615 p = perm.Permission.permission_name
620 p = perm.Permission.permission_name
616 if not explicit:
621 if not explicit:
617 p = _choose_perm(p, cur_perm)
622 p = _choose_perm(p, cur_perm)
618 user.permissions[RK][r_k] = p
623 user.permissions[RK][r_k] = p
619
624
620 #======================================================================
625 #======================================================================
621 # !! PERMISSIONS FOR REPOSITORY GROUPS !!
626 # !! PERMISSIONS FOR REPOSITORY GROUPS !!
622 #======================================================================
627 #======================================================================
623 #======================================================================
628 #======================================================================
624 # check if user is part of user groups for this repository groups and
629 # check if user is part of user groups for this repository groups and
625 # fill in his permission from it. _choose_perm decides of which
630 # fill in his permission from it. _choose_perm decides of which
626 # permission should be selected based on selected method
631 # permission should be selected based on selected method
627 #======================================================================
632 #======================================================================
628 # user group for repo groups permissions
633 # user group for repo groups permissions
629 user_repo_group_perms_from_users_groups = \
634 user_repo_group_perms_from_users_groups = \
630 self.sa.query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\
635 self.sa.query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\
631 .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
636 .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
632 .join((Permission, UserGroupRepoGroupToPerm.permission_id
637 .join((Permission, UserGroupRepoGroupToPerm.permission_id
633 == Permission.permission_id))\
638 == Permission.permission_id))\
634 .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id
639 .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id
635 == UserGroupMember.users_group_id))\
640 == UserGroupMember.users_group_id))\
636 .filter(UserGroupMember.user_id == uid)\
641 .filter(UserGroupMember.user_id == uid)\
637 .all()
642 .all()
638
643
639 multiple_counter = collections.defaultdict(int)
644 multiple_counter = collections.defaultdict(int)
640 for perm in user_repo_group_perms_from_users_groups:
645 for perm in user_repo_group_perms_from_users_groups:
641 g_k = perm.UserGroupRepoGroupToPerm.group.group_name
646 g_k = perm.UserGroupRepoGroupToPerm.group.group_name
642 multiple_counter[g_k] += 1
647 multiple_counter[g_k] += 1
643 p = perm.Permission.permission_name
648 p = perm.Permission.permission_name
644 cur_perm = user.permissions[GK][g_k]
649 cur_perm = user.permissions[GK][g_k]
645 if multiple_counter[g_k] > 1:
650 if multiple_counter[g_k] > 1:
646 p = _choose_perm(p, cur_perm)
651 p = _choose_perm(p, cur_perm)
647 user.permissions[GK][g_k] = p
652 user.permissions[GK][g_k] = p
648
653
649 # user explicit permissions for repository groups
654 # user explicit permissions for repository groups
650 user_repo_groups_perms = Permission.get_default_group_perms(uid)
655 user_repo_groups_perms = Permission.get_default_group_perms(uid)
651 for perm in user_repo_groups_perms:
656 for perm in user_repo_groups_perms:
652 rg_k = perm.UserRepoGroupToPerm.group.group_name
657 rg_k = perm.UserRepoGroupToPerm.group.group_name
653 p = perm.Permission.permission_name
658 p = perm.Permission.permission_name
654 cur_perm = user.permissions[GK][rg_k]
659 cur_perm = user.permissions[GK][rg_k]
655 if not explicit:
660 if not explicit:
656 p = _choose_perm(p, cur_perm)
661 p = _choose_perm(p, cur_perm)
657 user.permissions[GK][rg_k] = p
662 user.permissions[GK][rg_k] = p
658
663
659 #======================================================================
664 #======================================================================
660 # !! PERMISSIONS FOR USER GROUPS !!
665 # !! PERMISSIONS FOR USER GROUPS !!
661 #======================================================================
666 #======================================================================
662 #user explicit permission for user groups
667 #user explicit permission for user groups
663 user_user_groups_perms = Permission.get_default_user_group_perms(uid)
668 user_user_groups_perms = Permission.get_default_user_group_perms(uid)
664 for perm in user_user_groups_perms:
669 for perm in user_user_groups_perms:
665 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
670 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
666 p = perm.Permission.permission_name
671 p = perm.Permission.permission_name
667 cur_perm = user.permissions[UK][u_k]
672 cur_perm = user.permissions[UK][u_k]
668 if not explicit:
673 if not explicit:
669 p = _choose_perm(p, cur_perm)
674 p = _choose_perm(p, cur_perm)
670 user.permissions[UK][u_k] = p
675 user.permissions[UK][u_k] = p
671
676
672 return user
677 return user
673
678
674 def has_perm(self, user, perm):
679 def has_perm(self, user, perm):
675 perm = self._get_perm(perm)
680 perm = self._get_perm(perm)
676 user = self._get_user(user)
681 user = self._get_user(user)
677
682
678 return UserToPerm.query().filter(UserToPerm.user == user)\
683 return UserToPerm.query().filter(UserToPerm.user == user)\
679 .filter(UserToPerm.permission == perm).scalar() is not None
684 .filter(UserToPerm.permission == perm).scalar() is not None
680
685
681 def grant_perm(self, user, perm):
686 def grant_perm(self, user, perm):
682 """
687 """
683 Grant user global permissions
688 Grant user global permissions
684
689
685 :param user:
690 :param user:
686 :param perm:
691 :param perm:
687 """
692 """
688 user = self._get_user(user)
693 user = self._get_user(user)
689 perm = self._get_perm(perm)
694 perm = self._get_perm(perm)
690 # if this permission is already granted skip it
695 # if this permission is already granted skip it
691 _perm = UserToPerm.query()\
696 _perm = UserToPerm.query()\
692 .filter(UserToPerm.user == user)\
697 .filter(UserToPerm.user == user)\
693 .filter(UserToPerm.permission == perm)\
698 .filter(UserToPerm.permission == perm)\
694 .scalar()
699 .scalar()
695 if _perm:
700 if _perm:
696 return
701 return
697 new = UserToPerm()
702 new = UserToPerm()
698 new.user = user
703 new.user = user
699 new.permission = perm
704 new.permission = perm
700 self.sa.add(new)
705 self.sa.add(new)
701
706
702 def revoke_perm(self, user, perm):
707 def revoke_perm(self, user, perm):
703 """
708 """
704 Revoke users global permissions
709 Revoke users global permissions
705
710
706 :param user:
711 :param user:
707 :param perm:
712 :param perm:
708 """
713 """
709 user = self._get_user(user)
714 user = self._get_user(user)
710 perm = self._get_perm(perm)
715 perm = self._get_perm(perm)
711
716
712 obj = UserToPerm.query()\
717 obj = UserToPerm.query()\
713 .filter(UserToPerm.user == user)\
718 .filter(UserToPerm.user == user)\
714 .filter(UserToPerm.permission == perm)\
719 .filter(UserToPerm.permission == perm)\
715 .scalar()
720 .scalar()
716 if obj:
721 if obj:
717 self.sa.delete(obj)
722 self.sa.delete(obj)
718
723
719 def add_extra_email(self, user, email):
724 def add_extra_email(self, user, email):
720 """
725 """
721 Adds email address to UserEmailMap
726 Adds email address to UserEmailMap
722
727
723 :param user:
728 :param user:
724 :param email:
729 :param email:
725 """
730 """
726 from rhodecode.model import forms
731 from rhodecode.model import forms
727 form = forms.UserExtraEmailForm()()
732 form = forms.UserExtraEmailForm()()
728 data = form.to_python(dict(email=email))
733 data = form.to_python(dict(email=email))
729 user = self._get_user(user)
734 user = self._get_user(user)
730
735
731 obj = UserEmailMap()
736 obj = UserEmailMap()
732 obj.user = user
737 obj.user = user
733 obj.email = data['email']
738 obj.email = data['email']
734 self.sa.add(obj)
739 self.sa.add(obj)
735 return obj
740 return obj
736
741
737 def delete_extra_email(self, user, email_id):
742 def delete_extra_email(self, user, email_id):
738 """
743 """
739 Removes email address from UserEmailMap
744 Removes email address from UserEmailMap
740
745
741 :param user:
746 :param user:
742 :param email_id:
747 :param email_id:
743 """
748 """
744 user = self._get_user(user)
749 user = self._get_user(user)
745 obj = UserEmailMap.query().get(email_id)
750 obj = UserEmailMap.query().get(email_id)
746 if obj:
751 if obj:
747 self.sa.delete(obj)
752 self.sa.delete(obj)
748
753
749 def add_extra_ip(self, user, ip):
754 def add_extra_ip(self, user, ip):
750 """
755 """
751 Adds ip address to UserIpMap
756 Adds ip address to UserIpMap
752
757
753 :param user:
758 :param user:
754 :param ip:
759 :param ip:
755 """
760 """
756 from rhodecode.model import forms
761 from rhodecode.model import forms
757 form = forms.UserExtraIpForm()()
762 form = forms.UserExtraIpForm()()
758 data = form.to_python(dict(ip=ip))
763 data = form.to_python(dict(ip=ip))
759 user = self._get_user(user)
764 user = self._get_user(user)
760
765
761 obj = UserIpMap()
766 obj = UserIpMap()
762 obj.user = user
767 obj.user = user
763 obj.ip_addr = data['ip']
768 obj.ip_addr = data['ip']
764 self.sa.add(obj)
769 self.sa.add(obj)
765 return obj
770 return obj
766
771
767 def delete_extra_ip(self, user, ip_id):
772 def delete_extra_ip(self, user, ip_id):
768 """
773 """
769 Removes ip address from UserIpMap
774 Removes ip address from UserIpMap
770
775
771 :param user:
776 :param user:
772 :param ip_id:
777 :param ip_id:
773 """
778 """
774 user = self._get_user(user)
779 user = self._get_user(user)
775 obj = UserIpMap.query().get(ip_id)
780 obj = UserIpMap.query().get(ip_id)
776 if obj:
781 if obj:
777 self.sa.delete(obj)
782 self.sa.delete(obj)
@@ -1,289 +1,252 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Edit user')} ${c.user.username} &middot; ${c.rhodecode_name}
5 ${_('Edit user')} ${c.user.username} &middot; ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${h.link_to(_('Users'),h.url('users'))}
11 ${h.link_to(_('Users'),h.url('users'))}
12 &raquo;
12 &raquo;
13 ${_('Edit %s') % c.user.username}
13 ${_('Edit %s') % c.user.username}
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('admin')}
17 ${self.menu('admin')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 <div class="box box-left">
21 <div class="box box-left">
22 <!-- box / title -->
22 <!-- box / title -->
23 <div class="title">
23 <div class="title">
24 ${self.breadcrumbs()}
24 ${self.breadcrumbs()}
25 </div>
25 </div>
26 <!-- end box / title -->
26 <!-- end box / title -->
27 ${h.form(url('update_user', id=c.user.user_id),method='put')}
27 ${h.form(url('update_user', id=c.user.user_id),method='put')}
28 <div class="form">
28 <div class="form">
29 <div class="field">
29 <div class="field">
30 <div class="gravatar_box">
30 <div class="gravatar_box">
31 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
31 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
32 <p>
32 <p>
33 %if c.use_gravatar:
33 %if c.use_gravatar:
34 <strong>${_('Change your avatar at')} <a href="http://gravatar.com">gravatar.com</a></strong>
34 <strong>${_('Change your avatar at')} <a href="http://gravatar.com">gravatar.com</a></strong>
35 <br/>${_('Using')} ${c.user.email}
35 <br/>${_('Using')} ${c.user.email}
36 %else:
36 %else:
37 <br/>${c.user.email}
37 <br/>${c.user.email}
38 %endif
38 %endif
39 </div>
39 </div>
40 </div>
40 </div>
41 <div class="field">
41 <div class="field">
42 <div class="label">
42 <div class="label">
43 <label>${_('API key')}:</label> ${c.user.api_key}
43 <label>${_('API key')}:</label> ${c.user.api_key}
44 </div>
44 </div>
45 </div>
45 </div>
46 ##show current ip just if we show ourself
46 ##show current ip just if we show ourself
47 %if c.rhodecode_user.username == c.user.username:
47 %if c.rhodecode_user.username == c.user.username:
48 <div class="field">
48 <div class="field">
49 <div class="label">
49 <div class="label">
50 <label>${_('Current IP')}:</label> ${c.perm_user.ip_addr or "?"}
50 <label>${_('Current IP')}:</label> ${c.perm_user.ip_addr or "?"}
51 </div>
51 </div>
52 </div>
52 </div>
53 %endif
53 %endif
54 <div class="fields">
54 <div class="fields">
55 <div class="field">
55 <div class="field">
56 <div class="label">
56 <div class="label">
57 <label for="username">${_('Username')}:</label>
57 <label for="username">${_('Username')}:</label>
58 </div>
58 </div>
59 <div class="input">
59 <div class="input">
60 %if c.ldap_dn:
60 %if c.ldap_dn:
61 ${h.text('username',class_='medium disabled', readonly="readonly")}
61 ${h.text('username',class_='medium disabled', readonly="readonly")}
62 %else:
62 %else:
63 ${h.text('username',class_='medium')}
63 ${h.text('username',class_='medium')}
64 %endif:
64 %endif:
65 </div>
65 </div>
66 </div>
66 </div>
67
67
68 <div class="field">
68 <div class="field">
69 <div class="label">
69 <div class="label">
70 <label for="ldap_dn">${_('LDAP DN')}:</label>
70 <label for="ldap_dn">${_('LDAP DN')}:</label>
71 </div>
71 </div>
72 <div class="input">
72 <div class="input">
73 ${h.text('ldap_dn',class_='medium disabled',readonly="readonly")}
73 ${h.text('ldap_dn',class_='medium disabled',readonly="readonly")}
74 </div>
74 </div>
75 </div>
75 </div>
76
76
77 <div class="field">
77 <div class="field">
78 <div class="label">
78 <div class="label">
79 <label for="new_password">${_('New password')}:</label>
79 <label for="new_password">${_('New password')}:</label>
80 </div>
80 </div>
81 <div class="input">
81 <div class="input">
82 ${h.password('new_password',class_='medium',autocomplete="off")}
82 ${h.password('new_password',class_='medium',autocomplete="off")}
83 </div>
83 </div>
84 </div>
84 </div>
85
85
86 <div class="field">
86 <div class="field">
87 <div class="label">
87 <div class="label">
88 <label for="password_confirmation">${_('New password confirmation')}:</label>
88 <label for="password_confirmation">${_('New password confirmation')}:</label>
89 </div>
89 </div>
90 <div class="input">
90 <div class="input">
91 ${h.password('password_confirmation',class_="medium",autocomplete="off")}
91 ${h.password('password_confirmation',class_="medium",autocomplete="off")}
92 </div>
92 </div>
93 </div>
93 </div>
94
94
95 <div class="field">
95 <div class="field">
96 <div class="label">
96 <div class="label">
97 <label for="firstname">${_('First Name')}:</label>
97 <label for="firstname">${_('First Name')}:</label>
98 </div>
98 </div>
99 <div class="input">
99 <div class="input">
100 ${h.text('firstname',class_='medium')}
100 ${h.text('firstname',class_='medium')}
101 </div>
101 </div>
102 </div>
102 </div>
103
103
104 <div class="field">
104 <div class="field">
105 <div class="label">
105 <div class="label">
106 <label for="lastname">${_('Last Name')}:</label>
106 <label for="lastname">${_('Last Name')}:</label>
107 </div>
107 </div>
108 <div class="input">
108 <div class="input">
109 ${h.text('lastname',class_='medium')}
109 ${h.text('lastname',class_='medium')}
110 </div>
110 </div>
111 </div>
111 </div>
112
112
113 <div class="field">
113 <div class="field">
114 <div class="label">
114 <div class="label">
115 <label for="email">${_('Email')}:</label>
115 <label for="email">${_('Email')}:</label>
116 </div>
116 </div>
117 <div class="input">
117 <div class="input">
118 ${h.text('email',class_='medium')}
118 ${h.text('email',class_='medium')}
119 </div>
119 </div>
120 </div>
120 </div>
121
121
122 <div class="field">
122 <div class="field">
123 <div class="label label-checkbox">
123 <div class="label label-checkbox">
124 <label for="active">${_('Active')}:</label>
124 <label for="active">${_('Active')}:</label>
125 </div>
125 </div>
126 <div class="checkboxes">
126 <div class="checkboxes">
127 ${h.checkbox('active',value=True)}
127 ${h.checkbox('active',value=True)}
128 </div>
128 </div>
129 </div>
129 </div>
130
130
131 <div class="field">
131 <div class="field">
132 <div class="label label-checkbox">
132 <div class="label label-checkbox">
133 <label for="admin">${_('Admin')}:</label>
133 <label for="admin">${_('Admin')}:</label>
134 </div>
134 </div>
135 <div class="checkboxes">
135 <div class="checkboxes">
136 ${h.checkbox('admin',value=True)}
136 ${h.checkbox('admin',value=True)}
137 </div>
137 </div>
138 </div>
138 </div>
139 <div class="buttons">
139 <div class="buttons">
140 ${h.submit('save',_('Save'),class_="ui-btn large")}
140 ${h.submit('save',_('Save'),class_="ui-btn large")}
141 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
141 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
142 </div>
142 </div>
143 </div>
143 </div>
144 </div>
144 </div>
145 ${h.end_form()}
145 ${h.end_form()}
146 </div>
146 </div>
147 <div style="min-height:780px" class="box box-right">
147 <div style="min-height:780px" class="box box-right">
148 <!-- box / title -->
148 <!-- box / title -->
149 <div class="title">
149 <div class="title">
150 <h5>${_('Permissions')}</h5>
150 <h5>${_('Permissions')}</h5>
151 </div>
151 </div>
152 ${h.form(url('user_perm', id=c.user.user_id),method='put')}
152 <%namespace name="dpb" file="/base/default_perms_box.html"/>
153 <div class="form">
153 ${dpb.default_perms_box(url('user_perm', id=c.user.user_id))}
154 <!-- fields -->
155 <div class="fields">
156 <div class="field">
157 <div class="label label-checkbox">
158 <label for="inherit_permissions">${_('Inherit default permissions')}:</label>
159 </div>
160 <div class="checkboxes">
161 ${h.checkbox('inherit_default_permissions',value=True)}
162 </div>
163 <span class="help-block">${h.literal(_('Select to inherit permissions from %s settings. '
164 'With this selected below options does not have any action') % h.link_to('default', url('edit_permission', id='default')))}</span>
165 </div>
166 <div id="inherit_overlay" style="${'opacity:0.3' if c.user.inherit_default_permissions else ''}" >
167 <div class="field">
168 <div class="label label-checkbox">
169 <label for="create_repo_perm">${_('Create repositories')}:</label>
170 </div>
171 <div class="checkboxes">
172 ${h.checkbox('create_repo_perm',value=True)}
173 </div>
174 </div>
175 <div class="field">
176 <div class="label label-checkbox">
177 <label for="fork_repo_perm">${_('Fork repositories')}:</label>
178 </div>
179 <div class="checkboxes">
180 ${h.checkbox('fork_repo_perm',value=True)}
181 </div>
182 </div>
183 </div>
184 <div class="buttons">
185 ${h.submit('save',_('Save'),class_="ui-btn large")}
186 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
187 </div>
188 </div>
189 </div>
190 ${h.end_form()}
191
154
192 ## permissions overview
155 ## permissions overview
193 <%namespace name="p" file="/base/perms_summary.html"/>
156 <%namespace name="p" file="/base/perms_summary.html"/>
194 ${p.perms_summary(c.perm_user.permissions)}
157 ${p.perms_summary(c.perm_user.permissions)}
195
158
196 </div>
159 </div>
197 <div class="box box-left" style="clear:left">
160 <div class="box box-left" style="clear:left">
198 <!-- box / title -->
161 <!-- box / title -->
199 <div class="title">
162 <div class="title">
200 <h5>${_('Email addresses')}</h5>
163 <h5>${_('Email addresses')}</h5>
201 </div>
164 </div>
202
165
203 <div class="emails_wrap">
166 <div class="emails_wrap">
204 <table class="noborder">
167 <table class="noborder">
205 %for em in c.user_email_map:
168 %for em in c.user_email_map:
206 <tr>
169 <tr>
207 <td><div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(em.user.email,16)}"/> </div></td>
170 <td><div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(em.user.email,16)}"/> </div></td>
208 <td><div class="email">${em.email}</div></td>
171 <td><div class="email">${em.email}</div></td>
209 <td>
172 <td>
210 ${h.form(url('user_emails_delete', id=c.user.user_id),method='delete')}
173 ${h.form(url('user_emails_delete', id=c.user.user_id),method='delete')}
211 ${h.hidden('del_email',em.email_id)}
174 ${h.hidden('del_email',em.email_id)}
212 ${h.submit('remove_',_('delete'),id="remove_email_%s" % em.email_id,
175 ${h.submit('remove_',_('delete'),id="remove_email_%s" % em.email_id,
213 class_="delete_icon action_button", onclick="return confirm('"+_('Confirm to delete this email: %s') % em.email+"');")}
176 class_="delete_icon action_button", onclick="return confirm('"+_('Confirm to delete this email: %s') % em.email+"');")}
214 ${h.end_form()}
177 ${h.end_form()}
215 </td>
178 </td>
216 </tr>
179 </tr>
217 %endfor
180 %endfor
218 </table>
181 </table>
219 </div>
182 </div>
220
183
221 ${h.form(url('user_emails', id=c.user.user_id),method='put')}
184 ${h.form(url('user_emails', id=c.user.user_id),method='put')}
222 <div class="form">
185 <div class="form">
223 <!-- fields -->
186 <!-- fields -->
224 <div class="fields">
187 <div class="fields">
225 <div class="field">
188 <div class="field">
226 <div class="label">
189 <div class="label">
227 <label for="new_email">${_('New email address')}:</label>
190 <label for="new_email">${_('New email address')}:</label>
228 </div>
191 </div>
229 <div class="input">
192 <div class="input">
230 ${h.text('new_email', class_='medium')}
193 ${h.text('new_email', class_='medium')}
231 </div>
194 </div>
232 </div>
195 </div>
233 <div class="buttons">
196 <div class="buttons">
234 ${h.submit('save',_('Add'),class_="ui-btn large")}
197 ${h.submit('save',_('Add'),class_="ui-btn large")}
235 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
198 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
236 </div>
199 </div>
237 </div>
200 </div>
238 </div>
201 </div>
239 ${h.end_form()}
202 ${h.end_form()}
240 </div>
203 </div>
241 <div class="box box-left" style="clear:left">
204 <div class="box box-left" style="clear:left">
242 <!-- box / title -->
205 <!-- box / title -->
243 <div class="title">
206 <div class="title">
244 <h5>${_('Allowed IP addresses')}</h5>
207 <h5>${_('Allowed IP addresses')}</h5>
245 </div>
208 </div>
246
209
247 <div class="ips_wrap">
210 <div class="ips_wrap">
248 <table class="noborder">
211 <table class="noborder">
249 %if c.user_ip_map:
212 %if c.user_ip_map:
250 %for ip in c.user_ip_map:
213 %for ip in c.user_ip_map:
251 <tr>
214 <tr>
252 <td><div class="ip">${ip.ip_addr}</div></td>
215 <td><div class="ip">${ip.ip_addr}</div></td>
253 <td><div class="ip">${h.ip_range(ip.ip_addr)}</div></td>
216 <td><div class="ip">${h.ip_range(ip.ip_addr)}</div></td>
254 <td>
217 <td>
255 ${h.form(url('user_ips_delete', id=c.user.user_id),method='delete')}
218 ${h.form(url('user_ips_delete', id=c.user.user_id),method='delete')}
256 ${h.hidden('del_ip',ip.ip_id)}
219 ${h.hidden('del_ip',ip.ip_id)}
257 ${h.submit('remove_',_('delete'),id="remove_ip_%s" % ip.ip_id,
220 ${h.submit('remove_',_('delete'),id="remove_ip_%s" % ip.ip_id,
258 class_="delete_icon action_button", onclick="return confirm('"+_('Confirm to delete this ip: %s') % ip.ip_addr+"');")}
221 class_="delete_icon action_button", onclick="return confirm('"+_('Confirm to delete this ip: %s') % ip.ip_addr+"');")}
259 ${h.end_form()}
222 ${h.end_form()}
260 </td>
223 </td>
261 </tr>
224 </tr>
262 %endfor
225 %endfor
263 %else:
226 %else:
264 <tr><td><div class="ip">${_('All IP addresses are allowed')}</div></td></tr>
227 <tr><td><div class="ip">${_('All IP addresses are allowed')}</div></td></tr>
265 %endif
228 %endif
266 </table>
229 </table>
267 </div>
230 </div>
268
231
269 ${h.form(url('user_ips', id=c.user.user_id),method='put')}
232 ${h.form(url('user_ips', id=c.user.user_id),method='put')}
270 <div class="form">
233 <div class="form">
271 <!-- fields -->
234 <!-- fields -->
272 <div class="fields">
235 <div class="fields">
273 <div class="field">
236 <div class="field">
274 <div class="label">
237 <div class="label">
275 <label for="new_ip">${_('New ip address')}:</label>
238 <label for="new_ip">${_('New ip address')}:</label>
276 </div>
239 </div>
277 <div class="input">
240 <div class="input">
278 ${h.text('new_ip', class_='medium')}
241 ${h.text('new_ip', class_='medium')}
279 </div>
242 </div>
280 </div>
243 </div>
281 <div class="buttons">
244 <div class="buttons">
282 ${h.submit('save',_('Add'),class_="ui-btn large")}
245 ${h.submit('save',_('Add'),class_="ui-btn large")}
283 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
246 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
284 </div>
247 </div>
285 </div>
248 </div>
286 </div>
249 </div>
287 ${h.end_form()}
250 ${h.end_form()}
288 </div>
251 </div>
289 </%def>
252 </%def>
@@ -1,188 +1,150 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Edit user group')} ${c.users_group.users_group_name} &middot; ${c.rhodecode_name}
5 ${_('Edit user group')} ${c.users_group.users_group_name} &middot; ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${h.link_to(_('UserGroups'),h.url('users_groups'))}
11 ${h.link_to(_('UserGroups'),h.url('users_groups'))}
12 &raquo;
12 &raquo;
13 ${_('Edit %s') % c.users_group.users_group_name}
13 ${_('Edit %s') % c.users_group.users_group_name}
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('admin')}
17 ${self.menu('admin')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 <div class="box box-left" style="clear:left">
21 <div class="box box-left" style="clear:left">
22 <!-- box / title -->
22 <!-- box / title -->
23 <div class="title">
23 <div class="title">
24 ${self.breadcrumbs()}
24 ${self.breadcrumbs()}
25 </div>
25 </div>
26 <!-- end box / title -->
26 <!-- end box / title -->
27 ${h.form(url('users_group', id=c.users_group.users_group_id),method='put', id='edit_users_group')}
27 ${h.form(url('users_group', id=c.users_group.users_group_id),method='put', id='edit_users_group')}
28 <div class="form">
28 <div class="form">
29 <!-- fields -->
29 <!-- fields -->
30 <div class="fields">
30 <div class="fields">
31 <div class="field">
31 <div class="field">
32 <div class="label">
32 <div class="label">
33 <label for="users_group_name">${_('Group name')}:</label>
33 <label for="users_group_name">${_('Group name')}:</label>
34 </div>
34 </div>
35 <div class="input">
35 <div class="input">
36 ${h.text('users_group_name',class_='small')}
36 ${h.text('users_group_name',class_='small')}
37 </div>
37 </div>
38 </div>
38 </div>
39
39
40 <div class="field">
40 <div class="field">
41 <div class="label label-checkbox">
41 <div class="label label-checkbox">
42 <label for="users_group_active">${_('Active')}:</label>
42 <label for="users_group_active">${_('Active')}:</label>
43 </div>
43 </div>
44 <div class="checkboxes">
44 <div class="checkboxes">
45 ${h.checkbox('users_group_active',value=True)}
45 ${h.checkbox('users_group_active',value=True)}
46 </div>
46 </div>
47 </div>
47 </div>
48 <div class="field">
48 <div class="field">
49 <div class="label">
49 <div class="label">
50 <label for="users_group_active">${_('Members')}:</label>
50 <label for="users_group_active">${_('Members')}:</label>
51 </div>
51 </div>
52 <div class="select">
52 <div class="select">
53 <table>
53 <table>
54 <tr>
54 <tr>
55 <td>
55 <td>
56 <div>
56 <div>
57 <div style="float:left">
57 <div style="float:left">
58 <div class="text" style="padding: 0px 0px 6px;">${_('Chosen group members')}</div>
58 <div class="text" style="padding: 0px 0px 6px;">${_('Chosen group members')}</div>
59 ${h.select('users_group_members',[x[0] for x in c.group_members],c.group_members,multiple=True,size=8,style="min-width:210px")}
59 ${h.select('users_group_members',[x[0] for x in c.group_members],c.group_members,multiple=True,size=8,style="min-width:210px")}
60 <div id="remove_all_elements" style="cursor:pointer;text-align:center">
60 <div id="remove_all_elements" style="cursor:pointer;text-align:center">
61 ${_('Remove all elements')}
61 ${_('Remove all elements')}
62 <img alt="remove" style="vertical-align:text-bottom" src="${h.url('/images/icons/arrow_right.png')}"/>
62 <img alt="remove" style="vertical-align:text-bottom" src="${h.url('/images/icons/arrow_right.png')}"/>
63 </div>
63 </div>
64 </div>
64 </div>
65 <div style="float:left;width:20px;padding-top:50px">
65 <div style="float:left;width:20px;padding-top:50px">
66 <img alt="add" id="add_element"
66 <img alt="add" id="add_element"
67 style="padding:2px;cursor:pointer"
67 style="padding:2px;cursor:pointer"
68 src="${h.url('/images/icons/arrow_left.png')}"/>
68 src="${h.url('/images/icons/arrow_left.png')}"/>
69 <br />
69 <br />
70 <img alt="remove" id="remove_element"
70 <img alt="remove" id="remove_element"
71 style="padding:2px;cursor:pointer"
71 style="padding:2px;cursor:pointer"
72 src="${h.url('/images/icons/arrow_right.png')}"/>
72 src="${h.url('/images/icons/arrow_right.png')}"/>
73 </div>
73 </div>
74 <div style="float:left">
74 <div style="float:left">
75 <div class="text" style="padding: 0px 0px 6px;">${_('Available members')}</div>
75 <div class="text" style="padding: 0px 0px 6px;">${_('Available members')}</div>
76 ${h.select('available_members',[],c.available_members,multiple=True,size=8,style="min-width:210px")}
76 ${h.select('available_members',[],c.available_members,multiple=True,size=8,style="min-width:210px")}
77 <div id="add_all_elements" style="cursor:pointer;text-align:center">
77 <div id="add_all_elements" style="cursor:pointer;text-align:center">
78 <img alt="add" style="vertical-align:text-bottom" src="${h.url('/images/icons/arrow_left.png')}"/>
78 <img alt="add" style="vertical-align:text-bottom" src="${h.url('/images/icons/arrow_left.png')}"/>
79 ${_('Add all elements')}
79 ${_('Add all elements')}
80 </div>
80 </div>
81 </div>
81 </div>
82 </div>
82 </div>
83 </td>
83 </td>
84 </tr>
84 </tr>
85 </table>
85 </table>
86 </div>
86 </div>
87
87
88 </div>
88 </div>
89 <div class="buttons">
89 <div class="buttons">
90 ${h.submit('Save',_('Save'),class_="ui-btn large")}
90 ${h.submit('Save',_('Save'),class_="ui-btn large")}
91 </div>
91 </div>
92 </div>
92 </div>
93 </div>
93 </div>
94 ${h.end_form()}
94 ${h.end_form()}
95 <div class="group_members_wrap">
95 <div class="group_members_wrap">
96 % if c.group_members_obj:
96 % if c.group_members_obj:
97 <ul class="group_members">
97 <ul class="group_members">
98 %for user in c.group_members_obj:
98 %for user in c.group_members_obj:
99 <li>
99 <li>
100 <div class="group_member">
100 <div class="group_member">
101 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(user.email,24)}"/> </div>
101 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(user.email,24)}"/> </div>
102 <div>${h.link_to(user.username, h.url('edit_user',id=user.user_id))}</div>
102 <div>${h.link_to(user.username, h.url('edit_user',id=user.user_id))}</div>
103 <div>${user.full_name}</div>
103 <div>${user.full_name}</div>
104 </div>
104 </div>
105 </li>
105 </li>
106 %endfor
106 %endfor
107 </ul>
107 </ul>
108 %else:
108 %else:
109 <span class="empty_data">${_('No members yet')}</span>
109 <span class="empty_data">${_('No members yet')}</span>
110 %endif
110 %endif
111 </div>
111 </div>
112 </div>
112 </div>
113
113
114 <div class="box box-right">
115 <!-- box / title -->
116 <div class="title">
117 <h5>${_('Global Permissions')}</h5>
118 </div>
119 <%namespace name="dpb" file="/base/default_perms_box.html"/>
120 ${dpb.default_perms_box(url('users_group_perm', id=c.users_group.users_group_id))}
121 </div>
114
122
115 <div class="box box-right">
123 <div class="box box-right">
116 <div class="title">
124 <div class="title">
117 <h5>${_('Permissions')}</h5>
125 <h5>${_('Permissions')}</h5>
118 </div>
126 </div>
119 ${h.form(url('set_user_group_perm_member', id=c.users_group.users_group_id),method='post')}
127 ${h.form(url('set_user_group_perm_member', id=c.users_group.users_group_id),method='post')}
120 <div class="form">
128 <div class="form">
121 <div class="fields">
129 <div class="fields">
122 <div class="field">
130 <div class="field">
123 <div class="label">
131 <div class="label">
124 <label for="input">${_('Permissions')}:</label>
132 <label for="input">${_('Permissions')}:</label>
125 </div>
133 </div>
126 <div class="input">
134 <div class="input">
127 <%include file="user_group_edit_perms.html"/>
135 <%include file="user_group_edit_perms.html"/>
128 </div>
136 </div>
129 </div>
137 </div>
130 <div class="buttons">
138 <div class="buttons">
131 ${h.submit('save',_('Save'),class_="ui-btn large")}
139 ${h.submit('save',_('Save'),class_="ui-btn large")}
132 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
140 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
133 </div>
141 </div>
134 </div>
142 </div>
135 </div>
143 </div>
136 ${h.end_form()}
144 ${h.end_form()}
137 </div>
145 </div>
138
146
139 <div class="box box-right">
140 <!-- box / title -->
141 <div class="title">
142 <h5>${_('Global Permissions')}</h5>
143 </div>
144 ${h.form(url('users_group_perm', id=c.users_group.users_group_id), method='put')}
145 <div class="form">
146 <!-- fields -->
147 <div class="fields">
148 <div class="field">
149 <div class="label label-checkbox">
150 <label for="inherit_permissions">${_('Inherit default permissions')}:</label>
151 </div>
152 <div class="checkboxes">
153 ${h.checkbox('inherit_default_permissions',value=True)}
154 </div>
155 <span class="help-block">${h.literal(_('Select to inherit permissions from %s settings. '
156 'With this selected below options does not have any action') % h.link_to('default', url('edit_permission', id='default')))}</span>
157 </div>
158 <div id="inherit_overlay" style="${'opacity:0.3' if c.users_group.inherit_default_permissions else ''}" >
159 <div class="field">
160 <div class="label label-checkbox">
161 <label for="create_repo_perm">${_('Create repositories')}:</label>
162 </div>
163 <div class="checkboxes">
164 ${h.checkbox('create_repo_perm',value=True)}
165 </div>
166 </div>
167 <div class="field">
168 <div class="label label-checkbox">
169 <label for="fork_repo_perm">${_('Fork repositories')}:</label>
170 </div>
171 <div class="checkboxes">
172 ${h.checkbox('fork_repo_perm',value=True)}
173 </div>
174 </div>
175 </div>
176 <div class="buttons">
177 ${h.submit('save',_('Save'),class_="ui-btn large")}
178 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
179 </div>
180 </div>
181 </div>
182 ${h.end_form()}
183 </div>
184
185 <script type="text/javascript">
147 <script type="text/javascript">
186 MultiSelectWidget('users_group_members','available_members','edit_users_group');
148 MultiSelectWidget('users_group_members','available_members','edit_users_group');
187 </script>
149 </script>
188 </%def>
150 </%def>
@@ -1,71 +1,74 b''
1 ## snippet for displaying permissions overview for users
1 ## snippet for displaying permissions overview for users
2 ## usage:
3 ## <%namespace name="p" file="/base/perms_summary.html"/>
4 ## ${p.perms_summary(c.perm_user.permissions)}
2
5
3 <%def name="perms_summary(permissions)">
6 <%def name="perms_summary(permissions)">
4 <div id="perms" class="table">
7 <div id="perms" class="table">
5 %for section in sorted(permissions.keys()):
8 %for section in sorted(permissions.keys()):
6 <div class="perms_section_head">${section.replace("_"," ").capitalize()}</div>
9 <div class="perms_section_head">${section.replace("_"," ").capitalize()}</div>
7 %if not permissions[section]:
10 %if not permissions[section]:
8 <span class="empty_data">${_('No permissions defined yet')}</span>
11 <span class="empty_data">${_('No permissions defined yet')}</span>
9 %else:
12 %else:
10 <div id='tbl_list_wrap_${section}' class="yui-skin-sam">
13 <div id='tbl_list_wrap_${section}' class="yui-skin-sam">
11 <table id="tbl_list_${section}">
14 <table id="tbl_list_${section}">
12 %if section == 'global':
15 %if section == 'global':
13 <thead>
16 <thead>
14 <tr>
17 <tr>
15 <th colspan="2" class="left">${_('Permission')}</th>
18 <th colspan="2" class="left">${_('Permission')}</th>
16 <th class="left">${_('Edit Permission')}</th>
19 <th class="left">${_('Edit Permission')}</th>
17 </thead>
20 </thead>
18 <tbody>
21 <tbody>
19 %for k in sorted(permissions[section], key=lambda s: s.lower()):
22 %for k in permissions[section]:
20 <tr>
23 <tr>
21 <td colspan="2">
24 <td colspan="2">
22 ${h.get_permission_name(k)}
25 ${h.get_permission_name(k)}
23 </td>
26 </td>
24 <td>
27 <td>
25 <a href="${h.url('edit_permission', id='default')}">${_('edit')}</a>
28 <a href="${h.url('edit_permission', id='default')}">${_('edit')}</a>
26 </td>
29 </td>
27 </tr>
30 </tr>
28 %endfor
31 %endfor
29 </tbody>
32 </tbody>
30 %else:
33 %else:
31 <thead>
34 <thead>
32 <tr>
35 <tr>
33 <th class="left">${_('Name')}</th>
36 <th class="left">${_('Name')}</th>
34 <th class="left">${_('Permission')}</th>
37 <th class="left">${_('Permission')}</th>
35 <th class="left">${_('Edit Permission')}</th>
38 <th class="left">${_('Edit Permission')}</th>
36 </thead>
39 </thead>
37 <tbody>
40 <tbody>
38 %for k, section_perm in sorted(permissions[section].items(), key=lambda s: s[1]+s[0].lower()):
41 %for k, section_perm in sorted(permissions[section].items(), key=lambda s: s[1]+s[0].lower()):
39 <tr>
42 <tr>
40 <td>
43 <td>
41 %if section == 'repositories':
44 %if section == 'repositories':
42 <a href="${h.url('summary_home',repo_name=k)}">${k}</a>
45 <a href="${h.url('summary_home',repo_name=k)}">${k}</a>
43 %elif section == 'repositories_groups':
46 %elif section == 'repositories_groups':
44 <a href="${h.url('repos_group_home',group_name=k)}">${k}</a>
47 <a href="${h.url('repos_group_home',group_name=k)}">${k}</a>
45 %elif section == 'user_groups':
48 %elif section == 'user_groups':
46 ##<a href="${h.url('edit_users_group',id=k)}">${k}</a>
49 ##<a href="${h.url('edit_users_group',id=k)}">${k}</a>
47 ${k}
50 ${k}
48 %endif
51 %endif
49 </td>
52 </td>
50 <td>
53 <td>
51 <span class="perm_tag ${section_perm.split('.')[-1]}">${section_perm}</span>
54 <span class="perm_tag ${section_perm.split('.')[-1]}">${section_perm}</span>
52 </td>
55 </td>
53 <td>
56 <td>
54 %if section == 'repositories':
57 %if section == 'repositories':
55 <a href="${h.url('edit_repo',repo_name=k,anchor='permissions_manage')}">${_('edit')}</a>
58 <a href="${h.url('edit_repo',repo_name=k,anchor='permissions_manage')}">${_('edit')}</a>
56 %elif section == 'repositories_groups':
59 %elif section == 'repositories_groups':
57 <a href="${h.url('edit_repos_group',group_name=k,anchor='permissions_manage')}">${_('edit')}</a>
60 <a href="${h.url('edit_repos_group',group_name=k,anchor='permissions_manage')}">${_('edit')}</a>
58 %elif section == 'user_groups':
61 %elif section == 'user_groups':
59 ##<a href="${h.url('edit_users_group',id=k)}">${_('edit')}</a>
62 ##<a href="${h.url('edit_users_group',id=k)}">${_('edit')}</a>
60 %endif
63 %endif
61 </td>
64 </td>
62 </tr>
65 </tr>
63 %endfor
66 %endfor
64 </tbody>
67 </tbody>
65 %endif
68 %endif
66 </table>
69 </table>
67 </div>
70 </div>
68 %endif
71 %endif
69 %endfor
72 %endfor
70 </div>
73 </div>
71 </%def>
74 </%def>
General Comments 0
You need to be logged in to leave comments. Login now