def create(self, form_data, cur_user=None): if not cur_user: cur_user = getattr(get_current_authuser(), 'username', None) from kallithea.lib.hooks import log_create_user, \ check_allowed_create_user _fd = form_data user_data = { 'username': _fd['username'], 'password': _fd['password'], 'email': _fd['email'], 'firstname': _fd['firstname'], 'lastname': _fd['lastname'], 'active': _fd['active'], 'admin': False } # raises UserCreationError if it's not allowed check_allowed_create_user(user_data, cur_user) from kallithea.lib.auth import get_crypt_password new_user = User() for k, v in form_data.items(): if k == 'password': v = get_crypt_password(v) if k == 'firstname': k = 'name' setattr(new_user, k, v) new_user.api_key = generate_api_key() Session().add(new_user) Session().flush() # make database assign new_user.user_id log_create_user(new_user.get_dict(), cur_user) return new_user
def test_send_mail_extra_headers(self): mailserver = 'smtp.mailserver.org' recipients = ['rcpt1', 'rcpt2'] envelope_from = '*****@*****.**' subject = 'subject' body = 'body' html_body = 'html_body' author = User(name='foo', lastname='(fubar) "baz"') headers = {'extra': 'yes'} config_mock = { 'smtp_server': mailserver, 'app_email_from': envelope_from, } with mock.patch('kallithea.lib.celerylib.tasks.config', config_mock): kallithea.lib.celerylib.tasks.send_email(recipients, subject, body, html_body, from_name=author.full_name_or_username, headers=headers) assert smtplib_mock.lastdest == set(recipients) assert smtplib_mock.lastsender == envelope_from assert r'From: "foo (fubar) \"baz\" (no-reply)" <%s>' % envelope_from in smtplib_mock.lastmsg assert 'Subject: %s' % subject in smtplib_mock.lastmsg assert body in smtplib_mock.lastmsg assert html_body in smtplib_mock.lastmsg assert 'Extra: yes' in smtplib_mock.lastmsg # verify that headers dict hasn't mutated by send_email assert headers == {'extra': 'yes'}
def create_test_user(force=True): print('creating test user') sa = get_session() user = sa.query(User).filter(User.username == USER).scalar() if force and user is not None: print('removing current user') for repo in sa.query(Repository).filter(Repository.user == user).all(): sa.delete(repo) sa.delete(user) sa.commit() if user is None or force: print('creating new one') new_usr = User() new_usr.username = USER new_usr.password = get_crypt_password(PASS) new_usr.email = '*****@*****.**' new_usr.name = 'test' new_usr.lastname = 'lasttestname' new_usr.active = True new_usr.admin = True sa.add(new_usr) sa.commit() print('done')
def test_forgot_password(self): response = self.app.get( url(controller='login', action='password_reset')) self.assertEqual(response.status, '200 OK') username = '******' password = '******' email = '*****@*****.**' name = 'passwd' lastname = 'reset' new = User() new.username = username new.password = password new.email = email new.name = name new.lastname = lastname new.api_key = generate_api_key(username) Session().add(new) Session().commit() response = self.app.post( url(controller='login', action='password_reset'), { 'email': email, }) self.checkSessionFlash(response, 'Your password reset link was sent') response = response.follow() # BAD KEY key = "bad" response = self.app.get( url(controller='login', action='password_reset_confirmation', key=key)) self.assertEqual(response.status, '302 Found') self.assertTrue(response.location.endswith(url('reset_password'))) # GOOD KEY key = User.get_by_username(username).api_key response = self.app.get( url(controller='login', action='password_reset_confirmation', key=key)) self.assertEqual(response.status, '302 Found') self.assertTrue(response.location.endswith(url('login_home'))) self.checkSessionFlash(response, ('Your password reset was successful, ' 'new password has been sent to your email')) response = response.follow()
def create_or_update(self, username, password, email, firstname='', lastname='', active=True, admin=False, extern_type=None, extern_name=None, cur_user=None): """ Creates a new instance if not found, or updates current one :param username: :param password: :param email: :param active: :param firstname: :param lastname: :param active: :param admin: :param extern_name: :param extern_type: :param cur_user: """ if not cur_user: cur_user = getattr(get_current_authuser(), 'username', None) from kallithea.lib.auth import get_crypt_password, check_password from kallithea.lib.hooks import log_create_user, \ check_allowed_create_user user_data = { 'username': username, 'password': password, 'email': email, 'firstname': firstname, 'lastname': lastname, 'active': active, 'admin': admin } # raises UserCreationError if it's not allowed check_allowed_create_user(user_data, cur_user) log.debug('Checking for %s account in Kallithea database', username) user = User.get_by_username(username, case_insensitive=True) if user is None: log.debug('creating new user %s', username) new_user = User() edit = False else: log.debug('updating user %s', username) new_user = user edit = True try: new_user.username = username new_user.admin = admin new_user.email = email new_user.active = active new_user.extern_name = extern_name new_user.extern_type = extern_type new_user.name = firstname new_user.lastname = lastname if not edit: new_user.api_key = generate_api_key() # set password only if creating an user or password is changed password_change = new_user.password and \ not check_password(password, new_user.password) if not edit or password_change: reason = 'new password' if edit else 'new user' log.debug('Updating password reason=>%s', reason) new_user.password = get_crypt_password(password) \ if password else '' if user is None: Session().add(new_user) Session().flush() # make database assign new_user.user_id if not edit: log_create_user(new_user.get_dict(), cur_user) return new_user except (DatabaseError,): log.error(traceback.format_exc()) raise
def test_forgot_password(self): response = self.app.get(base.url(controller='login', action='password_reset')) assert response.status == '200 OK' username = '******' password = '******' email = '*****@*****.**' name = 'passwd' lastname = 'reset' timestamp = int(time.time()) new = User() new.username = username new.password = password new.email = email new.name = name new.lastname = lastname new.api_key = generate_api_key() Session().add(new) Session().commit() token = UserModel().get_reset_password_token( User.get_by_username(username), timestamp, self.session_csrf_secret_token()) collected = [] def mock_send_email(recipients, subject, body='', html_body='', headers=None, from_name=None): collected.append((recipients, subject, body, html_body)) with mock.patch.object(kallithea.lib.celerylib.tasks, 'send_email', mock_send_email), \ mock.patch.object(time, 'time', lambda: timestamp): response = self.app.post(base.url(controller='login', action='password_reset'), {'email': email, '_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'A password reset confirmation code has been sent') ((recipients, subject, body, html_body),) = collected assert recipients == ['*****@*****.**'] assert subject == 'Password reset link' assert '\n%s\n' % token in body (confirmation_url,) = (line for line in body.splitlines() if line.startswith('http://')) assert ' href="%s"' % confirmation_url.replace('&', '&').replace('@', '%40') in html_body d = urllib.parse.parse_qs(urllib.parse.urlparse(confirmation_url).query) assert d['token'] == [token] assert d['timestamp'] == [str(timestamp)] assert d['email'] == [email] response = response.follow() # BAD TOKEN bad_token = "bad" response = self.app.post(base.url(controller='login', action='password_reset_confirmation'), {'email': email, 'timestamp': timestamp, 'password': "******", 'password_confirm': "p@ssw0rd", 'token': bad_token, '_session_csrf_secret_token': self.session_csrf_secret_token(), }) assert response.status == '200 OK' response.mustcontain('Invalid password reset token') # GOOD TOKEN response = self.app.get(confirmation_url) assert response.status == '200 OK' response.mustcontain("You are about to set a new password for the email address %s" % email) response.mustcontain('<form action="%s" method="post">' % base.url(controller='login', action='password_reset_confirmation')) response.mustcontain('value="%s"' % self.session_csrf_secret_token()) response.mustcontain('value="%s"' % token) response.mustcontain('value="%s"' % timestamp) response.mustcontain('value="*****@*****.**"') # fake a submit of that form response = self.app.post(base.url(controller='login', action='password_reset_confirmation'), {'email': email, 'timestamp': timestamp, 'password': "******", 'password_confirm': "p@ssw0rd", 'token': token, '_session_csrf_secret_token': self.session_csrf_secret_token(), }) assert response.status == '302 Found' self.checkSessionFlash(response, 'Successfully updated password') response = response.follow()
def test_forgot_password(self): response = self.app.get( url(controller='login', action='password_reset')) assert response.status == '200 OK' username = '******' password = '******' email = '*****@*****.**' name = u'passwd' lastname = u'reset' timestamp = int(time.time()) new = User() new.username = username new.password = password new.email = email new.name = name new.lastname = lastname new.api_key = generate_api_key() Session().add(new) Session().commit() response = self.app.post( url(controller='login', action='password_reset'), { 'email': email, }) self.checkSessionFlash( response, 'A password reset confirmation code has been sent') response = response.follow() # BAD TOKEN token = "bad" response = self.app.post( url(controller='login', action='password_reset_confirmation'), { 'email': email, 'timestamp': timestamp, 'password': "******", 'password_confirm': "p@ssw0rd", 'token': token, }) assert response.status == '200 OK' response.mustcontain('Invalid password reset token') # GOOD TOKEN # TODO: The token should ideally be taken from the mail sent # above, instead of being recalculated. token = UserModel().get_reset_password_token( User.get_by_username(username), timestamp, self.authentication_token()) response = self.app.get( url(controller='login', action='password_reset_confirmation', email=email, timestamp=timestamp, token=token)) assert response.status == '200 OK' response.mustcontain( "You are about to set a new password for the email address %s" % email) response = self.app.post( url(controller='login', action='password_reset_confirmation'), { 'email': email, 'timestamp': timestamp, 'password': "******", 'password_confirm': "p@ssw0rd", 'token': token, }) assert response.status == '302 Found' self.checkSessionFlash(response, 'Successfully updated password') response = response.follow()