##// END OF EJS Templates
fixed bug when user is capable of creating _admin repository which is a link to admin interface
marcink -
r310:fc4027fe default
parent child Browse files
Show More
@@ -1,240 +1,242 b''
1 1 """ this is forms validation classes
2 2 http://formencode.org/module-formencode.validators.html
3 3 for list off all availible validators
4 4
5 5 we can create our own validators
6 6
7 7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 8 pre_validators [] These validators will be applied before the schema
9 9 chained_validators [] These validators will be applied after the schema
10 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 11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 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 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 16 <name> = formencode.validators.<name of validator>
17 17 <name> must equal form name
18 18 list=[1,2,3,4,5]
19 19 for SELECT use formencode.All(OneOf(list), Int())
20 20
21 21 """
22 22 from formencode import All
23 23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
24 24 Email, Bool, StringBoolean
25 25 from pylons import session
26 26 from pylons.i18n.translation import _
27 27 from pylons_app.lib.auth import get_crypt_password
28 28 import pylons_app.lib.helpers as h
29 29 from pylons_app.model import meta
30 30 from pylons_app.model.db import User, Repository
31 31 from sqlalchemy.exc import OperationalError
32 32 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
33 33 from webhelpers.pylonslib.secure_form import authentication_token
34 34 import datetime
35 35 import formencode
36 36 import logging
37 37 log = logging.getLogger(__name__)
38 38
39 39
40 40 #this is needed to translate the messages using _() in validators
41 41 class State_obj(object):
42 42 _ = staticmethod(_)
43 43
44 44 #===============================================================================
45 45 # VALIDATORS
46 46 #===============================================================================
47 47 class ValidAuthToken(formencode.validators.FancyValidator):
48 48 messages = {'invalid_token':_('Token mismatch')}
49 49
50 50 def validate_python(self, value, state):
51 51
52 52 if value != authentication_token():
53 53 raise formencode.Invalid(self.message('invalid_token', state,
54 54 search_number=value), value, state)
55 55 class ValidUsername(formencode.validators.FancyValidator):
56 56
57 57 def validate_python(self, value, state):
58 58 if value in ['default', 'new_user']:
59 59 raise formencode.Invalid(_('Invalid username'), value, state)
60 60
61 61 class ValidPassword(formencode.validators.FancyValidator):
62 62
63 63 def to_python(self, value, state):
64 64 return get_crypt_password(value)
65 65
66 66 class ValidAuth(formencode.validators.FancyValidator):
67 67 messages = {
68 68 'invalid_password':_('invalid password'),
69 69 'invalid_login':_('invalid user name'),
70 70 'disabled_account':_('Your acccount is disabled')
71 71
72 72 }
73 73 #error mapping
74 74 e_dict = {'username':messages['invalid_login'],
75 75 'password':messages['invalid_password']}
76 76 e_dict_disable = {'username':messages['disabled_account']}
77 77
78 78 def validate_python(self, value, state):
79 79 sa = meta.Session
80 80 crypted_passwd = get_crypt_password(value['password'])
81 81 username = value['username']
82 82 try:
83 83 user = sa.query(User).filter(User.username == username).one()
84 84 except (NoResultFound, MultipleResultsFound, OperationalError) as e:
85 85 log.error(e)
86 86 user = None
87 87 raise formencode.Invalid(self.message('invalid_password',
88 88 state=State_obj), value, state,
89 89 error_dict=self.e_dict)
90 90 if user:
91 91 if user.active:
92 92 if user.username == username and user.password == crypted_passwd:
93 93 from pylons_app.lib.auth import AuthUser
94 94 auth_user = AuthUser()
95 95 auth_user.username = username
96 96 auth_user.is_authenticated = True
97 97 auth_user.is_admin = user.admin
98 98 auth_user.user_id = user.user_id
99 99 session['hg_app_user'] = auth_user
100 100 session.save()
101 101 log.info('user %s is now authenticated', username)
102 102
103 103 try:
104 104 user.last_login = datetime.datetime.now()
105 105 sa.add(user)
106 106 sa.commit()
107 107 except (OperationalError) as e:
108 108 log.error(e)
109 109 sa.rollback()
110 110
111 111 return value
112 112 else:
113 113 log.warning('user %s not authenticated', username)
114 114 raise formencode.Invalid(self.message('invalid_password',
115 115 state=State_obj), value, state,
116 116 error_dict=self.e_dict)
117 117 else:
118 118 log.warning('user %s is disabled', username)
119 119 raise formencode.Invalid(self.message('disabled_account',
120 120 state=State_obj),
121 121 value, state,
122 122 error_dict=self.e_dict_disable)
123 123
124 124
125 125 class ValidRepoUser(formencode.validators.FancyValidator):
126 126
127 127 def to_python(self, value, state):
128 128 sa = meta.Session
129 129 try:
130 130 self.user_db = sa.query(User).filter(User.username == value).one()
131 131 except Exception:
132 132 raise formencode.Invalid(_('This username is not valid'),
133 133 value, state)
134 134 return self.user_db.user_id
135 135
136 136 def ValidRepoName(edit=False):
137 137 class _ValidRepoName(formencode.validators.FancyValidator):
138 138
139 139 def to_python(self, value, state):
140 140 slug = h.repo_name_slug(value)
141
141 if slug in ['_admin']:
142 raise formencode.Invalid(_('This repository name is disallowed'),
143 value, state)
142 144 sa = meta.Session
143 145 if sa.query(Repository).get(slug) and not edit:
144 146 raise formencode.Invalid(_('This repository already exists'),
145 147 value, state)
146 148
147 149 return slug
148 150 return _ValidRepoName
149 151
150 152 class ValidPerms(formencode.validators.FancyValidator):
151 153 messages = {'perm_new_user_name':_('This username is not valid')}
152 154
153 155 def to_python(self, value, state):
154 156 perms_update = []
155 157 perms_new = []
156 158 #build a list of permission to update and new permission to create
157 159 for k, v in value.items():
158 160 if k.startswith('perm_'):
159 161 if k.startswith('perm_new_user'):
160 162 new_perm = value.get('perm_new_user', False)
161 163 new_user = value.get('perm_new_user_name', False)
162 164 if new_user and new_perm:
163 165 if (new_user, new_perm) not in perms_new:
164 166 perms_new.append((new_user, new_perm))
165 167 else:
166 168 usr = k[5:]
167 169 if usr == 'default':
168 170 if value['private']:
169 171 #set none for default when updating to private repo
170 172 v = 'repository.none'
171 173 perms_update.append((usr, v))
172 174 value['perms_updates'] = perms_update
173 175 value['perms_new'] = perms_new
174 176 sa = meta.Session
175 177 for k, v in perms_new:
176 178 try:
177 179 self.user_db = sa.query(User).filter(User.username == k).one()
178 180 except Exception:
179 181 msg = self.message('perm_new_user_name',
180 182 state=State_obj)
181 183 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
182 184 return value
183 185
184 186 #===============================================================================
185 187 # FORMS
186 188 #===============================================================================
187 189 class LoginForm(formencode.Schema):
188 190 allow_extra_fields = True
189 191 filter_extra_fields = True
190 192 username = UnicodeString(
191 193 strip=True,
192 194 min=3,
193 195 not_empty=True,
194 196 messages={
195 197 'empty':_('Please enter a login'),
196 198 'tooShort':_('Enter a value %(min)i characters long or more')}
197 199 )
198 200
199 201 password = UnicodeString(
200 202 strip=True,
201 203 min=3,
202 204 not_empty=True,
203 205 messages={
204 206 'empty':_('Please enter a password'),
205 207 'tooShort':_('Enter a value %(min)i characters long or more')}
206 208 )
207 209
208 210
209 211 #chained validators have access to all data
210 212 chained_validators = [ValidAuth]
211 213
212 214 def UserForm(edit=False):
213 215 class _UserForm(formencode.Schema):
214 216 allow_extra_fields = True
215 217 filter_extra_fields = True
216 218 username = All(UnicodeString(strip=True, min=3, not_empty=True), ValidUsername)
217 219 if edit:
218 220 new_password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
219 221 else:
220 222 password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
221 223 active = StringBoolean(if_missing=False)
222 224 name = UnicodeString(strip=True, min=3, not_empty=True)
223 225 lastname = UnicodeString(strip=True, min=3, not_empty=True)
224 226 email = Email(not_empty=True)
225 227
226 228 return _UserForm
227 229
228 230 def RepoForm(edit=False):
229 231 class _RepoForm(formencode.Schema):
230 232 allow_extra_fields = True
231 233 filter_extra_fields = False
232 234 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit))
233 235 description = UnicodeString(strip=True, min=3, not_empty=True)
234 236 private = StringBoolean(if_missing=False)
235 237
236 238 if edit:
237 239 user = All(Int(not_empty=True), ValidRepoUser)
238 240
239 241 chained_validators = [ValidPerms]
240 242 return _RepoForm
General Comments 0
You need to be logged in to leave comments. Login now