##// END OF EJS Templates
feat(login by email option): added ability to log in with user primary email. Fixes: RCCE-63
ilin.s -
r5358:2095c653 default
parent child Browse files
Show More
@@ -80,6 +80,18 b' class TestLoginController(object):'
80 80 assert username == 'test_regular'
81 81 response.mustcontain('logout')
82 82
83 def test_login_with_primary_email(self):
84 user_email = 'test_regular@mail.com'
85 response = self.app.post(route_path('login'),
86 {'username': user_email,
87 'password': 'test12'}, status=302)
88 response = response.follow()
89 session = response.get_session_from_response()
90 user = session['rhodecode_user']
91 assert user['username'] == user_email.split('@')[0]
92 assert user['is_authenticated']
93 response.mustcontain('logout')
94
83 95 def test_login_regular_forbidden_when_super_admin_restriction(self):
84 96 from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin
85 97 with fixture.auth_restriction(self.app._pyramid_registry,
@@ -54,8 +54,8 b' CaptchaData = collections.namedtuple('
54 54 'CaptchaData', 'active, private_key, public_key')
55 55
56 56
57 def store_user_in_session(session, username, remember=False):
58 user = User.get_by_username(username, case_insensitive=True)
57 def store_user_in_session(session, user_identifier, remember=False):
58 user = User.get_by_username_or_primary_email(user_identifier)
59 59 auth_user = AuthUser(user.user_id)
60 60 auth_user.set_authenticated()
61 61 cs = auth_user.get_cookie_store()
@@ -74,7 +74,7 b' def store_user_in_session(session, usern'
74 74 safe_cs = cs.copy()
75 75 safe_cs['password'] = '****'
76 76 log.info('user %s is now authenticated and stored in '
77 'session, session attrs %s', username, safe_cs)
77 'session, session attrs %s', user_identifier, safe_cs)
78 78
79 79 # dumps session attrs back to cookie
80 80 session._update_cookie_out()
@@ -181,7 +181,7 b' class LoginView(BaseAppView):'
181 181 # form checks for username/password, now we're authenticated
182 182 headers = store_user_in_session(
183 183 self.session,
184 username=form_result['username'],
184 user_identifier=form_result['username'],
185 185 remember=form_result['remember'])
186 186 log.debug('Redirecting to "%s" after login.', c.came_from)
187 187
@@ -389,11 +389,7 b' class RhodeCodeAuthPluginBase(object):'
389 389 log.debug(
390 390 'Trying to fetch user `%s` from RhodeCode database', username)
391 391 if username:
392 user = User.get_by_username(username)
393 if not user:
394 log.debug('User not found, fallback to fetch user in '
395 'case insensitive mode')
396 user = User.get_by_username(username, case_insensitive=True)
392 user = User.get_by_username_or_primary_email(username)
397 393 else:
398 394 log.debug('provided username:`%s` is empty skipping...', username)
399 395 if not user:
@@ -169,7 +169,7 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
169 169 extra={"action": "user_auth_ok", "auth_module": "auth_rhodecode_anon", "username": userobj.username})
170 170 return user_attrs
171 171
172 elif userobj.username == username and password_match:
172 elif (userobj.username == username or userobj.email == username) and password_match:
173 173 log.info('user `%s` authenticated correctly', userobj.username,
174 174 extra={"action": "user_auth_ok", "auth_module": "auth_rhodecode", "username": userobj.username})
175 175 return user_attrs
@@ -35,7 +35,7 b' import collections'
35 35
36 36 from sqlalchemy import (
37 37 or_, and_, not_, func, cast, TypeDecorator, event, select,
38 true, false, null,
38 true, false, null, union_all,
39 39 Index, Sequence, UniqueConstraint, ForeignKey, CheckConstraint, Column,
40 40 Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary,
41 41 Text, Float, PickleType, BigInteger)
@@ -954,6 +954,12 b' class User(Base, BaseModel):'
954 954 return cls.execute(q).scalar_one_or_none()
955 955
956 956 @classmethod
957 def get_by_username_or_primary_email(cls, user_identifier):
958 qs = union_all(cls.select().where(func.lower(cls.username) == func.lower(user_identifier)),
959 cls.select().where(func.lower(cls.email) == func.lower(user_identifier)))
960 return cls.execute(cls.select(User).from_statement(qs)).scalar_one_or_none()
961
962 @classmethod
957 963 def get_by_auth_token(cls, auth_token, cache=False):
958 964
959 965 q = cls.select(User)\
@@ -432,7 +432,7 b' def ValidAuth(localizer):'
432 432
433 433 if not authenticate(username, password, '', HTTP_TYPE,
434 434 skip_missing=True):
435 user = User.get_by_username(username)
435 user = User.get_by_username_or_primary_email(username)
436 436 if user and not user.active:
437 437 log.warning('user %s is disabled', username)
438 438 msg = M(self, 'disabled_account', state)
@@ -35,12 +35,12 b''
35 35 <%block name="above_login_button" />
36 36 <!-- login -->
37 37 <div class="sign-in-title">
38 <h1>${_('Sign In using username/password')}</h1>
38 <h1>${_('Sign In using credentials')}</h1>
39 39 </div>
40 40 <div class="inner form">
41 41 ${h.form(request.route_path('login', _query={'came_from': c.came_from}), needs_csrf_token=False)}
42 42
43 <label for="username">${_('Username')}:</label>
43 <label for="username">${_('Username or email address')}:</label>
44 44 ${h.text('username', class_='focus', value=defaults.get('username'))}
45 45 %if 'username' in errors:
46 46 <span class="error-message">${errors.get('username')}</span>
General Comments 0
You need to be logged in to leave comments. Login now