##// END OF EJS Templates
fix fo empty email passed in attributes of ldap account....
marcink -
r1689:cc302c98 beta
parent child Browse files
Show More
@@ -1,471 +1,476 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.user
4 4 ~~~~~~~~~~~~~~~~~~~~
5 5
6 6 users model for RhodeCode
7 7
8 8 :created_on: Apr 9, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28
29 29 from pylons.i18n.translation import _
30 30
31 31 from rhodecode.lib import safe_unicode
32 32 from rhodecode.lib.caching_query import FromCache
33 33
34 34 from rhodecode.model import BaseModel
35 35 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
36 36 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember
37 37 from rhodecode.lib.exceptions import DefaultUserException, \
38 38 UserOwnsReposException
39 39
40 40 from sqlalchemy.exc import DatabaseError
41 41 from rhodecode.lib import generate_api_key
42 42 from sqlalchemy.orm import joinedload
43 43
44 44 log = logging.getLogger(__name__)
45 45
46 46 PERM_WEIGHTS = {'repository.none': 0,
47 47 'repository.read': 1,
48 48 'repository.write': 3,
49 49 'repository.admin': 3}
50 50
51 51
52 52 class UserModel(BaseModel):
53 53 def get(self, user_id, cache=False):
54 54 user = self.sa.query(User)
55 55 if cache:
56 56 user = user.options(FromCache("sql_cache_short",
57 57 "get_user_%s" % user_id))
58 58 return user.get(user_id)
59 59
60 60 def get_by_username(self, username, cache=False, case_insensitive=False):
61 61
62 62 if case_insensitive:
63 63 user = self.sa.query(User).filter(User.username.ilike(username))
64 64 else:
65 65 user = self.sa.query(User)\
66 66 .filter(User.username == username)
67 67 if cache:
68 68 user = user.options(FromCache("sql_cache_short",
69 69 "get_user_%s" % username))
70 70 return user.scalar()
71 71
72 72 def get_by_api_key(self, api_key, cache=False):
73 73
74 74 user = self.sa.query(User)\
75 75 .filter(User.api_key == api_key)
76 76 if cache:
77 77 user = user.options(FromCache("sql_cache_short",
78 78 "get_user_%s" % api_key))
79 79 return user.scalar()
80 80
81 81 def create(self, form_data):
82 82 try:
83 83 new_user = User()
84 84 for k, v in form_data.items():
85 85 setattr(new_user, k, v)
86 86
87 87 new_user.api_key = generate_api_key(form_data['username'])
88 88 self.sa.add(new_user)
89 89 self.sa.commit()
90 90 return new_user
91 91 except:
92 92 log.error(traceback.format_exc())
93 93 self.sa.rollback()
94 94 raise
95 95
96 96
97 97 def create_or_update(self, username, password, email, name, lastname,
98 98 active=True, admin=False, ldap_dn=None):
99 99 """
100 100 Creates a new instance if not found, or updates current one
101 101
102 102 :param username:
103 103 :param password:
104 104 :param email:
105 105 :param active:
106 106 :param name:
107 107 :param lastname:
108 108 :param active:
109 109 :param admin:
110 110 :param ldap_dn:
111 111 """
112 112
113 113 from rhodecode.lib.auth import get_crypt_password
114 114
115 115 log.debug('Checking for %s account in RhodeCode database', username)
116 116 user = User.get_by_username(username, case_insensitive=True)
117 117 if user is None:
118 118 log.debug('creating new user %s', username)
119 119 new_user = User()
120 120 else:
121 121 log.debug('updating user %s', username)
122 122 new_user = user
123 123
124 124 try:
125 125 new_user.username = username
126 126 new_user.admin = admin
127 127 new_user.password = get_crypt_password(password)
128 128 new_user.api_key = generate_api_key(username)
129 129 new_user.email = email
130 130 new_user.active = active
131 131 new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None
132 132 new_user.name = name
133 133 new_user.lastname = lastname
134 134
135 135 self.sa.add(new_user)
136 136 self.sa.commit()
137 137 return new_user
138 138 except (DatabaseError,):
139 139 log.error(traceback.format_exc())
140 140 self.sa.rollback()
141 141 raise
142 142
143 143
144 144 def create_for_container_auth(self, username, attrs):
145 145 """
146 146 Creates the given user if it's not already in the database
147 147
148 148 :param username:
149 149 :param attrs:
150 150 """
151 151 if self.get_by_username(username, case_insensitive=True) is None:
152 152 try:
153 153 new_user = User()
154 154 new_user.username = username
155 155 new_user.password = None
156 156 new_user.api_key = generate_api_key(username)
157 157 new_user.email = attrs['email']
158 158 new_user.active = attrs.get('active', True)
159 159 new_user.name = attrs['name']
160 160 new_user.lastname = attrs['lastname']
161 161
162 162 self.sa.add(new_user)
163 163 self.sa.commit()
164 164 return new_user
165 165 except (DatabaseError,):
166 166 log.error(traceback.format_exc())
167 167 self.sa.rollback()
168 168 raise
169 169 log.debug('User %s already exists. Skipping creation of account'
170 170 ' for container auth.', username)
171 171 return None
172 172
173 173 def create_ldap(self, username, password, user_dn, attrs):
174 174 """
175 175 Checks if user is in database, if not creates this user marked
176 176 as ldap user
177 177
178 178 :param username:
179 179 :param password:
180 180 :param user_dn:
181 181 :param attrs:
182 182 """
183 183 from rhodecode.lib.auth import get_crypt_password
184 184 log.debug('Checking for such ldap account in RhodeCode database')
185 185 if self.get_by_username(username, case_insensitive=True) is None:
186
187 # autogenerate email for ldap account without one
188 generate_email = lambda usr: '%s@ldap.account' % usr
189
186 190 try:
187 191 new_user = User()
192 username = username.lower()
188 193 # add ldap account always lowercase
189 new_user.username = username.lower()
194 new_user.username = username
190 195 new_user.password = get_crypt_password(password)
191 196 new_user.api_key = generate_api_key(username)
192 new_user.email = attrs['email']
197 new_user.email = attrs['email'] or generate_email(username)
193 198 new_user.active = attrs.get('active', True)
194 199 new_user.ldap_dn = safe_unicode(user_dn)
195 200 new_user.name = attrs['name']
196 201 new_user.lastname = attrs['lastname']
197 202
198 203 self.sa.add(new_user)
199 204 self.sa.commit()
200 205 return new_user
201 206 except (DatabaseError,):
202 207 log.error(traceback.format_exc())
203 208 self.sa.rollback()
204 209 raise
205 210 log.debug('this %s user exists skipping creation of ldap account',
206 211 username)
207 212 return None
208 213
209 214 def create_registration(self, form_data):
210 215 from rhodecode.lib.celerylib import tasks, run_task
211 216 try:
212 217 new_user = User()
213 218 for k, v in form_data.items():
214 219 if k != 'admin':
215 220 setattr(new_user, k, v)
216 221
217 222 self.sa.add(new_user)
218 223 self.sa.commit()
219 224 body = ('New user registration\n'
220 225 'username: %s\n'
221 226 'email: %s\n')
222 227 body = body % (form_data['username'], form_data['email'])
223 228
224 229 run_task(tasks.send_email, None,
225 230 _('[RhodeCode] New User registration'),
226 231 body)
227 232 except:
228 233 log.error(traceback.format_exc())
229 234 self.sa.rollback()
230 235 raise
231 236
232 237 def update(self, user_id, form_data):
233 238 try:
234 239 user = self.get(user_id, cache=False)
235 240 if user.username == 'default':
236 241 raise DefaultUserException(
237 242 _("You can't Edit this user since it's"
238 243 " crucial for entire application"))
239 244
240 245 for k, v in form_data.items():
241 246 if k == 'new_password' and v != '':
242 247 user.password = v
243 248 user.api_key = generate_api_key(user.username)
244 249 else:
245 250 setattr(user, k, v)
246 251
247 252 self.sa.add(user)
248 253 self.sa.commit()
249 254 except:
250 255 log.error(traceback.format_exc())
251 256 self.sa.rollback()
252 257 raise
253 258
254 259 def update_my_account(self, user_id, form_data):
255 260 try:
256 261 user = self.get(user_id, cache=False)
257 262 if user.username == 'default':
258 263 raise DefaultUserException(
259 264 _("You can't Edit this user since it's"
260 265 " crucial for entire application"))
261 266 for k, v in form_data.items():
262 267 if k == 'new_password' and v != '':
263 268 user.password = v
264 269 user.api_key = generate_api_key(user.username)
265 270 else:
266 271 if k not in ['admin', 'active']:
267 272 setattr(user, k, v)
268 273
269 274 self.sa.add(user)
270 275 self.sa.commit()
271 276 except:
272 277 log.error(traceback.format_exc())
273 278 self.sa.rollback()
274 279 raise
275 280
276 281 def delete(self, user_id):
277 282 try:
278 283 user = self.get(user_id, cache=False)
279 284 if user.username == 'default':
280 285 raise DefaultUserException(
281 286 _("You can't remove this user since it's"
282 287 " crucial for entire application"))
283 288 if user.repositories:
284 289 raise UserOwnsReposException(_('This user still owns %s '
285 290 'repositories and cannot be '
286 291 'removed. Switch owners or '
287 292 'remove those repositories') \
288 293 % user.repositories)
289 294 self.sa.delete(user)
290 295 self.sa.commit()
291 296 except:
292 297 log.error(traceback.format_exc())
293 298 self.sa.rollback()
294 299 raise
295 300
296 301 def reset_password_link(self, data):
297 302 from rhodecode.lib.celerylib import tasks, run_task
298 303 run_task(tasks.send_password_link, data['email'])
299 304
300 305 def reset_password(self, data):
301 306 from rhodecode.lib.celerylib import tasks, run_task
302 307 run_task(tasks.reset_user_password, data['email'])
303 308
304 309 def fill_data(self, auth_user, user_id=None, api_key=None):
305 310 """
306 311 Fetches auth_user by user_id,or api_key if present.
307 312 Fills auth_user attributes with those taken from database.
308 313 Additionally set's is_authenitated if lookup fails
309 314 present in database
310 315
311 316 :param auth_user: instance of user to set attributes
312 317 :param user_id: user id to fetch by
313 318 :param api_key: api key to fetch by
314 319 """
315 320 if user_id is None and api_key is None:
316 321 raise Exception('You need to pass user_id or api_key')
317 322
318 323 try:
319 324 if api_key:
320 325 dbuser = self.get_by_api_key(api_key)
321 326 else:
322 327 dbuser = self.get(user_id)
323 328
324 329 if dbuser is not None and dbuser.active:
325 330 log.debug('filling %s data', dbuser)
326 331 for k, v in dbuser.get_dict().items():
327 332 setattr(auth_user, k, v)
328 333 else:
329 334 return False
330 335
331 336 except:
332 337 log.error(traceback.format_exc())
333 338 auth_user.is_authenticated = False
334 339 return False
335 340
336 341 return True
337 342
338 343 def fill_perms(self, user):
339 344 """
340 345 Fills user permission attribute with permissions taken from database
341 346 works for permissions given for repositories, and for permissions that
342 347 are granted to groups
343 348
344 349 :param user: user instance to fill his perms
345 350 """
346 351
347 352 user.permissions['repositories'] = {}
348 353 user.permissions['global'] = set()
349 354
350 355 #======================================================================
351 356 # fetch default permissions
352 357 #======================================================================
353 358 default_user = self.get_by_username('default', cache=True)
354 359
355 360 default_perms = self.sa.query(UserRepoToPerm, Repository, Permission)\
356 361 .join((Repository, UserRepoToPerm.repository_id ==
357 362 Repository.repo_id))\
358 363 .join((Permission, UserRepoToPerm.permission_id ==
359 364 Permission.permission_id))\
360 365 .filter(UserRepoToPerm.user == default_user).all()
361 366
362 367 if user.is_admin:
363 368 #==================================================================
364 369 # #admin have all default rights set to admin
365 370 #==================================================================
366 371 user.permissions['global'].add('hg.admin')
367 372
368 373 for perm in default_perms:
369 374 p = 'repository.admin'
370 375 user.permissions['repositories'][perm.UserRepoToPerm.
371 376 repository.repo_name] = p
372 377
373 378 else:
374 379 #==================================================================
375 380 # set default permissions
376 381 #==================================================================
377 382 uid = user.user_id
378 383
379 384 #default global
380 385 default_global_perms = self.sa.query(UserToPerm)\
381 386 .filter(UserToPerm.user == default_user)
382 387
383 388 for perm in default_global_perms:
384 389 user.permissions['global'].add(perm.permission.permission_name)
385 390
386 391 #default for repositories
387 392 for perm in default_perms:
388 393 if perm.Repository.private and not (perm.Repository.user_id ==
389 394 uid):
390 395 #diself.sable defaults for private repos,
391 396 p = 'repository.none'
392 397 elif perm.Repository.user_id == uid:
393 398 #set admin if owner
394 399 p = 'repository.admin'
395 400 else:
396 401 p = perm.Permission.permission_name
397 402
398 403 user.permissions['repositories'][perm.UserRepoToPerm.
399 404 repository.repo_name] = p
400 405
401 406 #==================================================================
402 407 # overwrite default with user permissions if any
403 408 #==================================================================
404 409
405 410 #user global
406 411 user_perms = self.sa.query(UserToPerm)\
407 412 .options(joinedload(UserToPerm.permission))\
408 413 .filter(UserToPerm.user_id == uid).all()
409 414
410 415 for perm in user_perms:
411 416 user.permissions['global'].add(perm.permission.
412 417 permission_name)
413 418
414 419 #user repositories
415 420 user_repo_perms = self.sa.query(UserRepoToPerm, Permission,
416 421 Repository)\
417 422 .join((Repository, UserRepoToPerm.repository_id ==
418 423 Repository.repo_id))\
419 424 .join((Permission, UserRepoToPerm.permission_id ==
420 425 Permission.permission_id))\
421 426 .filter(UserRepoToPerm.user_id == uid).all()
422 427
423 428 for perm in user_repo_perms:
424 429 # set admin if owner
425 430 if perm.Repository.user_id == uid:
426 431 p = 'repository.admin'
427 432 else:
428 433 p = perm.Permission.permission_name
429 434 user.permissions['repositories'][perm.UserRepoToPerm.
430 435 repository.repo_name] = p
431 436
432 437 #==================================================================
433 438 # check if user is part of groups for this repository and fill in
434 439 # (or replace with higher) permissions
435 440 #==================================================================
436 441
437 442 #users group global
438 443 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
439 444 .options(joinedload(UsersGroupToPerm.permission))\
440 445 .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
441 446 UsersGroupMember.users_group_id))\
442 447 .filter(UsersGroupMember.user_id == uid).all()
443 448
444 449 for perm in user_perms_from_users_groups:
445 450 user.permissions['global'].add(perm.permission.permission_name)
446 451
447 452 #users group repositories
448 453 user_repo_perms_from_users_groups = self.sa.query(
449 454 UsersGroupRepoToPerm,
450 455 Permission, Repository,)\
451 456 .join((Repository, UsersGroupRepoToPerm.repository_id ==
452 457 Repository.repo_id))\
453 458 .join((Permission, UsersGroupRepoToPerm.permission_id ==
454 459 Permission.permission_id))\
455 460 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
456 461 UsersGroupMember.users_group_id))\
457 462 .filter(UsersGroupMember.user_id == uid).all()
458 463
459 464 for perm in user_repo_perms_from_users_groups:
460 465 p = perm.Permission.permission_name
461 466 cur_perm = user.permissions['repositories'][perm.
462 467 UsersGroupRepoToPerm.
463 468 repository.repo_name]
464 469 #overwrite permission only if it's greater than permission
465 470 # given from other sources
466 471 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
467 472 user.permissions['repositories'][perm.UsersGroupRepoToPerm.
468 473 repository.repo_name] = p
469 474
470 475 return user
471 476
General Comments 0
You need to be logged in to leave comments. Login now