##// END OF EJS Templates
fixed validation of user email in user creation, and editing on admin panel
marcink -
r490:74b9bed2 celery
parent child Browse files
Show More
@@ -1,164 +1,166
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # users controller for pylons
3 # users controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 4, 2010
21 Created on April 4, 2010
22 users controller for pylons
22 users controller for pylons
23 @author: marcink
23 @author: marcink
24 """
24 """
25
25
26 from formencode import htmlfill
26 from formencode import htmlfill
27 from pylons import request, session, tmpl_context as c, url
27 from pylons import request, session, tmpl_context as c, url
28 from pylons.controllers.util import abort, redirect
28 from pylons.controllers.util import abort, redirect
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30 from pylons_app.lib import helpers as h
30 from pylons_app.lib import helpers as h
31 from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator
31 from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator
32 from pylons_app.lib.base import BaseController, render
32 from pylons_app.lib.base import BaseController, render
33 from pylons_app.model.db import User, UserLog
33 from pylons_app.model.db import User, UserLog
34 from pylons_app.model.forms import UserForm
34 from pylons_app.model.forms import UserForm
35 from pylons_app.model.user_model import UserModel, DefaultUserException
35 from pylons_app.model.user_model import UserModel, DefaultUserException
36 import formencode
36 import formencode
37 import logging
37 import logging
38 import traceback
38 import traceback
39
39
40 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
41
41
42 class UsersController(BaseController):
42 class UsersController(BaseController):
43 """REST Controller styled on the Atom Publishing Protocol"""
43 """REST Controller styled on the Atom Publishing Protocol"""
44 # To properly map this controller, ensure your config/routing.py
44 # To properly map this controller, ensure your config/routing.py
45 # file has a resource setup:
45 # file has a resource setup:
46 # map.resource('user', 'users')
46 # map.resource('user', 'users')
47
47
48 @LoginRequired()
48 @LoginRequired()
49 @HasPermissionAllDecorator('hg.admin')
49 @HasPermissionAllDecorator('hg.admin')
50 def __before__(self):
50 def __before__(self):
51 c.admin_user = session.get('admin_user')
51 c.admin_user = session.get('admin_user')
52 c.admin_username = session.get('admin_username')
52 c.admin_username = session.get('admin_username')
53 super(UsersController, self).__before__()
53 super(UsersController, self).__before__()
54
54
55
55
56 def index(self, format='html'):
56 def index(self, format='html'):
57 """GET /users: All items in the collection"""
57 """GET /users: All items in the collection"""
58 # url('users')
58 # url('users')
59
59
60 c.users_list = self.sa.query(User).all()
60 c.users_list = self.sa.query(User).all()
61 return render('admin/users/users.html')
61 return render('admin/users/users.html')
62
62
63 def create(self):
63 def create(self):
64 """POST /users: Create a new item"""
64 """POST /users: Create a new item"""
65 # url('users')
65 # url('users')
66
66
67 user_model = UserModel()
67 user_model = UserModel()
68 login_form = UserForm()()
68 login_form = UserForm()()
69 try:
69 try:
70 form_result = login_form.to_python(dict(request.POST))
70 form_result = login_form.to_python(dict(request.POST))
71 user_model.create(form_result)
71 user_model.create(form_result)
72 h.flash(_('created user %s') % form_result['username'],
72 h.flash(_('created user %s') % form_result['username'],
73 category='success')
73 category='success')
74 except formencode.Invalid as errors:
74 except formencode.Invalid as errors:
75 return htmlfill.render(
75 return htmlfill.render(
76 render('admin/users/user_add.html'),
76 render('admin/users/user_add.html'),
77 defaults=errors.value,
77 defaults=errors.value,
78 errors=errors.error_dict or {},
78 errors=errors.error_dict or {},
79 prefix_error=False,
79 prefix_error=False,
80 encoding="UTF-8")
80 encoding="UTF-8")
81 except Exception:
81 except Exception:
82 log.error(traceback.format_exc())
82 log.error(traceback.format_exc())
83 h.flash(_('error occured during creation of user %s') \
83 h.flash(_('error occured during creation of user %s') \
84 % request.POST.get('username'), category='error')
84 % request.POST.get('username'), category='error')
85 return redirect(url('users'))
85 return redirect(url('users'))
86
86
87 def new(self, format='html'):
87 def new(self, format='html'):
88 """GET /users/new: Form to create a new item"""
88 """GET /users/new: Form to create a new item"""
89 # url('new_user')
89 # url('new_user')
90 return render('admin/users/user_add.html')
90 return render('admin/users/user_add.html')
91
91
92 def update(self, id):
92 def update(self, id):
93 """PUT /users/id: Update an existing item"""
93 """PUT /users/id: Update an existing item"""
94 # Forms posted to this method should contain a hidden field:
94 # Forms posted to this method should contain a hidden field:
95 # <input type="hidden" name="_method" value="PUT" />
95 # <input type="hidden" name="_method" value="PUT" />
96 # Or using helpers:
96 # Or using helpers:
97 # h.form(url('user', id=ID),
97 # h.form(url('user', id=ID),
98 # method='put')
98 # method='put')
99 # url('user', id=ID)
99 # url('user', id=ID)
100 user_model = UserModel()
100 user_model = UserModel()
101 _form = UserForm(edit=True, old_data={'user_id':id})()
101 c.user = user_model.get_user(id)
102
103 _form = UserForm(edit=True, old_data={'user_id':id,
104 'email':c.user.email})()
102 form_result = {}
105 form_result = {}
103 try:
106 try:
104 form_result = _form.to_python(dict(request.POST))
107 form_result = _form.to_python(dict(request.POST))
105 user_model.update(id, form_result)
108 user_model.update(id, form_result)
106 h.flash(_('User updated succesfully'), category='success')
109 h.flash(_('User updated succesfully'), category='success')
107
110
108 except formencode.Invalid as errors:
111 except formencode.Invalid as errors:
109 c.user = user_model.get_user(id)
110 return htmlfill.render(
112 return htmlfill.render(
111 render('admin/users/user_edit.html'),
113 render('admin/users/user_edit.html'),
112 defaults=errors.value,
114 defaults=errors.value,
113 errors=errors.error_dict or {},
115 errors=errors.error_dict or {},
114 prefix_error=False,
116 prefix_error=False,
115 encoding="UTF-8")
117 encoding="UTF-8")
116 except Exception:
118 except Exception:
117 log.error(traceback.format_exc())
119 log.error(traceback.format_exc())
118 h.flash(_('error occured during update of user %s') \
120 h.flash(_('error occured during update of user %s') \
119 % form_result.get('username'), category='error')
121 % form_result.get('username'), category='error')
120
122
121 return redirect(url('users'))
123 return redirect(url('users'))
122
124
123 def delete(self, id):
125 def delete(self, id):
124 """DELETE /users/id: Delete an existing item"""
126 """DELETE /users/id: Delete an existing item"""
125 # Forms posted to this method should contain a hidden field:
127 # Forms posted to this method should contain a hidden field:
126 # <input type="hidden" name="_method" value="DELETE" />
128 # <input type="hidden" name="_method" value="DELETE" />
127 # Or using helpers:
129 # Or using helpers:
128 # h.form(url('user', id=ID),
130 # h.form(url('user', id=ID),
129 # method='delete')
131 # method='delete')
130 # url('user', id=ID)
132 # url('user', id=ID)
131 user_model = UserModel()
133 user_model = UserModel()
132 try:
134 try:
133 user_model.delete(id)
135 user_model.delete(id)
134 h.flash(_('sucessfully deleted user'), category='success')
136 h.flash(_('sucessfully deleted user'), category='success')
135 except DefaultUserException as e:
137 except DefaultUserException as e:
136 h.flash(str(e), category='warning')
138 h.flash(str(e), category='warning')
137 except Exception:
139 except Exception:
138 h.flash(_('An error occured during deletion of user'),
140 h.flash(_('An error occured during deletion of user'),
139 category='error')
141 category='error')
140 return redirect(url('users'))
142 return redirect(url('users'))
141
143
142 def show(self, id, format='html'):
144 def show(self, id, format='html'):
143 """GET /users/id: Show a specific item"""
145 """GET /users/id: Show a specific item"""
144 # url('user', id=ID)
146 # url('user', id=ID)
145
147
146
148
147 def edit(self, id, format='html'):
149 def edit(self, id, format='html'):
148 """GET /users/id/edit: Form to edit an existing item"""
150 """GET /users/id/edit: Form to edit an existing item"""
149 # url('edit_user', id=ID)
151 # url('edit_user', id=ID)
150 c.user = self.sa.query(User).get(id)
152 c.user = self.sa.query(User).get(id)
151 if not c.user:
153 if not c.user:
152 return redirect(url('users'))
154 return redirect(url('users'))
153 if c.user.username == 'default':
155 if c.user.username == 'default':
154 h.flash(_("You can't edit this user since it's"
156 h.flash(_("You can't edit this user since it's"
155 " crucial for entire application"), category='warning')
157 " crucial for entire application"), category='warning')
156 return redirect(url('users'))
158 return redirect(url('users'))
157
159
158 defaults = c.user.__dict__
160 defaults = c.user.__dict__
159 return htmlfill.render(
161 return htmlfill.render(
160 render('admin/users/user_edit.html'),
162 render('admin/users/user_edit.html'),
161 defaults=defaults,
163 defaults=defaults,
162 encoding="UTF-8",
164 encoding="UTF-8",
163 force_defaults=False
165 force_defaults=False
164 )
166 )
@@ -1,351 +1,351
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 from formencode import All
22 from formencode import All
23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
24 Email, Bool, StringBoolean
24 Email, Bool, StringBoolean
25 from pylons import session
25 from pylons import session
26 from pylons.i18n.translation import _
26 from pylons.i18n.translation import _
27 from pylons_app.lib.auth import check_password, get_crypt_password
27 from pylons_app.lib.auth import check_password, get_crypt_password
28 from pylons_app.model import meta
28 from pylons_app.model import meta
29 from pylons_app.model.user_model import UserModel
29 from pylons_app.model.user_model import UserModel
30 from pylons_app.model.db import User, Repository
30 from pylons_app.model.db import User, Repository
31 from sqlalchemy.exc import OperationalError
31 from sqlalchemy.exc import OperationalError
32 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
32 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
33 from webhelpers.pylonslib.secure_form import authentication_token
33 from webhelpers.pylonslib.secure_form import authentication_token
34 import formencode
34 import formencode
35 import logging
35 import logging
36 import os
36 import os
37 import pylons_app.lib.helpers as h
37 import pylons_app.lib.helpers as h
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40
40
41 #this is needed to translate the messages using _() in validators
41 #this is needed to translate the messages using _() in validators
42 class State_obj(object):
42 class State_obj(object):
43 _ = staticmethod(_)
43 _ = staticmethod(_)
44
44
45 #===============================================================================
45 #===============================================================================
46 # VALIDATORS
46 # VALIDATORS
47 #===============================================================================
47 #===============================================================================
48 class ValidAuthToken(formencode.validators.FancyValidator):
48 class ValidAuthToken(formencode.validators.FancyValidator):
49 messages = {'invalid_token':_('Token mismatch')}
49 messages = {'invalid_token':_('Token mismatch')}
50
50
51 def validate_python(self, value, state):
51 def validate_python(self, value, state):
52
52
53 if value != authentication_token():
53 if value != authentication_token():
54 raise formencode.Invalid(self.message('invalid_token', state,
54 raise formencode.Invalid(self.message('invalid_token', state,
55 search_number=value), value, state)
55 search_number=value), value, state)
56
56
57 def ValidUsername(edit, old_data):
57 def ValidUsername(edit, old_data):
58 class _ValidUsername(formencode.validators.FancyValidator):
58 class _ValidUsername(formencode.validators.FancyValidator):
59
59
60 def validate_python(self, value, state):
60 def validate_python(self, value, state):
61 if value in ['default', 'new_user']:
61 if value in ['default', 'new_user']:
62 raise formencode.Invalid(_('Invalid username'), value, state)
62 raise formencode.Invalid(_('Invalid username'), value, state)
63 #check if user is uniq
63 #check if user is uniq
64 sa = meta.Session
64 sa = meta.Session
65 old_un = None
65 old_un = None
66 if edit:
66 if edit:
67 old_un = sa.query(User).get(old_data.get('user_id')).username
67 old_un = sa.query(User).get(old_data.get('user_id')).username
68
68
69 if old_un != value or not edit:
69 if old_un != value or not edit:
70 if sa.query(User).filter(User.username == value).scalar():
70 if sa.query(User).filter(User.username == value).scalar():
71 raise formencode.Invalid(_('This username already exists') ,
71 raise formencode.Invalid(_('This username already exists') ,
72 value, state)
72 value, state)
73 meta.Session.remove()
73 meta.Session.remove()
74
74
75 return _ValidUsername
75 return _ValidUsername
76
76
77 class ValidPassword(formencode.validators.FancyValidator):
77 class ValidPassword(formencode.validators.FancyValidator):
78
78
79 def to_python(self, value, state):
79 def to_python(self, value, state):
80 if value:
80 if value:
81 return get_crypt_password(value)
81 return get_crypt_password(value)
82
82
83 class ValidAuth(formencode.validators.FancyValidator):
83 class ValidAuth(formencode.validators.FancyValidator):
84 messages = {
84 messages = {
85 'invalid_password':_('invalid password'),
85 'invalid_password':_('invalid password'),
86 'invalid_login':_('invalid user name'),
86 'invalid_login':_('invalid user name'),
87 'disabled_account':_('Your acccount is disabled')
87 'disabled_account':_('Your acccount is disabled')
88
88
89 }
89 }
90 #error mapping
90 #error mapping
91 e_dict = {'username':messages['invalid_login'],
91 e_dict = {'username':messages['invalid_login'],
92 'password':messages['invalid_password']}
92 'password':messages['invalid_password']}
93 e_dict_disable = {'username':messages['disabled_account']}
93 e_dict_disable = {'username':messages['disabled_account']}
94
94
95 def validate_python(self, value, state):
95 def validate_python(self, value, state):
96 password = value['password']
96 password = value['password']
97 username = value['username']
97 username = value['username']
98 user = UserModel().get_user_by_name(username)
98 user = UserModel().get_user_by_name(username)
99 if user is None:
99 if user is None:
100 raise formencode.Invalid(self.message('invalid_password',
100 raise formencode.Invalid(self.message('invalid_password',
101 state=State_obj), value, state,
101 state=State_obj), value, state,
102 error_dict=self.e_dict)
102 error_dict=self.e_dict)
103 if user:
103 if user:
104 if user.active:
104 if user.active:
105 if user.username == username and check_password(password,
105 if user.username == username and check_password(password,
106 user.password):
106 user.password):
107 return value
107 return value
108 else:
108 else:
109 log.warning('user %s not authenticated', username)
109 log.warning('user %s not authenticated', username)
110 raise formencode.Invalid(self.message('invalid_password',
110 raise formencode.Invalid(self.message('invalid_password',
111 state=State_obj), value, state,
111 state=State_obj), value, state,
112 error_dict=self.e_dict)
112 error_dict=self.e_dict)
113 else:
113 else:
114 log.warning('user %s is disabled', username)
114 log.warning('user %s is disabled', username)
115 raise formencode.Invalid(self.message('disabled_account',
115 raise formencode.Invalid(self.message('disabled_account',
116 state=State_obj),
116 state=State_obj),
117 value, state,
117 value, state,
118 error_dict=self.e_dict_disable)
118 error_dict=self.e_dict_disable)
119
119
120 class ValidRepoUser(formencode.validators.FancyValidator):
120 class ValidRepoUser(formencode.validators.FancyValidator):
121
121
122 def to_python(self, value, state):
122 def to_python(self, value, state):
123 try:
123 try:
124 self.user_db = meta.Session.query(User)\
124 self.user_db = meta.Session.query(User)\
125 .filter(User.active == True)\
125 .filter(User.active == True)\
126 .filter(User.username == value).one()
126 .filter(User.username == value).one()
127 except Exception:
127 except Exception:
128 raise formencode.Invalid(_('This username is not valid'),
128 raise formencode.Invalid(_('This username is not valid'),
129 value, state)
129 value, state)
130 finally:
130 finally:
131 meta.Session.remove()
131 meta.Session.remove()
132
132
133 return self.user_db.user_id
133 return self.user_db.user_id
134
134
135 def ValidRepoName(edit, old_data):
135 def ValidRepoName(edit, old_data):
136 class _ValidRepoName(formencode.validators.FancyValidator):
136 class _ValidRepoName(formencode.validators.FancyValidator):
137
137
138 def to_python(self, value, state):
138 def to_python(self, value, state):
139 slug = h.repo_name_slug(value)
139 slug = h.repo_name_slug(value)
140 if slug in ['_admin']:
140 if slug in ['_admin']:
141 raise formencode.Invalid(_('This repository name is disallowed'),
141 raise formencode.Invalid(_('This repository name is disallowed'),
142 value, state)
142 value, state)
143 if old_data.get('repo_name') != value or not edit:
143 if old_data.get('repo_name') != value or not edit:
144 sa = meta.Session
144 sa = meta.Session
145 if sa.query(Repository).filter(Repository.repo_name == slug).scalar():
145 if sa.query(Repository).filter(Repository.repo_name == slug).scalar():
146 raise formencode.Invalid(_('This repository already exists') ,
146 raise formencode.Invalid(_('This repository already exists') ,
147 value, state)
147 value, state)
148 meta.Session.remove()
148 meta.Session.remove()
149 return slug
149 return slug
150
150
151
151
152 return _ValidRepoName
152 return _ValidRepoName
153
153
154 class ValidPerms(formencode.validators.FancyValidator):
154 class ValidPerms(formencode.validators.FancyValidator):
155 messages = {'perm_new_user_name':_('This username is not valid')}
155 messages = {'perm_new_user_name':_('This username is not valid')}
156
156
157 def to_python(self, value, state):
157 def to_python(self, value, state):
158 perms_update = []
158 perms_update = []
159 perms_new = []
159 perms_new = []
160 #build a list of permission to update and new permission to create
160 #build a list of permission to update and new permission to create
161 for k, v in value.items():
161 for k, v in value.items():
162 if k.startswith('perm_'):
162 if k.startswith('perm_'):
163 if k.startswith('perm_new_user'):
163 if k.startswith('perm_new_user'):
164 new_perm = value.get('perm_new_user', False)
164 new_perm = value.get('perm_new_user', False)
165 new_user = value.get('perm_new_user_name', False)
165 new_user = value.get('perm_new_user_name', False)
166 if new_user and new_perm:
166 if new_user and new_perm:
167 if (new_user, new_perm) not in perms_new:
167 if (new_user, new_perm) not in perms_new:
168 perms_new.append((new_user, new_perm))
168 perms_new.append((new_user, new_perm))
169 else:
169 else:
170 usr = k[5:]
170 usr = k[5:]
171 if usr == 'default':
171 if usr == 'default':
172 if value['private']:
172 if value['private']:
173 #set none for default when updating to private repo
173 #set none for default when updating to private repo
174 v = 'repository.none'
174 v = 'repository.none'
175 perms_update.append((usr, v))
175 perms_update.append((usr, v))
176 value['perms_updates'] = perms_update
176 value['perms_updates'] = perms_update
177 value['perms_new'] = perms_new
177 value['perms_new'] = perms_new
178 sa = meta.Session
178 sa = meta.Session
179 for k, v in perms_new:
179 for k, v in perms_new:
180 try:
180 try:
181 self.user_db = sa.query(User)\
181 self.user_db = sa.query(User)\
182 .filter(User.active == True)\
182 .filter(User.active == True)\
183 .filter(User.username == k).one()
183 .filter(User.username == k).one()
184 except Exception:
184 except Exception:
185 msg = self.message('perm_new_user_name',
185 msg = self.message('perm_new_user_name',
186 state=State_obj)
186 state=State_obj)
187 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
187 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
188 return value
188 return value
189
189
190 class ValidSettings(formencode.validators.FancyValidator):
190 class ValidSettings(formencode.validators.FancyValidator):
191
191
192 def to_python(self, value, state):
192 def to_python(self, value, state):
193 #settings form can't edit user
193 #settings form can't edit user
194 if value.has_key('user'):
194 if value.has_key('user'):
195 del['value']['user']
195 del['value']['user']
196
196
197 return value
197 return value
198
198
199 class ValidPath(formencode.validators.FancyValidator):
199 class ValidPath(formencode.validators.FancyValidator):
200 def to_python(self, value, state):
200 def to_python(self, value, state):
201 isdir = os.path.isdir(value.replace('*', ''))
201 isdir = os.path.isdir(value.replace('*', ''))
202 if (value.endswith('/*') or value.endswith('/**')) and isdir:
202 if (value.endswith('/*') or value.endswith('/**')) and isdir:
203 return value
203 return value
204 elif not isdir:
204 elif not isdir:
205 msg = _('This is not a valid path')
205 msg = _('This is not a valid path')
206 else:
206 else:
207 msg = _('You need to specify * or ** at the end of path (ie. /tmp/*)')
207 msg = _('You need to specify * or ** at the end of path (ie. /tmp/*)')
208
208
209 raise formencode.Invalid(msg, value, state,
209 raise formencode.Invalid(msg, value, state,
210 error_dict={'paths_root_path':msg})
210 error_dict={'paths_root_path':msg})
211
211
212 def UniqSystemEmail(old_data):
212 def UniqSystemEmail(old_data):
213 class _UniqSystemEmail(formencode.validators.FancyValidator):
213 class _UniqSystemEmail(formencode.validators.FancyValidator):
214 def to_python(self, value, state):
214 def to_python(self, value, state):
215 if old_data['email'] != value:
215 if old_data.get('email') != value:
216 sa = meta.Session
216 sa = meta.Session
217 try:
217 try:
218 user = sa.query(User).filter(User.email == value).scalar()
218 user = sa.query(User).filter(User.email == value).scalar()
219 if user:
219 if user:
220 raise formencode.Invalid(_("That e-mail address is already taken") ,
220 raise formencode.Invalid(_("That e-mail address is already taken") ,
221 value, state)
221 value, state)
222 finally:
222 finally:
223 meta.Session.remove()
223 meta.Session.remove()
224
224
225 return value
225 return value
226
226
227 return _UniqSystemEmail
227 return _UniqSystemEmail
228
228
229 class ValidSystemEmail(formencode.validators.FancyValidator):
229 class ValidSystemEmail(formencode.validators.FancyValidator):
230 def to_python(self, value, state):
230 def to_python(self, value, state):
231 sa = meta.Session
231 sa = meta.Session
232 try:
232 try:
233 user = sa.query(User).filter(User.email == value).scalar()
233 user = sa.query(User).filter(User.email == value).scalar()
234 if user is None:
234 if user is None:
235 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
235 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
236 value, state)
236 value, state)
237 finally:
237 finally:
238 meta.Session.remove()
238 meta.Session.remove()
239
239
240 return value
240 return value
241
241
242 #===============================================================================
242 #===============================================================================
243 # FORMS
243 # FORMS
244 #===============================================================================
244 #===============================================================================
245 class LoginForm(formencode.Schema):
245 class LoginForm(formencode.Schema):
246 allow_extra_fields = True
246 allow_extra_fields = True
247 filter_extra_fields = True
247 filter_extra_fields = True
248 username = UnicodeString(
248 username = UnicodeString(
249 strip=True,
249 strip=True,
250 min=3,
250 min=3,
251 not_empty=True,
251 not_empty=True,
252 messages={
252 messages={
253 'empty':_('Please enter a login'),
253 'empty':_('Please enter a login'),
254 'tooShort':_('Enter a value %(min)i characters long or more')}
254 'tooShort':_('Enter a value %(min)i characters long or more')}
255 )
255 )
256
256
257 password = UnicodeString(
257 password = UnicodeString(
258 strip=True,
258 strip=True,
259 min=3,
259 min=3,
260 not_empty=True,
260 not_empty=True,
261 messages={
261 messages={
262 'empty':_('Please enter a password'),
262 'empty':_('Please enter a password'),
263 'tooShort':_('Enter a value %(min)i characters long or more')}
263 'tooShort':_('Enter a value %(min)i characters long or more')}
264 )
264 )
265
265
266
266
267 #chained validators have access to all data
267 #chained validators have access to all data
268 chained_validators = [ValidAuth]
268 chained_validators = [ValidAuth]
269
269
270 def UserForm(edit=False, old_data={}):
270 def UserForm(edit=False, old_data={}):
271 class _UserForm(formencode.Schema):
271 class _UserForm(formencode.Schema):
272 allow_extra_fields = True
272 allow_extra_fields = True
273 filter_extra_fields = True
273 filter_extra_fields = True
274 username = All(UnicodeString(strip=True, min=3, not_empty=True), ValidUsername(edit, old_data))
274 username = All(UnicodeString(strip=True, min=3, not_empty=True), ValidUsername(edit, old_data))
275 if edit:
275 if edit:
276 new_password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
276 new_password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
277 admin = StringBoolean(if_missing=False)
277 admin = StringBoolean(if_missing=False)
278 else:
278 else:
279 password = All(UnicodeString(strip=True, min=8, not_empty=True), ValidPassword)
279 password = All(UnicodeString(strip=True, min=8, not_empty=True), ValidPassword)
280 active = StringBoolean(if_missing=False)
280 active = StringBoolean(if_missing=False)
281 name = UnicodeString(strip=True, min=3, not_empty=True)
281 name = UnicodeString(strip=True, min=3, not_empty=True)
282 lastname = UnicodeString(strip=True, min=3, not_empty=True)
282 lastname = UnicodeString(strip=True, min=3, not_empty=True)
283 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
283 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
284
284
285 return _UserForm
285 return _UserForm
286
286
287 RegisterForm = UserForm
287 RegisterForm = UserForm
288
288
289 def PasswordResetForm():
289 def PasswordResetForm():
290 class _PasswordResetForm(formencode.Schema):
290 class _PasswordResetForm(formencode.Schema):
291 allow_extra_fields = True
291 allow_extra_fields = True
292 filter_extra_fields = True
292 filter_extra_fields = True
293 email = All(ValidSystemEmail(), Email(not_empty=True))
293 email = All(ValidSystemEmail(), Email(not_empty=True))
294 return _PasswordResetForm
294 return _PasswordResetForm
295
295
296 def RepoForm(edit=False, old_data={}):
296 def RepoForm(edit=False, old_data={}):
297 class _RepoForm(formencode.Schema):
297 class _RepoForm(formencode.Schema):
298 allow_extra_fields = True
298 allow_extra_fields = True
299 filter_extra_fields = False
299 filter_extra_fields = False
300 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
300 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
301 description = UnicodeString(strip=True, min=3, not_empty=True)
301 description = UnicodeString(strip=True, min=3, not_empty=True)
302 private = StringBoolean(if_missing=False)
302 private = StringBoolean(if_missing=False)
303
303
304 if edit:
304 if edit:
305 user = All(Int(not_empty=True), ValidRepoUser)
305 user = All(Int(not_empty=True), ValidRepoUser)
306
306
307 chained_validators = [ValidPerms]
307 chained_validators = [ValidPerms]
308 return _RepoForm
308 return _RepoForm
309
309
310 def RepoSettingsForm(edit=False, old_data={}):
310 def RepoSettingsForm(edit=False, old_data={}):
311 class _RepoForm(formencode.Schema):
311 class _RepoForm(formencode.Schema):
312 allow_extra_fields = True
312 allow_extra_fields = True
313 filter_extra_fields = False
313 filter_extra_fields = False
314 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
314 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
315 description = UnicodeString(strip=True, min=3, not_empty=True)
315 description = UnicodeString(strip=True, min=3, not_empty=True)
316 private = StringBoolean(if_missing=False)
316 private = StringBoolean(if_missing=False)
317
317
318 chained_validators = [ValidPerms, ValidSettings]
318 chained_validators = [ValidPerms, ValidSettings]
319 return _RepoForm
319 return _RepoForm
320
320
321
321
322 def ApplicationSettingsForm():
322 def ApplicationSettingsForm():
323 class _ApplicationSettingsForm(formencode.Schema):
323 class _ApplicationSettingsForm(formencode.Schema):
324 allow_extra_fields = True
324 allow_extra_fields = True
325 filter_extra_fields = False
325 filter_extra_fields = False
326 hg_app_title = UnicodeString(strip=True, min=3, not_empty=True)
326 hg_app_title = UnicodeString(strip=True, min=3, not_empty=True)
327 hg_app_realm = UnicodeString(strip=True, min=3, not_empty=True)
327 hg_app_realm = UnicodeString(strip=True, min=3, not_empty=True)
328
328
329 return _ApplicationSettingsForm
329 return _ApplicationSettingsForm
330
330
331 def ApplicationUiSettingsForm():
331 def ApplicationUiSettingsForm():
332 class _ApplicationUiSettingsForm(formencode.Schema):
332 class _ApplicationUiSettingsForm(formencode.Schema):
333 allow_extra_fields = True
333 allow_extra_fields = True
334 filter_extra_fields = False
334 filter_extra_fields = False
335 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
335 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
336 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=3, not_empty=True))
336 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=3, not_empty=True))
337 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
337 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
338 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
338 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
339
339
340 return _ApplicationUiSettingsForm
340 return _ApplicationUiSettingsForm
341
341
342 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
342 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
343 class _DefaultPermissionsForm(formencode.Schema):
343 class _DefaultPermissionsForm(formencode.Schema):
344 allow_extra_fields = True
344 allow_extra_fields = True
345 filter_extra_fields = True
345 filter_extra_fields = True
346 overwrite_default = OneOf(['true', 'false'], if_missing='false')
346 overwrite_default = OneOf(['true', 'false'], if_missing='false')
347 default_perm = OneOf(perms_choices)
347 default_perm = OneOf(perms_choices)
348 default_register = OneOf(register_choices)
348 default_register = OneOf(register_choices)
349 default_create = OneOf(create_choices)
349 default_create = OneOf(create_choices)
350
350
351 return _DefaultPermissionsForm
351 return _DefaultPermissionsForm
General Comments 0
You need to be logged in to leave comments. Login now