def test_passwords_api(session, users, http_client, base_url, graph): user = users['*****@*****.**'] TEST_PASSWORD = "******" add_new_user_password(session, "test", TEST_PASSWORD, user.id) assert len(user_passwords(session, user)) == 1, "The user should only have a single password" graph.update_from_db(session) c = Counter.get(session, name="updates") api_url = url(base_url, '/users/{}'.format(user.username)) resp = yield http_client.fetch(api_url) body = json.loads(resp.body) assert body["checkpoint"] == c.count, "The API response is not up to date" assert body["data"]["user"]["passwords"] != [], "The user should not have an empty passwords field" assert body["data"]["user"]["passwords"][0]["name"] == "test", "The password should have the same name" assert body["data"]["user"]["passwords"][0]["func"] == "crypt(3)-$6$", "This test does not support any hash functions other than crypt(3)-$6$" assert body["data"]["user"]["passwords"][0]["hash"] == crypt.crypt(TEST_PASSWORD, body["data"]["user"]["passwords"][0]["salt"]), "The hash should be the same as hashing the password and the salt together using the hashing function" assert body["data"]["user"]["passwords"][0]["hash"] != crypt.crypt("hello", body["data"]["user"]["passwords"][0]["salt"]), "The hash should not be the same as hashing the wrong password and the salt together using the hashing function" delete_user_password(session, "test", user.id) c = Counter.get(session, name="updates") graph.update_from_db(session) api_url = url(base_url, '/users/{}'.format(user.username)) resp = yield http_client.fetch(api_url) body = json.loads(resp.body) assert body["checkpoint"] == c.count, "The API response is not up to date" assert body["data"]["user"]["passwords"] == [], "The user should not have any passwords"
def post(self, user_id=None, name=None): user = User.get(self.session, user_id, name) if not user: return self.notfound() if not self.check_access(self.session, self.current_user, user): return self.forbidden() form = UserPasswordForm(self.request.arguments) if not form.validate(): return self.render("user-password-add.html", form=form, user=user, alerts=self.get_form_alerts(form.errors)) pass_name = form.data["name"] password = form.data["password"] try: add_new_user_password(self.session, pass_name, password, user.id) except PasswordAlreadyExists: self.session.rollback() form.name.errors.append("Name already in use.") return self.render("user-password-add.html", form=form, user=user, alerts=self.get_form_alerts(form.errors)) AuditLog.log( self.session, self.current_user.id, "add_password", "Added password: {}".format(pass_name), on_user_id=user.id, ) email_context = {"actioner": self.current_user.name, "changed_user": user.name, "pass_name": pass_name} send_email(self.session, [user.name], "User password created", "user_password_created", settings, email_context) return self.redirect("/users/{}?refresh=yes".format(user.name))
def post(self, *args, **kwargs): # type: (*Any, **Any) -> None user_id = kwargs.get("user_id") # type: Optional[int] name = kwargs.get("name") # type: Optional[str] user = User.get(self.session, user_id, name) if not user: return self.notfound() if not self.check_access(self.session, self.current_user, user): return self.forbidden() form = UserPasswordForm(self.request.arguments) if not form.validate(): return self.render( "user-password-add.html", form=form, user=user, alerts=self.get_form_alerts(form.errors), ) pass_name = form.data["name"] password = form.data["password"] try: add_new_user_password(self.session, pass_name, password, user.id) except PasswordAlreadyExists: self.session.rollback() form.name.errors.append("Name already in use.") return self.render( "user-password-add.html", form=form, user=user, alerts=self.get_form_alerts(form.errors), ) AuditLog.log( self.session, self.current_user.id, "add_password", "Added password: {}".format(pass_name), on_user_id=user.id, ) email_context = { "actioner": self.current_user.name, "changed_user": user.name, "pass_name": pass_name, } send_email( self.session, [user.name], "User password created", "user_password_created", settings(), email_context, ) return self.redirect("/users/{}?refresh=yes".format(user.name))
def test_passwords(session, users): user = users["*****@*****.**"] add_new_user_password(session, "test", TEST_PASSWORD, user.id) assert len(user_passwords(session, user)) == 1, "The user should only have a single password" password = user_passwords(session, user)[0] assert password.name == "test", "The password should have the name we gave it" assert password.password_hash != TEST_PASSWORD, "The password should not be what is passed in" assert password.check_password(TEST_PASSWORD), "The password should validate when given the same password" assert not password.check_password("sadfjhsdf"), "Incorrect passwords should fail" add_new_user_password(session, "test2", TEST_PASSWORD, user.id) assert len(user_passwords(session, user)) == 2, "The user should have 2 passwords" password2 = user_passwords(session, user)[1] assert password2.name == "test2", "The password should have the name we gave it" assert password2.password_hash != TEST_PASSWORD, "The password should not be what is passed in" assert password2.check_password(TEST_PASSWORD), "The password should validate when given the same password" assert not password2.check_password("sadfjhsdf"), "Incorrect passwords should fail" with pytest.raises(PasswordAlreadyExists): add_new_user_password(session, "test", TEST_PASSWORD, user.id) session.rollback() # Technically there's a very very very small O(1/2^160) chance that this will fail for a correct implementation assert ( password.password_hash != password2.password_hash ), "2 passwords that are identical should hash differently because of the salts" delete_user_password(session, "test", user.id) assert len(user_passwords(session, user)) == 1, "The user should only have a single password" assert user_passwords(session, user)[0].name == "test2", "The password named test should have been deleted"
def test_passwords(session, users): user = users['*****@*****.**'] add_new_user_password(session, "test", TEST_PASSWORD, user.id) assert len(user_passwords(session, user)) == 1, "The user should only have a single password" password = user_passwords(session, user)[0] assert password.name == "test", "The password should have the name we gave it" assert password.password_hash != TEST_PASSWORD, "The password should not be what is passed in" assert password.check_password(TEST_PASSWORD), "The password should validate when given the same password" assert not password.check_password("sadfjhsdf"), "Incorrect passwords should fail" add_new_user_password(session, "test2", TEST_PASSWORD, user.id) assert len(user_passwords(session, user)) == 2, "The user should have 2 passwords" password2 = user_passwords(session, user)[1] assert password2.name == "test2", "The password should have the name we gave it" assert password2.password_hash != TEST_PASSWORD, "The password should not be what is passed in" assert password2.check_password(TEST_PASSWORD), "The password should validate when given the same password" assert not password2.check_password("sadfjhsdf"), "Incorrect passwords should fail" with pytest.raises(PasswordAlreadyExists): add_new_user_password(session, "test", TEST_PASSWORD, user.id) session.rollback() # Technically there's a very very very small O(1/2^160) chance that this will fail for a correct implementation assert password.password_hash != password2.password_hash, "2 passwords that are identical should hash differently because of the salts" delete_user_password(session, "test", user.id) assert len(user_passwords(session, user)) == 1, "The user should only have a single password" assert user_passwords(session, user)[0].name == "test2", "The password named test should have been deleted"