Show More
@@ -48,6 +48,7 b' from rhodecode.lib.caching_query import ' | |||||
48 |
|
48 | |||
49 | from rhodecode.model.meta import Base, Session |
|
49 | from rhodecode.model.meta import Base, Session | |
50 | import hashlib |
|
50 | import hashlib | |
|
51 | from sqlalchemy.exc import DatabaseError | |||
51 |
|
52 | |||
52 |
|
53 | |||
53 | log = logging.getLogger(__name__) |
|
54 | log = logging.getLogger(__name__) | |
@@ -381,8 +382,23 b' class User(Base, BaseModel):' | |||||
381 |
|
382 | |||
382 | if cache: |
|
383 | if cache: | |
383 | q = q.options(FromCache("sql_cache_short", |
|
384 | q = q.options(FromCache("sql_cache_short", | |
384 |
"get_a |
|
385 | "get_email_key_%s" % email)) | |
385 | return q.scalar() |
|
386 | ||
|
387 | ret = q.scalar() | |||
|
388 | if ret is None: | |||
|
389 | q = UserEmailMap.query() | |||
|
390 | # try fetching in alternate email map | |||
|
391 | if case_insensitive: | |||
|
392 | q = q.filter(UserEmailMap.email.ilike(email)) | |||
|
393 | else: | |||
|
394 | q = q.filter(UserEmailMap.email == email) | |||
|
395 | q = q.options(joinedload(UserEmailMap.user)) | |||
|
396 | if cache: | |||
|
397 | q = q.options(FromCache("sql_cache_short", | |||
|
398 | "get_email_map_key_%s" % email)) | |||
|
399 | ret = getattr(q.scalar(), 'user', None) | |||
|
400 | ||||
|
401 | return ret | |||
386 |
|
402 | |||
387 | def update_lastlogin(self): |
|
403 | def update_lastlogin(self): | |
388 | """Update user lastlogin""" |
|
404 | """Update user lastlogin""" | |
@@ -403,6 +419,38 b' class User(Base, BaseModel):' | |||||
403 | ) |
|
419 | ) | |
404 |
|
420 | |||
405 |
|
421 | |||
|
422 | class UserEmailMap(Base, BaseModel): | |||
|
423 | __tablename__ = 'user_email_map' | |||
|
424 | __table_args__ = ( | |||
|
425 | UniqueConstraint('email'), | |||
|
426 | {'extend_existing': True, 'mysql_engine':'InnoDB', | |||
|
427 | 'mysql_charset': 'utf8'} | |||
|
428 | ) | |||
|
429 | __mapper_args__ = {} | |||
|
430 | ||||
|
431 | email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) | |||
|
432 | user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) | |||
|
433 | _email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) | |||
|
434 | ||||
|
435 | user = relationship('User') | |||
|
436 | ||||
|
437 | @validates('_email') | |||
|
438 | def validate_email(self, key, email): | |||
|
439 | # check if this email is not main one | |||
|
440 | main_email = Session.query(User).filter(User.email == email).scalar() | |||
|
441 | if main_email is not None: | |||
|
442 | raise AttributeError('email %s is present is user table' % email) | |||
|
443 | return email | |||
|
444 | ||||
|
445 | @hybrid_property | |||
|
446 | def email(self): | |||
|
447 | return self._email | |||
|
448 | ||||
|
449 | @email.setter | |||
|
450 | def email(self, val): | |||
|
451 | self._email = val.lower() if val else None | |||
|
452 | ||||
|
453 | ||||
406 | class UserLog(Base, BaseModel): |
|
454 | class UserLog(Base, BaseModel): | |
407 | __tablename__ = 'user_logs' |
|
455 | __tablename__ = 'user_logs' | |
408 | __table_args__ = ( |
|
456 | __table_args__ = ( |
@@ -6,8 +6,8 b' from rhodecode.model.repos_group import ' | |||||
6 | from rhodecode.model.repo import RepoModel |
|
6 | from rhodecode.model.repo import RepoModel | |
7 | from rhodecode.model.db import RepoGroup, User, Notification, UserNotification, \ |
|
7 | from rhodecode.model.db import RepoGroup, User, Notification, UserNotification, \ | |
8 | UsersGroup, UsersGroupMember, Permission, UsersGroupRepoGroupToPerm,\ |
|
8 | UsersGroup, UsersGroupMember, Permission, UsersGroupRepoGroupToPerm,\ | |
9 | Repository |
|
9 | Repository, UserEmailMap | |
10 | from sqlalchemy.exc import IntegrityError |
|
10 | from sqlalchemy.exc import IntegrityError, DatabaseError | |
11 | from rhodecode.model.user import UserModel |
|
11 | from rhodecode.model.user import UserModel | |
12 |
|
12 | |||
13 | from rhodecode.model.meta import Session |
|
13 | from rhodecode.model.meta import Session | |
@@ -181,7 +181,8 b' class TestUser(unittest.TestCase):' | |||||
181 | super(TestUser, self).__init__(methodName=methodName) |
|
181 | super(TestUser, self).__init__(methodName=methodName) | |
182 |
|
182 | |||
183 | def test_create_and_remove(self): |
|
183 | def test_create_and_remove(self): | |
184 |
usr = UserModel().create_or_update(username=u'test_user', |
|
184 | usr = UserModel().create_or_update(username=u'test_user', | |
|
185 | password=u'qweqwe', | |||
185 | email=u'u232@rhodecode.org', |
|
186 | email=u'u232@rhodecode.org', | |
186 | name=u'u1', lastname=u'u1') |
|
187 | name=u'u1', lastname=u'u1') | |
187 | Session.commit() |
|
188 | Session.commit() | |
@@ -201,6 +202,50 b' class TestUser(unittest.TestCase):' | |||||
201 |
|
202 | |||
202 | self.assertEqual(UsersGroupMember.query().all(), []) |
|
203 | self.assertEqual(UsersGroupMember.query().all(), []) | |
203 |
|
204 | |||
|
205 | def test_additonal_email_as_main(self): | |||
|
206 | usr = UserModel().create_or_update(username=u'test_user', | |||
|
207 | password=u'qweqwe', | |||
|
208 | email=u'main_email@rhodecode.org', | |||
|
209 | name=u'u1', lastname=u'u1') | |||
|
210 | Session.commit() | |||
|
211 | ||||
|
212 | def do(): | |||
|
213 | m = UserEmailMap() | |||
|
214 | m.email = u'main_email@rhodecode.org' | |||
|
215 | m.user = usr | |||
|
216 | Session.add(m) | |||
|
217 | Session.commit() | |||
|
218 | self.assertRaises(AttributeError, do) | |||
|
219 | ||||
|
220 | UserModel().delete(usr.user_id) | |||
|
221 | Session.commit() | |||
|
222 | ||||
|
223 | def test_extra_email_map(self): | |||
|
224 | usr = UserModel().create_or_update(username=u'test_user', | |||
|
225 | password=u'qweqwe', | |||
|
226 | email=u'main_email@rhodecode.org', | |||
|
227 | name=u'u1', lastname=u'u1') | |||
|
228 | Session.commit() | |||
|
229 | ||||
|
230 | m = UserEmailMap() | |||
|
231 | m.email = u'main_email2@rhodecode.org' | |||
|
232 | m.user = usr | |||
|
233 | Session.add(m) | |||
|
234 | Session.commit() | |||
|
235 | ||||
|
236 | u = User.get_by_email(email='main_email@rhodecode.org') | |||
|
237 | self.assertEqual(usr.user_id, u.user_id) | |||
|
238 | self.assertEqual(usr.username, u.username) | |||
|
239 | ||||
|
240 | u = User.get_by_email(email='main_email2@rhodecode.org') | |||
|
241 | self.assertEqual(usr.user_id, u.user_id) | |||
|
242 | self.assertEqual(usr.username, u.username) | |||
|
243 | u = User.get_by_email(email='main_email3@rhodecode.org') | |||
|
244 | self.assertEqual(None, u) | |||
|
245 | ||||
|
246 | UserModel().delete(usr.user_id) | |||
|
247 | Session.commit() | |||
|
248 | ||||
204 |
|
249 | |||
205 | class TestNotifications(unittest.TestCase): |
|
250 | class TestNotifications(unittest.TestCase): | |
206 |
|
251 |
General Comments 0
You need to be logged in to leave comments.
Login now