def test_verify_email(self, clean_mongo, smtp_mock): uuidv4 = str(uuid.uuid4()) tenant, email, password = ( "test.mender.io-" + uuidv4, "some.user+" + uuidv4 + "@example.com", "secretsecret", ) create_org(tenant, email, password) # login and try to enable two factor authentication # it shouldn't be possible since the user email address # has not been verified r = self.uc.call("POST", useradm.URL_LOGIN, auth=(email, password)) assert r.status_code == 200 utoken = r.text r = self.uc.with_auth(utoken).call( "POST", useradm.URL_SETTINGS, body={"2fa": "enabled"} ) assert r.status_code == 403 # verify user email address r = self.uc.post(useradm.URL_VERIFY_EMAIL_START, body={"email": email}) assert r.status_code == 202 # wait for the verification email message = None for i in range(15): messages = smtp_mock.filtered_messages(email) if len(messages) > 0: message = messages[0] break time.sleep(1) # be sure we received the email assert message is not None assert message.data != "" # extract the secret hash from the link match = re.search( r"https://hosted.mender.io/ui/#/activate/([a-z0-9\-]+)", message.data.decode("utf-8"), ) secret_hash = match.group(1) assert secret_hash != "" # complete the email address r = self.uc.post( useradm.URL_VERIFY_EMAIL_COMPLETE, body={"secret_hash": secret_hash}, ) assert r.status_code == 204 # try to enable two factor authentication after email address verification # now it should be possible r = self.uc.with_auth(utoken).call( "POST", useradm.URL_SETTINGS, body={"2fa": "enabled"} ) assert r.status_code == 201
def test_contact_support(self, clean_mongo, smtp_mock): uuidv4 = str(uuid.uuid4()) tenant, email, password = ( "test.mender.io-" + uuidv4, "some.user-" + uuidv4 + "@example.com", "secretsecret", ) org = create_org(tenant, email, password) r = api_useradm.call("POST", useradm.URL_LOGIN, auth=(email, password)) assert r.status_code == 200 utoken = r.text r = api_tadm_v2.with_auth(utoken).call( "POST", tenantadm_v2.URL_CONTACT_SUPPORT, body={ "subject": "foo", "body": "bar" }, ) assert r.status_code == 202 # wait for the email message = None for i in range(15): messages = smtp_mock.filtered_messages("*****@*****.**") if len(messages) > 0: message = messages[0] break time.sleep(1) # be sure we received the email assert message is not None assert message.data != "" # and the email is properly formatted data = message.data.decode("utf-8") match = re.search( r"Subject: ([a-z0-9\-]+)", data, ) subject = match.group(1) assert re.search(r"Subject: foo", data) is not None assert re.search(r"From: [email protected]", data) is not None assert re.search(r"To: [email protected]", data) is not None assert re.search(r"Organization ID: " + org.id, data) is not None assert re.search(r"Organization name: " + tenant, data) is not None assert re.search(r"Plan name: os", data) is not None assert re.search(r"User ID: " + org.users[0].id, data) is not None assert re.search(r"User Email: " + email, data) is not None assert re.search(r"bar", data) is not None
def test_password_reset(self, clean_mongo, smtp_mock): uuidv4 = str(uuid.uuid4()) tenant, email, password = ( "test.mender.io-" + uuidv4, "some.user+" + uuidv4 + "@example.com", "secretsecret", ) create_org(tenant, email, password) new_password = "******" r = self.uc.post(useradm.URL_PASSWORD_RESET_START, body={"email": email}) assert r.status_code == 202 # wait for the password reset email message = None for i in range(15): messages = smtp_mock.filtered_messages(email) if len(messages) > 0: message = messages[0] break time.sleep(1) # be sure we received the email assert message is not None assert message.data != "" # extract the secret hash from the link match = re.search( r"https://hosted.mender.io/ui/#/password/([a-z0-9\-]+)", message.data.decode("utf-8"), ) secret_hash = match.group(1) assert secret_hash != "" # reset the password r = self.uc.post( useradm.URL_PASSWORD_RESET_COMPLETE, body={"secret_hash": secret_hash, "password": new_password}, ) assert r.status_code == 202 # try to login using the new password r = self.uc.call("POST", useradm.URL_LOGIN, auth=(email, new_password)) assert r.status_code == 200 assert bool(r.text)
def test_enable_disable(self, tenants_users, smtp_mock): user_2fa = tenants_users[0].users[0] user_no_2fa = tenants_users[0].users[1] r = self._login(user_2fa) assert r.status_code == 200 user_2fa_tok = r.text # some error scenarios related to invalid 2fa state # before email verification - can't touch settings for on in [True, False]: r = self._toggle_tfa(user_2fa_tok, user_2fa.id, on=True) assert r.status_code == 403 # /2faqr available only in 'unverified' state r = uadm.with_auth(user_2fa_tok).call("GET", useradm.URL_2FAQR) assert r.status_code == 400 # /verify available only in 'unverified' state r = uadm.with_auth(user_2fa_tok).call("GET", useradm.URL_2FAQR) assert r.status_code == 400 # verify user email address r = uadm.post(useradm.URL_VERIFY_EMAIL_START, body={"email": user_2fa.name}) assert r.status_code == 202 # wait for the verification email message = None for i in range(15): messages = smtp_mock.filtered_messages(user_2fa.name) if len(messages) > 0: message = messages[0] break time.sleep(1) # be sure we received the email assert message is not None assert message.data != "" # extract the secret hash from the link match = re.search( r"https://hosted.mender.io/ui/#/activate/([a-z0-9\-]+)", message.data.decode("utf-8"), ) secret_hash = match.group(1) assert secret_hash != "" # complete the email address r = uadm.post(useradm.URL_VERIFY_EMAIL_COMPLETE, body={"secret_hash": secret_hash}) assert r.status_code == 204 # enable tfa for 1 user, straight login still works, token is not verified r = self._toggle_tfa(user_2fa_tok, user_2fa.id, on=True) assert r.status_code == 200 r = self._login(user_2fa) assert r.status_code == 200 # get the user info and verify 2fa status user = self._get_user(user_2fa_tok) assert user["tfa_status"] == TFA_UNVERIFIED # grab qr code, extract token, calc TOTP r = uadm.with_auth(user_2fa_tok).call("GET", useradm.URL_2FAQR) assert r.status_code == 200 secret = self._qr_dec(r.json()["qr"]) totp = pyotp.TOTP(secret) tok = totp.now() # verify token r = self._verify(user_2fa_tok, tok) assert r.status_code == 202 # get the user info and verify 2fa status user = self._get_user(user_2fa_tok) assert user["tfa_status"] == TFA_ENABLED # login with totp succeeds r = self._login(user_2fa, totp=tok) assert r.status_code == 200 # already enabled - can't enable twice r = self._toggle_tfa(user_2fa_tok, user_2fa.id, on=True) assert r.status_code == 400 # logi without otp now does not work r = self._login(user_2fa) assert r.status_code == 401 # the other user, and other tenant's users, are unaffected r = self._login(user_no_2fa) assert r.status_code == 200 user_no_2fa_tok = r.text # other users can't change our settings r = self._toggle_tfa(user_no_2fa_tok, user_2fa.id, on=False) assert r.status_code == 401 # get the user info and verify 2fa status user = self._get_user(user_2fa_tok) assert user["tfa_status"] == TFA_ENABLED for other_user in tenants_users[1].users: r = self._login(other_user) assert r.status_code == 200 # after disabling - straight login works again r = self._toggle_tfa(user_2fa_tok, "me", on=False) assert r.status_code == 200 r = self._login(user_2fa) assert r.status_code == 200 # get the user info and verify 2fa status user = self._get_user(user_2fa_tok) assert user["tfa_status"] == TFA_DISABLED # although POST /settings is still functional, # it will not save any 2fa settings, and will not break # any user's statuses # simulate overwriting user statuses - no effect signore = self._make_2fa_settings({ user_2fa.id: TFA_ENABLED, user_no_2fa.id: TFA_ENABLED }) r = uadm.with_auth(user_2fa_tok).call("POST", useradm.URL_SETTINGS, signore) assert r.status_code == 201 # get the user info and verify 2fa status user = self._get_user(user_2fa_tok) assert user["tfa_status"] == TFA_DISABLED
def test_enable_disable(self, tenants_users, smtp_mock): user_2fa = tenants_users[0].users[0] user_no_2fa = tenants_users[0].users[1] r = self._login(user_2fa) assert r.status_code == 200 user_2fa_tok = r.text # verify user email address r = uadm.post(useradm.URL_VERIFY_EMAIL_START, body={"email": user_2fa.name}) assert r.status_code == 202 # wait for the verification email message = None for i in range(15): messages = smtp_mock.filtered_messages(user_2fa.name) if len(messages) > 0: message = messages[0] break time.sleep(1) # be sure we received the email assert message is not None assert message.data != "" # extract the secret hash from the link match = re.search( r"https://hosted.mender.io/ui/#/activate/([a-z0-9\-]+)", message.data.decode("utf-8"), ) secret_hash = match.group(1) assert secret_hash != "" # complete the email address r = uadm.post(useradm.URL_VERIFY_EMAIL_COMPLETE, body={"secret_hash": secret_hash}) assert r.status_code == 204 # enable tfa for 1 user, straight login still works, token is not verified self._toggle_tfa(user_2fa_tok, user_2fa.id, on=True) r = self._login(user_2fa) assert r.status_code == 200 # grab qr code, extract token, calc TOTP r = uadm.with_auth(user_2fa_tok).call("GET", useradm.URL_2FAQR) assert r.status_code == 200 secret = self._qr_dec(r.json()["qr"]) totp = pyotp.TOTP(secret) tok = totp.now() # verify token r = self._verify(user_2fa_tok, tok) assert r.status_code == 202 # login with totp succeeds r = self._login(user_2fa, totp=tok) assert r.status_code == 200 # logi without otp now does not work r = self._login(user_2fa) assert r.status_code == 401 # the other user, and other tenant's users, are unaffected r = self._login(user_no_2fa) assert r.status_code == 200 for other_user in tenants_users[1].users: r = self._login(other_user) assert r.status_code == 200 # after disabling - straight login works again self._toggle_tfa(user_2fa_tok, user_2fa.id, on=False) r = self._login(user_2fa) assert r.status_code == 200