def test_failed_login_with_api_error(self, mocked): # get a valid login link/provider providers = OAuthProvider() valid_providers = providers.get_slugs() self.assertTrue(valid_providers) # error in HTML and parsed html = """ <html> <head> <title>Error Page</title> </head> <body> <div class="error"> <h1>Ooops...</h1> <p>Error message</p> </div> </body> </html> """ parsed = 'Error Page Ooops... Error message' # create a mock object for Authomatic.login() mocked.return_value = MockAuthomatic(error=html) # login & assert welcome message was shown resp1 = self.app.get('/login/{}'.format(valid_providers[0]), follow_redirects=True) self.assertIn(parsed, resp1.data, 'API message does not match')
def test_new_user_login(self, mocked): # get a valid login link/provider providers = OAuthProvider() valid_providers = providers.get_slugs() self.assertTrue(valid_providers) # create a mock object for Authomatic.login() mocked.return_value = MockAuthomatic() # assert that we have no users in the database self.assertEqual(db.session.query(User).count(), 0, 'User count before login differs than 0') self.app.get('/login/{}'.format(valid_providers[0])) # assert a user was created self.assertEqual(db.session.query(User).count(), 1, 'User count after login differs than 1') # assert user data u = User.query.first() self.assertEqual(u.email, '*****@*****.**', "Emails don't match") self.assertEqual(u.name, 'John Doe', "Name doesn't match") self.assertEqual(u.created_at, u.last_seen, "Time doesn't match") self.assertEqual(u.group.title, 'user') self.assertTrue(u.last_seen, "Last seen is blank") self.assertEqual(u.created_with, valid_providers[0], "Provider doesn't match")
def test_returning_user_with_remember_me(self, mocked): # get a valid login link/provider providers = OAuthProvider() valid_providers = providers.get_slugs() self.assertTrue(valid_providers) # create a mock object for Authomatic.login() mocked.return_value = MockAuthomatic() # create user and token user = User(email='*****@*****.**') user.remember_me_token = user.get_token() db.session.add(user) db.session.commit() # create cookies self.app.set_cookie('localhost', 'user_id', '1') self.app.set_cookie('localhost', 'remember_me', user.get_hash()) # assert user is logged in resp = self.app.get('/') self.assertIn('href="/logout"', resp.data) self.assertNotIn('href="/login', resp.data) # clean cookis for next sessions self.app.delete_cookie('localhost', 'user_id') self.app.delete_cookie('localhost', 'remember_me')
def test_login_with_remember_me(self, mocked): # get a valid login link/provider providers = OAuthProvider() valid_providers = providers.get_slugs() self.assertTrue(valid_providers) # create a mock object for Authomatic.login() mocked.return_value = MockAuthomatic() # create new user self.app.delete_cookie('localhost', 'user_id') self.app.delete_cookie('localhost', 'remember_me') self.app.post('/login/process', follow_redirects=True, data={'remember_me': '1', 'provider': valid_providers[0]}) # assert cookies were created accordingly user = User.query.first() self.assertEqual(user.id, int(self.read_cookie('user_id'))) self.assertTrue(user.check_hash(self.read_cookie('remember_me'))) # clean cookis for next sessions self.app.delete_cookie('localhost', 'user_id') self.app.delete_cookie('localhost', 'remember_me')
def test_returning_user_login(self, mocked): # get a valid login link/provider providers = OAuthProvider() valid_providers = providers.get_slugs() self.assertTrue(valid_providers) # create a mock object for Authomatic.login() mocked.return_value = MockAuthomatic() # login & assert welcome message was shown resp1 = self.app.get('/login/{}'.format(valid_providers[0]), follow_redirects=True) self.assertIn('Welcome, John Doe', resp1.data, 'No welcome message found after login') # logout & assert logout message was shown resp2 = self.app.get('/logout', follow_redirects=True) self.assertIn('You\'ve been logged out', resp2.data, 'No logout message found after logout') # login again & assert only one user was created self.app.get('/login/{}'.format(valid_providers[0])) u = User.query.first() self.assertEqual(u.email, '*****@*****.**', "Emails don't match") self.assertEqual(u.name, 'John Doe', "Name doesn't match") self.assertNotEqual(u.created_at, u.last_seen, "Last seen wasn't updated") self.assertEqual(db.session.query(User).count(), 1, 'User count after login differs than 1')
def test_login_providers(self): # test if links to the ouauth/oauth2 providers (20X or 30X) providers = OAuthProvider() for provider in providers.get_slugs(): resp = self.app.get('/login/{}'.format(provider)) self.assertEqual(resp.status_code, 302) # test if unauthorized provider returns 404 resp = self.app.get('/login/anything_else') self.assertEqual(resp.status_code, 404)
def test_login_pages(self): # test if login page exists resp = self.app.get('/login') self.assertEqual(resp.status_code, 200) self.assertEqual(resp.mimetype, 'text/html') # test if are there links to oauth/oauth2 providers providers = OAuthProvider() for provider in providers.get_slugs(): self.assertIn(' data-oauth="{}"'.format(provider), resp.data) # test if is there a link to login in the home page resp = self.app.get('/') self.assertIn('href="/login', resp.data)
def test_unsuccessful_user_login_with_no_email(self, mocked): # get a valid login link/provider providers = OAuthProvider() valid_providers = providers.get_slugs() self.assertTrue(valid_providers) # create a mock object for Authomatic.login() & try to login mocked.return_value = MockAuthomatic(email=None) resp = self.app.get('/login/{}'.format(valid_providers[0]), follow_redirects=True) # assert error message was shown self.assertIn('refusing to send us your email address', resp.data, 'No error shown after trying login without email') # assert that we have no users in the database self.assertEqual(db.session.query(User).count(), 0, 'User count after login differs than 0')
def test_new_admin_user_login(self, mocked): # get a valid login link/provider providers = OAuthProvider() valid_providers = providers.get_slugs() self.assertTrue(valid_providers) # random pick an admin email from the config admin_email = random_choice(app.config['ADMIN']) # create a mock object for Authomatic.login() mocked.return_value = MockAuthomatic(email=admin_email) # create a new admin user self.app.get('/login/{}'.format(valid_providers[0])) # assert the new user is an admin u = User.query.first() self.assertEqual(u.group.title, 'admin')
def login(provider): # after login url next_page = 'site.index' # check if provider is valid providers = OAuthProvider() if provider not in providers.get_slugs(): abort(404) # create authomatic and response objects authomatic = Authomatic(providers.credentials, app.config['SECRET_KEY'], report_errors=True) oauth_response = make_response() # try login provider_name = providers.get_name(provider) adapter = WerkzeugAdapter(request, oauth_response) result = authomatic.login(adapter, provider_name) if result: # flash error message if any if result.error and app.debug: session['remember_me'] = False session['provider'] = None msg = BeautifulSoup(result.error.message).findAll(text=True) flash({'type': 'alert', 'text': ' '.join(msg)}) # if success redir_resp = make_response(redirect(url_for(next_page))) if result.user: result.user.update() # check if api sent email address if not result.user.email: msg = '{} is refusing to send us your email address. ' msg += 'Please, try another log in provider.' flash({'type': 'error', 'text': msg.format(provider_name)}) next_page = 'site.login_options' # manage user data in db else: # convert all emails to lowercase (avoids duplicity in db) result.user.email = result.user.email.lower() # if existing user user = User.query.filter_by(email=result.user.email).first() if user: if provider != user.created_with: return redirect('/login/{}'.format(user.created_with)) user.last_seen = datetime.now() db.session.add(user) db.session.commit() # if new user else: now = datetime.now() roles = Group() if result.user.email in app.config['ADMIN']: role = roles.default('admin') else: role = roles.default() new_user = User(email=result.user.email, name=result.user.name, created_with=provider, created_at=now, last_seen=now, group=role) # check if email address is valid if not new_user.valid_email(): msg = 'The address “{}” provided by {} is not a valid ' msg += 'email. Please, try another log in provider.' flash({ 'type': 'error', 'text': msg.format(new_user.email, provider_name) }) next_page = 'site.login_options' # save user to db else: db.session.add(new_user) db.session.commit() new_query = User.query.filter_by(email=new_user.email) user = new_query.first() # login user if user and user.valid_email(): login_user(user) flash({ 'type': 'success', 'text': 'Welcome, {}'.format(result.user.name) }) # remember me remember_me = session.get('remember_me', False) if remember_me: session_provider = session.get('provider', False) if provider == session_provider: session['remember_me'] = False session['provider'] = None user.remember_me_token = user.get_token() db.session.add(user) db.session.commit() max_age = 60 * 60 * 24 * 30 redir_resp.set_cookie('remember_me', user.get_hash(), max_age=max_age) redir_resp.set_cookie('user_id', str(user.id), max_age=max_age) return redir_resp return oauth_response
def login(provider): # after login url next_page = 'site.index' # check if provider is valid providers = OAuthProvider() if provider not in providers.get_slugs(): abort(404) # create authomatic and response objects authomatic = Authomatic(providers.credentials, app.config['SECRET_KEY'], report_errors=True) oauth_response = make_response() # try login provider_name = providers.get_name(provider) adapter = WerkzeugAdapter(request, oauth_response) result = authomatic.login(adapter, provider_name) if result: # flash error message if any if result.error and app.debug: session['remember_me'] = False session['provider'] = None msg = BeautifulSoup(result.error.message).findAll(text=True) flash({'type': 'alert', 'text': ' '.join(msg)}) # if success redir_resp = make_response(redirect(url_for(next_page))) if result.user: result.user.update() # check if api sent email address if not result.user.email: msg = '{} is refusing to send us your email address. ' msg += 'Please, try another log in provider.' flash({'type': 'error', 'text': msg.format(provider_name)}) next_page = 'site.login_options' # manage user data in db else: # convert all emails to lowercase (avoids duplicity in db) result.user.email = result.user.email.lower() # if existing user user = User.query.filter_by(email=result.user.email).first() if user: if provider != user.created_with: return redirect('/login/{}'.format(user.created_with)) user.last_seen = datetime.now() db.session.add(user) db.session.commit() # if new user else: now = datetime.now() roles = Group() if result.user.email in app.config['ADMIN']: role = roles.default('admin') else: role = roles.default() new_user = User(email=result.user.email, name=result.user.name, created_with=provider, created_at=now, last_seen=now, group=role) # check if email address is valid if not new_user.valid_email(): msg = 'The address “{}” provided by {} is not a valid ' msg += 'email. Please, try another log in provider.' flash({'type': 'error', 'text': msg.format(new_user.email, provider_name)}) next_page = 'site.login_options' # save user to db else: db.session.add(new_user) db.session.commit() new_query = User.query.filter_by(email=new_user.email) user = new_query.first() # login user if user and user.valid_email(): login_user(user) flash({'type': 'success', 'text': 'Welcome, {}'.format(result.user.name)}) # remember me remember_me = session.get('remember_me', False) if remember_me: session_provider = session.get('provider', False) if provider == session_provider: session['remember_me'] = False session['provider'] = None user.remember_me_token = user.get_token() db.session.add(user) db.session.commit() max_age = 60 * 60 * 24 * 30 redir_resp.set_cookie('remember_me', user.get_hash(), max_age=max_age) redir_resp.set_cookie('user_id', str(user.id), max_age=max_age) return redir_resp return oauth_response