##// END OF EJS Templates
#56 hacking on forms, and model for users groups
marcink -
r1013:d2a840b2 beta
parent child Browse files
Show More
@@ -1,535 +1,546 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 os
22 import os
23 import re
23 import re
24 import logging
24 import logging
25
25
26 import formencode
26 import formencode
27 from formencode import All
27 from formencode import All
28 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
28 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
29 Email, Bool, StringBoolean, Set
29 Email, Bool, StringBoolean, Set
30
30
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32
32
33 import rhodecode.lib.helpers as h
33 import rhodecode.lib.helpers as h
34 from rhodecode.lib.auth import authenticate, get_crypt_password
34 from rhodecode.lib.auth import authenticate, get_crypt_password
35 from rhodecode.lib.exceptions import LdapImportError
35 from rhodecode.lib.exceptions import LdapImportError
36 from rhodecode.model import meta
36 from rhodecode.model import meta
37 from rhodecode.model.user import UserModel
37 from rhodecode.model.user import UserModel
38 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.repo import RepoModel
39 from rhodecode.model.users_group import UsersGroupModel
39 from rhodecode.model.users_group import UsersGroupModel
40 from rhodecode.model.db import User
40 from rhodecode.model.db import User, UsersGroup
41 from rhodecode import BACKENDS
41 from rhodecode import BACKENDS
42
42
43 from webhelpers.pylonslib.secure_form import authentication_token
43 from webhelpers.pylonslib.secure_form import authentication_token
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
46
46
47 #this is needed to translate the messages using _() in validators
47 #this is needed to translate the messages using _() in validators
48 class State_obj(object):
48 class State_obj(object):
49 _ = staticmethod(_)
49 _ = staticmethod(_)
50
50
51 #===============================================================================
51 #===============================================================================
52 # VALIDATORS
52 # VALIDATORS
53 #===============================================================================
53 #===============================================================================
54 class ValidAuthToken(formencode.validators.FancyValidator):
54 class ValidAuthToken(formencode.validators.FancyValidator):
55 messages = {'invalid_token':_('Token mismatch')}
55 messages = {'invalid_token':_('Token mismatch')}
56
56
57 def validate_python(self, value, state):
57 def validate_python(self, value, state):
58
58
59 if value != authentication_token():
59 if value != authentication_token():
60 raise formencode.Invalid(self.message('invalid_token', state,
60 raise formencode.Invalid(self.message('invalid_token', state,
61 search_number=value), value, state)
61 search_number=value), value, state)
62
62
63 def ValidUsername(edit, old_data):
63 def ValidUsername(edit, old_data):
64 class _ValidUsername(formencode.validators.FancyValidator):
64 class _ValidUsername(formencode.validators.FancyValidator):
65
65
66 def validate_python(self, value, state):
66 def validate_python(self, value, state):
67 if value in ['default', 'new_user']:
67 if value in ['default', 'new_user']:
68 raise formencode.Invalid(_('Invalid username'), value, state)
68 raise formencode.Invalid(_('Invalid username'), value, state)
69 #check if user is unique
69 #check if user is unique
70 old_un = None
70 old_un = None
71 if edit:
71 if edit:
72 old_un = UserModel().get(old_data.get('user_id')).username
72 old_un = UserModel().get(old_data.get('user_id')).username
73
73
74 if old_un != value or not edit:
74 if old_un != value or not edit:
75 if UserModel().get_by_username(value, cache=False,
75 if UserModel().get_by_username(value, cache=False,
76 case_insensitive=True):
76 case_insensitive=True):
77 raise formencode.Invalid(_('This username already exists') ,
77 raise formencode.Invalid(_('This username already exists') ,
78 value, state)
78 value, state)
79
79
80
80
81 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
81 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
82 raise formencode.Invalid(_('Username may only contain '
82 raise formencode.Invalid(_('Username may only contain '
83 'alphanumeric characters underscores, '
83 'alphanumeric characters underscores, '
84 'periods or dashes and must begin with '
84 'periods or dashes and must begin with '
85 'alphanumeric character'),
85 'alphanumeric character'),
86 value, state)
86 value, state)
87
87
88
88
89
89
90 return _ValidUsername
90 return _ValidUsername
91
91
92
92
93
93
94 def ValidUsersGroup(edit, old_data):
94 def ValidUsersGroup(edit, old_data):
95
95
96 class _ValidUsersGroup(formencode.validators.FancyValidator):
96 class _ValidUsersGroup(formencode.validators.FancyValidator):
97
97
98 def validate_python(self, value, state):
98 def validate_python(self, value, state):
99 if value in ['default']:
99 if value in ['default']:
100 raise formencode.Invalid(_('Invalid group name'), value, state)
100 raise formencode.Invalid(_('Invalid group name'), value, state)
101 #check if group is unique
101 #check if group is unique
102 old_ugname = None
102 old_ugname = None
103 if edit:
103 if edit:
104 old_ugname = UsersGroupModel()\
104 old_ugname = UsersGroupModel()\
105 .get(old_data.get('users_group_id')).users_group_name
105 .get(old_data.get('users_group_id')).users_group_name
106
106
107 if old_ugname != value or not edit:
107 if old_ugname != value or not edit:
108 if UsersGroupModel().get_by_groupname(value, cache=False,
108 if UsersGroupModel().get_by_groupname(value, cache=False,
109 case_insensitive=True):
109 case_insensitive=True):
110 raise formencode.Invalid(_('This users group already exists') ,
110 raise formencode.Invalid(_('This users group already exists') ,
111 value, state)
111 value, state)
112
112
113
113
114 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
114 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
115 raise formencode.Invalid(_('Group name may only contain '
115 raise formencode.Invalid(_('Group name may only contain '
116 'alphanumeric characters underscores, '
116 'alphanumeric characters underscores, '
117 'periods or dashes and must begin with '
117 'periods or dashes and must begin with '
118 'alphanumeric character'),
118 'alphanumeric character'),
119 value, state)
119 value, state)
120
120
121 return _ValidUsersGroup
121 return _ValidUsersGroup
122
122
123
123
124
124
125 class ValidPassword(formencode.validators.FancyValidator):
125 class ValidPassword(formencode.validators.FancyValidator):
126
126
127 def to_python(self, value, state):
127 def to_python(self, value, state):
128
128
129 if value:
129 if value:
130
130
131 if value.get('password'):
131 if value.get('password'):
132 try:
132 try:
133 value['password'] = get_crypt_password(value['password'])
133 value['password'] = get_crypt_password(value['password'])
134 except UnicodeEncodeError:
134 except UnicodeEncodeError:
135 e_dict = {'password':_('Invalid characters in password')}
135 e_dict = {'password':_('Invalid characters in password')}
136 raise formencode.Invalid('', value, state, error_dict=e_dict)
136 raise formencode.Invalid('', value, state, error_dict=e_dict)
137
137
138 if value.get('password_confirmation'):
138 if value.get('password_confirmation'):
139 try:
139 try:
140 value['password_confirmation'] = \
140 value['password_confirmation'] = \
141 get_crypt_password(value['password_confirmation'])
141 get_crypt_password(value['password_confirmation'])
142 except UnicodeEncodeError:
142 except UnicodeEncodeError:
143 e_dict = {'password_confirmation':_('Invalid characters in password')}
143 e_dict = {'password_confirmation':_('Invalid characters in password')}
144 raise formencode.Invalid('', value, state, error_dict=e_dict)
144 raise formencode.Invalid('', value, state, error_dict=e_dict)
145
145
146 if value.get('new_password'):
146 if value.get('new_password'):
147 try:
147 try:
148 value['new_password'] = \
148 value['new_password'] = \
149 get_crypt_password(value['new_password'])
149 get_crypt_password(value['new_password'])
150 except UnicodeEncodeError:
150 except UnicodeEncodeError:
151 e_dict = {'new_password':_('Invalid characters in password')}
151 e_dict = {'new_password':_('Invalid characters in password')}
152 raise formencode.Invalid('', value, state, error_dict=e_dict)
152 raise formencode.Invalid('', value, state, error_dict=e_dict)
153
153
154 return value
154 return value
155
155
156 class ValidPasswordsMatch(formencode.validators.FancyValidator):
156 class ValidPasswordsMatch(formencode.validators.FancyValidator):
157
157
158 def validate_python(self, value, state):
158 def validate_python(self, value, state):
159
159
160 if value['password'] != value['password_confirmation']:
160 if value['password'] != value['password_confirmation']:
161 e_dict = {'password_confirmation':
161 e_dict = {'password_confirmation':
162 _('Password do not match')}
162 _('Password do not match')}
163 raise formencode.Invalid('', value, state, error_dict=e_dict)
163 raise formencode.Invalid('', value, state, error_dict=e_dict)
164
164
165 class ValidAuth(formencode.validators.FancyValidator):
165 class ValidAuth(formencode.validators.FancyValidator):
166 messages = {
166 messages = {
167 'invalid_password':_('invalid password'),
167 'invalid_password':_('invalid password'),
168 'invalid_login':_('invalid user name'),
168 'invalid_login':_('invalid user name'),
169 'disabled_account':_('Your account is disabled')
169 'disabled_account':_('Your account is disabled')
170
170
171 }
171 }
172 #error mapping
172 #error mapping
173 e_dict = {'username':messages['invalid_login'],
173 e_dict = {'username':messages['invalid_login'],
174 'password':messages['invalid_password']}
174 'password':messages['invalid_password']}
175 e_dict_disable = {'username':messages['disabled_account']}
175 e_dict_disable = {'username':messages['disabled_account']}
176
176
177 def validate_python(self, value, state):
177 def validate_python(self, value, state):
178 password = value['password']
178 password = value['password']
179 username = value['username']
179 username = value['username']
180 user = UserModel().get_by_username(username)
180 user = UserModel().get_by_username(username)
181
181
182 if authenticate(username, password):
182 if authenticate(username, password):
183 return value
183 return value
184 else:
184 else:
185 if user and user.active is False:
185 if user and user.active is False:
186 log.warning('user %s is disabled', username)
186 log.warning('user %s is disabled', username)
187 raise formencode.Invalid(self.message('disabled_account',
187 raise formencode.Invalid(self.message('disabled_account',
188 state=State_obj),
188 state=State_obj),
189 value, state,
189 value, state,
190 error_dict=self.e_dict_disable)
190 error_dict=self.e_dict_disable)
191 else:
191 else:
192 log.warning('user %s not authenticated', username)
192 log.warning('user %s not authenticated', username)
193 raise formencode.Invalid(self.message('invalid_password',
193 raise formencode.Invalid(self.message('invalid_password',
194 state=State_obj), value, state,
194 state=State_obj), value, state,
195 error_dict=self.e_dict)
195 error_dict=self.e_dict)
196
196
197 class ValidRepoUser(formencode.validators.FancyValidator):
197 class ValidRepoUser(formencode.validators.FancyValidator):
198
198
199 def to_python(self, value, state):
199 def to_python(self, value, state):
200 sa = meta.Session()
200 sa = meta.Session()
201 try:
201 try:
202 self.user_db = sa.query(User)\
202 self.user_db = sa.query(User)\
203 .filter(User.active == True)\
203 .filter(User.active == True)\
204 .filter(User.username == value).one()
204 .filter(User.username == value).one()
205 except Exception:
205 except Exception:
206 raise formencode.Invalid(_('This username is not valid'),
206 raise formencode.Invalid(_('This username is not valid'),
207 value, state)
207 value, state)
208 finally:
208 finally:
209 meta.Session.remove()
209 meta.Session.remove()
210
210
211 return self.user_db.user_id
211 return self.user_db.user_id
212
212
213 def ValidRepoName(edit, old_data):
213 def ValidRepoName(edit, old_data):
214 class _ValidRepoName(formencode.validators.FancyValidator):
214 class _ValidRepoName(formencode.validators.FancyValidator):
215
215
216 def to_python(self, value, state):
216 def to_python(self, value, state):
217 slug = h.repo_name_slug(value)
217 slug = h.repo_name_slug(value)
218 if slug in ['_admin']:
218 if slug in ['_admin']:
219 raise formencode.Invalid(_('This repository name is disallowed'),
219 raise formencode.Invalid(_('This repository name is disallowed'),
220 value, state)
220 value, state)
221 if old_data.get('repo_name') != value or not edit:
221 if old_data.get('repo_name') != value or not edit:
222 if RepoModel().get_by_repo_name(slug, cache=False):
222 if RepoModel().get_by_repo_name(slug, cache=False):
223 raise formencode.Invalid(_('This repository already exists') ,
223 raise formencode.Invalid(_('This repository already exists') ,
224 value, state)
224 value, state)
225 return slug
225 return slug
226
226
227
227
228 return _ValidRepoName
228 return _ValidRepoName
229
229
230 def ValidForkType(old_data):
230 def ValidForkType(old_data):
231 class _ValidForkType(formencode.validators.FancyValidator):
231 class _ValidForkType(formencode.validators.FancyValidator):
232
232
233 def to_python(self, value, state):
233 def to_python(self, value, state):
234 if old_data['repo_type'] != value:
234 if old_data['repo_type'] != value:
235 raise formencode.Invalid(_('Fork have to be the same type as original'),
235 raise formencode.Invalid(_('Fork have to be the same type as original'),
236 value, state)
236 value, state)
237 return value
237 return value
238 return _ValidForkType
238 return _ValidForkType
239
239
240 class ValidPerms(formencode.validators.FancyValidator):
240 class ValidPerms(formencode.validators.FancyValidator):
241 messages = {'perm_new_user_name':_('This username is not valid')}
241 messages = {'perm_new_member_name':_('This username or users group name'
242 ' is not valid')}
242
243
243 def to_python(self, value, state):
244 def to_python(self, value, state):
244 perms_update = []
245 perms_update = []
245 perms_new = []
246 perms_new = []
246 #build a list of permission to update and new permission to create
247 #build a list of permission to update and new permission to create
247 for k, v in value.items():
248 for k, v in value.items():
248 if k.startswith('perm_'):
249 if k.startswith('perm_'):
249 if k.startswith('perm_new_user'):
250 if k.startswith('perm_new_member'):
250 new_perm = value.get('perm_new_user', False)
251 #means new added member to permissions
251 new_user = value.get('perm_new_user_name', False)
252 new_perm = value.get('perm_new_member', False)
252 if new_user and new_perm:
253 new_member = value.get('perm_new_member_name', False)
253 if (new_user, new_perm) not in perms_new:
254 new_type = value.get('perm_new_member_type')
254 perms_new.append((new_user, new_perm))
255
256 if new_member and new_perm:
257 if (new_member, new_perm) not in perms_new:
258 perms_new.append((new_member, new_perm, new_type))
255 else:
259 else:
256 usr = k[5:]
260 usr = k[5:]
261 t = 'user'
257 if usr == 'default':
262 if usr == 'default':
258 if value['private']:
263 if value['private']:
259 #set none for default when updating to private repo
264 #set none for default when updating to private repo
260 v = 'repository.none'
265 v = 'repository.none'
261 perms_update.append((usr, v))
266 perms_update.append((usr, v, t))
262 value['perms_updates'] = perms_update
267 value['perms_updates'] = perms_update
263 value['perms_new'] = perms_new
268 value['perms_new'] = perms_new
264 sa = meta.Session
269 sa = meta.Session
265 for k, v in perms_new:
270 for k, v, t in perms_new:
266 try:
271 try:
267 self.user_db = sa.query(User)\
272 if t is 'user':
268 .filter(User.active == True)\
273 self.user_db = sa.query(User)\
269 .filter(User.username == k).one()
274 .filter(User.active == True)\
275 .filter(User.username == k).one()
276 if t is 'users_group':
277 self.user_db = sa.query(UsersGroup)\
278 .filter(UsersGroup.users_group_active == True)\
279 .filter(UsersGroup.users_group_name == k).one()
280
270 except Exception:
281 except Exception:
271 msg = self.message('perm_new_user_name',
282 msg = self.message('perm_new_member_name',
272 state=State_obj)
283 state=State_obj)
273 raise formencode.Invalid(msg, value, state,
284 raise formencode.Invalid(msg, value, state,
274 error_dict={'perm_new_user_name':msg})
285 error_dict={'perm_new_member_name':msg})
275 return value
286 return value
276
287
277 class ValidSettings(formencode.validators.FancyValidator):
288 class ValidSettings(formencode.validators.FancyValidator):
278
289
279 def to_python(self, value, state):
290 def to_python(self, value, state):
280 #settings form can't edit user
291 #settings form can't edit user
281 if value.has_key('user'):
292 if value.has_key('user'):
282 del['value']['user']
293 del['value']['user']
283
294
284 return value
295 return value
285
296
286 class ValidPath(formencode.validators.FancyValidator):
297 class ValidPath(formencode.validators.FancyValidator):
287 def to_python(self, value, state):
298 def to_python(self, value, state):
288
299
289 if not os.path.isdir(value):
300 if not os.path.isdir(value):
290 msg = _('This is not a valid path')
301 msg = _('This is not a valid path')
291 raise formencode.Invalid(msg, value, state,
302 raise formencode.Invalid(msg, value, state,
292 error_dict={'paths_root_path':msg})
303 error_dict={'paths_root_path':msg})
293 return value
304 return value
294
305
295 def UniqSystemEmail(old_data):
306 def UniqSystemEmail(old_data):
296 class _UniqSystemEmail(formencode.validators.FancyValidator):
307 class _UniqSystemEmail(formencode.validators.FancyValidator):
297 def to_python(self, value, state):
308 def to_python(self, value, state):
298 value = value.lower()
309 value = value.lower()
299 if old_data.get('email') != value:
310 if old_data.get('email') != value:
300 sa = meta.Session()
311 sa = meta.Session()
301 try:
312 try:
302 user = sa.query(User).filter(User.email == value).scalar()
313 user = sa.query(User).filter(User.email == value).scalar()
303 if user:
314 if user:
304 raise formencode.Invalid(_("This e-mail address is already taken") ,
315 raise formencode.Invalid(_("This e-mail address is already taken") ,
305 value, state)
316 value, state)
306 finally:
317 finally:
307 meta.Session.remove()
318 meta.Session.remove()
308
319
309 return value
320 return value
310
321
311 return _UniqSystemEmail
322 return _UniqSystemEmail
312
323
313 class ValidSystemEmail(formencode.validators.FancyValidator):
324 class ValidSystemEmail(formencode.validators.FancyValidator):
314 def to_python(self, value, state):
325 def to_python(self, value, state):
315 value = value.lower()
326 value = value.lower()
316 sa = meta.Session
327 sa = meta.Session
317 try:
328 try:
318 user = sa.query(User).filter(User.email == value).scalar()
329 user = sa.query(User).filter(User.email == value).scalar()
319 if user is None:
330 if user is None:
320 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
331 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
321 value, state)
332 value, state)
322 finally:
333 finally:
323 meta.Session.remove()
334 meta.Session.remove()
324
335
325 return value
336 return value
326
337
327 class LdapLibValidator(formencode.validators.FancyValidator):
338 class LdapLibValidator(formencode.validators.FancyValidator):
328
339
329 def to_python(self, value, state):
340 def to_python(self, value, state):
330
341
331 try:
342 try:
332 import ldap
343 import ldap
333 except ImportError:
344 except ImportError:
334 raise LdapImportError
345 raise LdapImportError
335 return value
346 return value
336
347
337 class AttrLoginValidator(formencode.validators.FancyValidator):
348 class AttrLoginValidator(formencode.validators.FancyValidator):
338
349
339 def to_python(self, value, state):
350 def to_python(self, value, state):
340
351
341 if not value or not isinstance(value, (str, unicode)):
352 if not value or not isinstance(value, (str, unicode)):
342 raise formencode.Invalid(_("The LDAP Login attribute of the CN must be specified "
353 raise formencode.Invalid(_("The LDAP Login attribute of the CN must be specified "
343 "- this is the name of the attribute that is equivalent to 'username'"),
354 "- this is the name of the attribute that is equivalent to 'username'"),
344 value, state)
355 value, state)
345
356
346 return value
357 return value
347
358
348 #===============================================================================
359 #===============================================================================
349 # FORMS
360 # FORMS
350 #===============================================================================
361 #===============================================================================
351 class LoginForm(formencode.Schema):
362 class LoginForm(formencode.Schema):
352 allow_extra_fields = True
363 allow_extra_fields = True
353 filter_extra_fields = True
364 filter_extra_fields = True
354 username = UnicodeString(
365 username = UnicodeString(
355 strip=True,
366 strip=True,
356 min=1,
367 min=1,
357 not_empty=True,
368 not_empty=True,
358 messages={
369 messages={
359 'empty':_('Please enter a login'),
370 'empty':_('Please enter a login'),
360 'tooShort':_('Enter a value %(min)i characters long or more')}
371 'tooShort':_('Enter a value %(min)i characters long or more')}
361 )
372 )
362
373
363 password = UnicodeString(
374 password = UnicodeString(
364 strip=True,
375 strip=True,
365 min=6,
376 min=6,
366 not_empty=True,
377 not_empty=True,
367 messages={
378 messages={
368 'empty':_('Please enter a password'),
379 'empty':_('Please enter a password'),
369 'tooShort':_('Enter %(min)i characters or more')}
380 'tooShort':_('Enter %(min)i characters or more')}
370 )
381 )
371
382
372
383
373 #chained validators have access to all data
384 #chained validators have access to all data
374 chained_validators = [ValidAuth]
385 chained_validators = [ValidAuth]
375
386
376 def UserForm(edit=False, old_data={}):
387 def UserForm(edit=False, old_data={}):
377 class _UserForm(formencode.Schema):
388 class _UserForm(formencode.Schema):
378 allow_extra_fields = True
389 allow_extra_fields = True
379 filter_extra_fields = True
390 filter_extra_fields = True
380 username = All(UnicodeString(strip=True, min=1, not_empty=True),
391 username = All(UnicodeString(strip=True, min=1, not_empty=True),
381 ValidUsername(edit, old_data))
392 ValidUsername(edit, old_data))
382 if edit:
393 if edit:
383 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
394 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
384 admin = StringBoolean(if_missing=False)
395 admin = StringBoolean(if_missing=False)
385 else:
396 else:
386 password = All(UnicodeString(strip=True, min=6, not_empty=True))
397 password = All(UnicodeString(strip=True, min=6, not_empty=True))
387 active = StringBoolean(if_missing=False)
398 active = StringBoolean(if_missing=False)
388 name = UnicodeString(strip=True, min=1, not_empty=True)
399 name = UnicodeString(strip=True, min=1, not_empty=True)
389 lastname = UnicodeString(strip=True, min=1, not_empty=True)
400 lastname = UnicodeString(strip=True, min=1, not_empty=True)
390 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
401 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
391
402
392 chained_validators = [ValidPassword]
403 chained_validators = [ValidPassword]
393
404
394 return _UserForm
405 return _UserForm
395
406
396
407
397 def UsersGroupForm(edit=False, old_data={}, available_members=[]):
408 def UsersGroupForm(edit=False, old_data={}, available_members=[]):
398 class _UsersGroupForm(formencode.Schema):
409 class _UsersGroupForm(formencode.Schema):
399 allow_extra_fields = True
410 allow_extra_fields = True
400 filter_extra_fields = True
411 filter_extra_fields = True
401
412
402 users_group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
413 users_group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
403 ValidUsersGroup(edit, old_data))
414 ValidUsersGroup(edit, old_data))
404
415
405 users_group_active = StringBoolean(if_missing=False)
416 users_group_active = StringBoolean(if_missing=False)
406
417
407 if edit:
418 if edit:
408 users_group_members = OneOf(available_members, hideList=False,
419 users_group_members = OneOf(available_members, hideList=False,
409 testValueList=True,
420 testValueList=True,
410 if_missing=None, not_empty=False)
421 if_missing=None, not_empty=False)
411
422
412 return _UsersGroupForm
423 return _UsersGroupForm
413
424
414 def RegisterForm(edit=False, old_data={}):
425 def RegisterForm(edit=False, old_data={}):
415 class _RegisterForm(formencode.Schema):
426 class _RegisterForm(formencode.Schema):
416 allow_extra_fields = True
427 allow_extra_fields = True
417 filter_extra_fields = True
428 filter_extra_fields = True
418 username = All(ValidUsername(edit, old_data),
429 username = All(ValidUsername(edit, old_data),
419 UnicodeString(strip=True, min=1, not_empty=True))
430 UnicodeString(strip=True, min=1, not_empty=True))
420 password = All(UnicodeString(strip=True, min=6, not_empty=True))
431 password = All(UnicodeString(strip=True, min=6, not_empty=True))
421 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
432 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
422 active = StringBoolean(if_missing=False)
433 active = StringBoolean(if_missing=False)
423 name = UnicodeString(strip=True, min=1, not_empty=True)
434 name = UnicodeString(strip=True, min=1, not_empty=True)
424 lastname = UnicodeString(strip=True, min=1, not_empty=True)
435 lastname = UnicodeString(strip=True, min=1, not_empty=True)
425 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
436 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
426
437
427 chained_validators = [ValidPasswordsMatch, ValidPassword]
438 chained_validators = [ValidPasswordsMatch, ValidPassword]
428
439
429 return _RegisterForm
440 return _RegisterForm
430
441
431 def PasswordResetForm():
442 def PasswordResetForm():
432 class _PasswordResetForm(formencode.Schema):
443 class _PasswordResetForm(formencode.Schema):
433 allow_extra_fields = True
444 allow_extra_fields = True
434 filter_extra_fields = True
445 filter_extra_fields = True
435 email = All(ValidSystemEmail(), Email(not_empty=True))
446 email = All(ValidSystemEmail(), Email(not_empty=True))
436 return _PasswordResetForm
447 return _PasswordResetForm
437
448
438 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
449 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
439 class _RepoForm(formencode.Schema):
450 class _RepoForm(formencode.Schema):
440 allow_extra_fields = True
451 allow_extra_fields = True
441 filter_extra_fields = False
452 filter_extra_fields = False
442 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
453 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
443 ValidRepoName(edit, old_data))
454 ValidRepoName(edit, old_data))
444 description = UnicodeString(strip=True, min=1, not_empty=True)
455 description = UnicodeString(strip=True, min=1, not_empty=True)
445 private = StringBoolean(if_missing=False)
456 private = StringBoolean(if_missing=False)
446 enable_statistics = StringBoolean(if_missing=False)
457 enable_statistics = StringBoolean(if_missing=False)
447 enable_downloads = StringBoolean(if_missing=False)
458 enable_downloads = StringBoolean(if_missing=False)
448 repo_type = OneOf(supported_backends)
459 repo_type = OneOf(supported_backends)
449 if edit:
460 if edit:
450 user = All(Int(not_empty=True), ValidRepoUser)
461 user = All(Int(not_empty=True), ValidRepoUser)
451
462
452 chained_validators = [ValidPerms]
463 chained_validators = [ValidPerms]
453 return _RepoForm
464 return _RepoForm
454
465
455 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
466 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
456 class _RepoForkForm(formencode.Schema):
467 class _RepoForkForm(formencode.Schema):
457 allow_extra_fields = True
468 allow_extra_fields = True
458 filter_extra_fields = False
469 filter_extra_fields = False
459 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
470 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
460 ValidRepoName(edit, old_data))
471 ValidRepoName(edit, old_data))
461 description = UnicodeString(strip=True, min=1, not_empty=True)
472 description = UnicodeString(strip=True, min=1, not_empty=True)
462 private = StringBoolean(if_missing=False)
473 private = StringBoolean(if_missing=False)
463 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
474 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
464 return _RepoForkForm
475 return _RepoForkForm
465
476
466 def RepoSettingsForm(edit=False, old_data={}):
477 def RepoSettingsForm(edit=False, old_data={}):
467 class _RepoForm(formencode.Schema):
478 class _RepoForm(formencode.Schema):
468 allow_extra_fields = True
479 allow_extra_fields = True
469 filter_extra_fields = False
480 filter_extra_fields = False
470 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
481 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
471 ValidRepoName(edit, old_data))
482 ValidRepoName(edit, old_data))
472 description = UnicodeString(strip=True, min=1, not_empty=True)
483 description = UnicodeString(strip=True, min=1, not_empty=True)
473 private = StringBoolean(if_missing=False)
484 private = StringBoolean(if_missing=False)
474
485
475 chained_validators = [ValidPerms, ValidSettings]
486 chained_validators = [ValidPerms, ValidSettings]
476 return _RepoForm
487 return _RepoForm
477
488
478
489
479 def ApplicationSettingsForm():
490 def ApplicationSettingsForm():
480 class _ApplicationSettingsForm(formencode.Schema):
491 class _ApplicationSettingsForm(formencode.Schema):
481 allow_extra_fields = True
492 allow_extra_fields = True
482 filter_extra_fields = False
493 filter_extra_fields = False
483 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
494 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
484 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
495 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
485 rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False)
496 rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False)
486
497
487 return _ApplicationSettingsForm
498 return _ApplicationSettingsForm
488
499
489 def ApplicationUiSettingsForm():
500 def ApplicationUiSettingsForm():
490 class _ApplicationUiSettingsForm(formencode.Schema):
501 class _ApplicationUiSettingsForm(formencode.Schema):
491 allow_extra_fields = True
502 allow_extra_fields = True
492 filter_extra_fields = False
503 filter_extra_fields = False
493 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
504 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
494 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
505 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
495 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
506 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
496 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
507 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
497 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
508 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
498 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
509 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
499
510
500 return _ApplicationUiSettingsForm
511 return _ApplicationUiSettingsForm
501
512
502 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
513 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
503 class _DefaultPermissionsForm(formencode.Schema):
514 class _DefaultPermissionsForm(formencode.Schema):
504 allow_extra_fields = True
515 allow_extra_fields = True
505 filter_extra_fields = True
516 filter_extra_fields = True
506 overwrite_default = StringBoolean(if_missing=False)
517 overwrite_default = StringBoolean(if_missing=False)
507 anonymous = OneOf(['True', 'False'], if_missing=False)
518 anonymous = OneOf(['True', 'False'], if_missing=False)
508 default_perm = OneOf(perms_choices)
519 default_perm = OneOf(perms_choices)
509 default_register = OneOf(register_choices)
520 default_register = OneOf(register_choices)
510 default_create = OneOf(create_choices)
521 default_create = OneOf(create_choices)
511
522
512 return _DefaultPermissionsForm
523 return _DefaultPermissionsForm
513
524
514
525
515 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices):
526 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices):
516 class _LdapSettingsForm(formencode.Schema):
527 class _LdapSettingsForm(formencode.Schema):
517 allow_extra_fields = True
528 allow_extra_fields = True
518 filter_extra_fields = True
529 filter_extra_fields = True
519 pre_validators = [LdapLibValidator]
530 pre_validators = [LdapLibValidator]
520 ldap_active = StringBoolean(if_missing=False)
531 ldap_active = StringBoolean(if_missing=False)
521 ldap_host = UnicodeString(strip=True,)
532 ldap_host = UnicodeString(strip=True,)
522 ldap_port = Number(strip=True,)
533 ldap_port = Number(strip=True,)
523 ldap_ldaps = StringBoolean(if_missing=False)
534 ldap_ldaps = StringBoolean(if_missing=False)
524 ldap_tls_reqcert = OneOf(tls_reqcert_choices)
535 ldap_tls_reqcert = OneOf(tls_reqcert_choices)
525 ldap_dn_user = UnicodeString(strip=True,)
536 ldap_dn_user = UnicodeString(strip=True,)
526 ldap_dn_pass = UnicodeString(strip=True,)
537 ldap_dn_pass = UnicodeString(strip=True,)
527 ldap_base_dn = UnicodeString(strip=True,)
538 ldap_base_dn = UnicodeString(strip=True,)
528 ldap_filter = UnicodeString(strip=True,)
539 ldap_filter = UnicodeString(strip=True,)
529 ldap_search_scope = OneOf(search_scope_choices)
540 ldap_search_scope = OneOf(search_scope_choices)
530 ldap_attr_login = All(AttrLoginValidator, UnicodeString(strip=True,))
541 ldap_attr_login = All(AttrLoginValidator, UnicodeString(strip=True,))
531 ldap_attr_firstname = UnicodeString(strip=True,)
542 ldap_attr_firstname = UnicodeString(strip=True,)
532 ldap_attr_lastname = UnicodeString(strip=True,)
543 ldap_attr_lastname = UnicodeString(strip=True,)
533 ldap_attr_email = UnicodeString(strip=True,)
544 ldap_attr_email = UnicodeString(strip=True,)
534
545
535 return _LdapSettingsForm
546 return _LdapSettingsForm
@@ -1,263 +1,291 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.repo
3 rhodecode.model.repo
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 Repository model for rhodecode
6 Repository model for rhodecode
7
7
8 :created_on: Jun 5, 2010
8 :created_on: Jun 5, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 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
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27 import os
27 import os
28 import shutil
28 import shutil
29 import logging
29 import logging
30 import traceback
30 import traceback
31 from datetime import datetime
31 from datetime import datetime
32
32
33 from pylons import app_globals as g
34
35 from rhodecode.model import BaseModel
33 from rhodecode.model import BaseModel
36 from rhodecode.model.caching_query import FromCache
34 from rhodecode.model.caching_query import FromCache
37 from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
35 from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
38 Statistics
36 Statistics, UsersGroup
39 from rhodecode.model.user import UserModel
37 from rhodecode.model.user import UserModel
40
38
41 from vcs.backends import get_backend
39 from vcs.backends import get_backend
42
40
43 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
44
42
45 class RepoModel(BaseModel):
43 class RepoModel(BaseModel):
46
44
45 def __init__(self, sa=None):
46 try:
47 from pylons import app_globals
48 self._base_path = app_globals.base_path
49 except:
50 self._base_path = None
51
52 @property
53 def base_path():
54 if self._base_path is None:
55 raise Exception('Base Path is empty, try set this after'
56 'class initialization when not having '
57 'app_globals available')
58 return self._base_path
59
60 super(RepoModel, self).__init__()
61
62
47 def get(self, repo_id, cache=False):
63 def get(self, repo_id, cache=False):
48 repo = self.sa.query(Repository)\
64 repo = self.sa.query(Repository)\
49 .filter(Repository.repo_id == repo_id)
65 .filter(Repository.repo_id == repo_id)
50
66
51 if cache:
67 if cache:
52 repo = repo.options(FromCache("sql_cache_short",
68 repo = repo.options(FromCache("sql_cache_short",
53 "get_repo_%s" % repo_id))
69 "get_repo_%s" % repo_id))
54 return repo.scalar()
70 return repo.scalar()
55
71
56
72
57 def get_by_repo_name(self, repo_name, cache=False):
73 def get_by_repo_name(self, repo_name, cache=False):
58 repo = self.sa.query(Repository)\
74 repo = self.sa.query(Repository)\
59 .filter(Repository.repo_name == repo_name)
75 .filter(Repository.repo_name == repo_name)
60
76
61 if cache:
77 if cache:
62 repo = repo.options(FromCache("sql_cache_short",
78 repo = repo.options(FromCache("sql_cache_short",
63 "get_repo_%s" % repo_name))
79 "get_repo_%s" % repo_name))
64 return repo.scalar()
80 return repo.scalar()
65
81
66 def get_users_js(self):
82 def get_users_js(self):
67
83
68 users = self.sa.query(User).filter(User.active == True).all()
84 users = self.sa.query(User).filter(User.active == True).all()
69 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
85 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
70 users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
86 users_array = '[%s]' % '\n'.join([u_tmpl % (u.user_id, u.name,
71 u.lastname, u.username)
87 u.lastname, u.username)
72 for u in users])
88 for u in users])
73 return users_array
89 return users_array
74
90
75
91
92 def get_users_groups_js(self):
93 users_groups = self.sa.query(UsersGroup)\
94 .filter(UsersGroup.users_group_active == True).all()
95
96 g_tmpl = '''{id:%s, grname:"%s",grmembers:"%s"},'''
97
98 users_groups_array = '[%s]' % '\n'.join([g_tmpl % \
99 (gr.users_group_id, gr.users_group_name,
100 len(gr.members))
101 for gr in users_groups])
102 return users_groups_array
103
76 def update(self, repo_name, form_data):
104 def update(self, repo_name, form_data):
77 try:
105 try:
78 cur_repo = self.get_by_repo_name(repo_name, cache=False)
106 cur_repo = self.get_by_repo_name(repo_name, cache=False)
79 user_model = UserModel(self.sa)
107 user_model = UserModel(self.sa)
80
108
81 #update permissions
109 #update permissions
82 for username, perm in form_data['perms_updates']:
110 for username, perm, member_type in form_data['perms_updates']:
83 r2p = self.sa.query(RepoToPerm)\
111 r2p = self.sa.query(RepoToPerm)\
84 .filter(RepoToPerm.user == user_model.get_by_username(username))\
112 .filter(RepoToPerm.user == user_model.get_by_username(username))\
85 .filter(RepoToPerm.repository == cur_repo)\
113 .filter(RepoToPerm.repository == cur_repo)\
86 .one()
114 .one()
87
115
88 r2p.permission = self.sa.query(Permission)\
116 r2p.permission = self.sa.query(Permission)\
89 .filter(Permission.permission_name == perm)\
117 .filter(Permission.permission_name == perm)\
90 .scalar()
118 .scalar()
91 self.sa.add(r2p)
119 self.sa.add(r2p)
92
120
93 #set new permissions
121 #set new permissions
94 for username, perm in form_data['perms_new']:
122 for username, perm, member_type in form_data['perms_new']:
95 r2p = RepoToPerm()
123 r2p = RepoToPerm()
96 r2p.repository = cur_repo
124 r2p.repository = cur_repo
97 r2p.user = user_model.get_by_username(username, cache=False)
125 r2p.user = user_model.get_by_username(username, cache=False)
98
126
99 r2p.permission = self.sa.query(Permission)\
127 r2p.permission = self.sa.query(Permission)\
100 .filter(Permission.permission_name == perm)\
128 .filter(Permission.permission_name == perm)\
101 .scalar()
129 .scalar()
102 self.sa.add(r2p)
130 self.sa.add(r2p)
103
131
104 #update current repo
132 #update current repo
105 for k, v in form_data.items():
133 for k, v in form_data.items():
106 if k == 'user':
134 if k == 'user':
107 cur_repo.user = user_model.get(v)
135 cur_repo.user = user_model.get(v)
108 else:
136 else:
109 setattr(cur_repo, k, v)
137 setattr(cur_repo, k, v)
110
138
111 self.sa.add(cur_repo)
139 self.sa.add(cur_repo)
112
140
113 if repo_name != form_data['repo_name']:
141 if repo_name != form_data['repo_name']:
114 #rename our data
142 #rename our data
115 self.__rename_repo(repo_name, form_data['repo_name'])
143 self.__rename_repo(repo_name, form_data['repo_name'])
116
144
117 self.sa.commit()
145 self.sa.commit()
118 except:
146 except:
119 log.error(traceback.format_exc())
147 log.error(traceback.format_exc())
120 self.sa.rollback()
148 self.sa.rollback()
121 raise
149 raise
122
150
123 def create(self, form_data, cur_user, just_db=False, fork=False):
151 def create(self, form_data, cur_user, just_db=False, fork=False):
124 try:
152 try:
125 if fork:
153 if fork:
126 #force str since hg doesn't go with unicode
154 #force str since hg doesn't go with unicode
127 repo_name = str(form_data['fork_name'])
155 repo_name = str(form_data['fork_name'])
128 org_name = str(form_data['repo_name'])
156 org_name = str(form_data['repo_name'])
129
157
130 else:
158 else:
131 org_name = repo_name = str(form_data['repo_name'])
159 org_name = repo_name = str(form_data['repo_name'])
132 new_repo = Repository()
160 new_repo = Repository()
133 new_repo.enable_statistics = True
161 new_repo.enable_statistics = True
134 for k, v in form_data.items():
162 for k, v in form_data.items():
135 if k == 'repo_name':
163 if k == 'repo_name':
136 v = repo_name
164 v = repo_name
137 setattr(new_repo, k, v)
165 setattr(new_repo, k, v)
138
166
139 if fork:
167 if fork:
140 parent_repo = self.sa.query(Repository)\
168 parent_repo = self.sa.query(Repository)\
141 .filter(Repository.repo_name == org_name).scalar()
169 .filter(Repository.repo_name == org_name).scalar()
142 new_repo.fork = parent_repo
170 new_repo.fork = parent_repo
143
171
144 new_repo.user_id = cur_user.user_id
172 new_repo.user_id = cur_user.user_id
145 self.sa.add(new_repo)
173 self.sa.add(new_repo)
146
174
147 #create default permission
175 #create default permission
148 repo_to_perm = RepoToPerm()
176 repo_to_perm = RepoToPerm()
149 default = 'repository.read'
177 default = 'repository.read'
150 for p in UserModel(self.sa).get_by_username('default', cache=False).user_perms:
178 for p in UserModel(self.sa).get_by_username('default', cache=False).user_perms:
151 if p.permission.permission_name.startswith('repository.'):
179 if p.permission.permission_name.startswith('repository.'):
152 default = p.permission.permission_name
180 default = p.permission.permission_name
153 break
181 break
154
182
155 default_perm = 'repository.none' if form_data['private'] else default
183 default_perm = 'repository.none' if form_data['private'] else default
156
184
157 repo_to_perm.permission_id = self.sa.query(Permission)\
185 repo_to_perm.permission_id = self.sa.query(Permission)\
158 .filter(Permission.permission_name == default_perm)\
186 .filter(Permission.permission_name == default_perm)\
159 .one().permission_id
187 .one().permission_id
160
188
161 repo_to_perm.repository_id = new_repo.repo_id
189 repo_to_perm.repository_id = new_repo.repo_id
162 repo_to_perm.user_id = UserModel(self.sa)\
190 repo_to_perm.user_id = UserModel(self.sa)\
163 .get_by_username('default', cache=False).user_id
191 .get_by_username('default', cache=False).user_id
164
192
165 self.sa.add(repo_to_perm)
193 self.sa.add(repo_to_perm)
166 self.sa.commit()
194 self.sa.commit()
167
195
168
196
169 #now automatically start following this repository as owner
197 #now automatically start following this repository as owner
170 from rhodecode.model.scm import ScmModel
198 from rhodecode.model.scm import ScmModel
171 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
199 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
172 cur_user.user_id)
200 cur_user.user_id)
173
201
174 if not just_db:
202 if not just_db:
175 self.__create_repo(repo_name, form_data['repo_type'])
203 self.__create_repo(repo_name, form_data['repo_type'])
176 except:
204 except:
177 log.error(traceback.format_exc())
205 log.error(traceback.format_exc())
178 self.sa.rollback()
206 self.sa.rollback()
179 raise
207 raise
180
208
181 def create_fork(self, form_data, cur_user):
209 def create_fork(self, form_data, cur_user):
182 from rhodecode.lib.celerylib import tasks, run_task
210 from rhodecode.lib.celerylib import tasks, run_task
183 run_task(tasks.create_repo_fork, form_data, cur_user)
211 run_task(tasks.create_repo_fork, form_data, cur_user)
184
212
185 def delete(self, repo):
213 def delete(self, repo):
186 try:
214 try:
187 self.sa.delete(repo)
215 self.sa.delete(repo)
188 self.__delete_repo(repo)
216 self.__delete_repo(repo)
189 self.sa.commit()
217 self.sa.commit()
190 except:
218 except:
191 log.error(traceback.format_exc())
219 log.error(traceback.format_exc())
192 self.sa.rollback()
220 self.sa.rollback()
193 raise
221 raise
194
222
195 def delete_perm_user(self, form_data, repo_name):
223 def delete_perm_user(self, form_data, repo_name):
196 try:
224 try:
197 self.sa.query(RepoToPerm)\
225 self.sa.query(RepoToPerm)\
198 .filter(RepoToPerm.repository \
226 .filter(RepoToPerm.repository \
199 == self.get_by_repo_name(repo_name))\
227 == self.get_by_repo_name(repo_name))\
200 .filter(RepoToPerm.user_id == form_data['user_id']).delete()
228 .filter(RepoToPerm.user_id == form_data['user_id']).delete()
201 self.sa.commit()
229 self.sa.commit()
202 except:
230 except:
203 log.error(traceback.format_exc())
231 log.error(traceback.format_exc())
204 self.sa.rollback()
232 self.sa.rollback()
205 raise
233 raise
206
234
207 def delete_stats(self, repo_name):
235 def delete_stats(self, repo_name):
208 try:
236 try:
209 self.sa.query(Statistics)\
237 self.sa.query(Statistics)\
210 .filter(Statistics.repository == \
238 .filter(Statistics.repository == \
211 self.get_by_repo_name(repo_name)).delete()
239 self.get_by_repo_name(repo_name)).delete()
212 self.sa.commit()
240 self.sa.commit()
213 except:
241 except:
214 log.error(traceback.format_exc())
242 log.error(traceback.format_exc())
215 self.sa.rollback()
243 self.sa.rollback()
216 raise
244 raise
217
245
218
246
219 def __create_repo(self, repo_name, alias):
247 def __create_repo(self, repo_name, alias):
220 """
248 """
221 makes repository on filesystem
249 makes repository on filesystem
222 :param repo_name:
250 :param repo_name:
223 :param alias:
251 :param alias:
224 """
252 """
225 from rhodecode.lib.utils import check_repo
253 from rhodecode.lib.utils import check_repo
226 repo_path = os.path.join(g.base_path, repo_name)
254 repo_path = os.path.join(self.base_path, repo_name)
227 if check_repo(repo_name, g.base_path):
255 if check_repo(repo_name, self.base_path):
228 log.info('creating repo %s in %s', repo_name, repo_path)
256 log.info('creating repo %s in %s', repo_name, repo_path)
229 backend = get_backend(alias)
257 backend = get_backend(alias)
230 backend(repo_path, create=True)
258 backend(repo_path, create=True)
231
259
232 def __rename_repo(self, old, new):
260 def __rename_repo(self, old, new):
233 """
261 """
234 renames repository on filesystem
262 renames repository on filesystem
235 :param old: old name
263 :param old: old name
236 :param new: new name
264 :param new: new name
237 """
265 """
238 log.info('renaming repo from %s to %s', old, new)
266 log.info('renaming repo from %s to %s', old, new)
239
267
240 old_path = os.path.join(g.base_path, old)
268 old_path = os.path.join(self.base_path, old)
241 new_path = os.path.join(g.base_path, new)
269 new_path = os.path.join(self.base_path, new)
242 if os.path.isdir(new_path):
270 if os.path.isdir(new_path):
243 raise Exception('Was trying to rename to already existing dir %s',
271 raise Exception('Was trying to rename to already existing dir %s',
244 new_path)
272 new_path)
245 shutil.move(old_path, new_path)
273 shutil.move(old_path, new_path)
246
274
247 def __delete_repo(self, repo):
275 def __delete_repo(self, repo):
248 """
276 """
249 removes repo from filesystem, the removal is acctually made by
277 removes repo from filesystem, the removal is acctually made by
250 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
278 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
251 repository is no longer valid for rhodecode, can be undeleted later on
279 repository is no longer valid for rhodecode, can be undeleted later on
252 by reverting the renames on this repository
280 by reverting the renames on this repository
253 :param repo: repo object
281 :param repo: repo object
254 """
282 """
255 rm_path = os.path.join(g.base_path, repo.repo_name)
283 rm_path = os.path.join(self.base_path, repo.repo_name)
256 log.info("Removing %s", rm_path)
284 log.info("Removing %s", rm_path)
257 #disable hg/git
285 #disable hg/git
258 alias = repo.repo_type
286 alias = repo.repo_type
259 shutil.move(os.path.join(rm_path, '.%s' % alias),
287 shutil.move(os.path.join(rm_path, '.%s' % alias),
260 os.path.join(rm_path, 'rm__.%s' % alias))
288 os.path.join(rm_path, 'rm__.%s' % alias))
261 #disable repo
289 #disable repo
262 shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s__%s' \
290 shutil.move(rm_path, os.path.join(self.base_path, 'rm__%s__%s' \
263 % (datetime.today(), repo.repo_name)))
291 % (datetime.today(), repo.repo_name)))
General Comments 0
You need to be logged in to leave comments. Login now