def wsgi_factory(): # pragma: no cover morepath.autoscan() if os.getenv("RUN_ENV") == "production": ProductionApp.commit() app = ProductionApp() elif os.getenv("RUN_ENV") == "test": TestApp.commit() app = TestApp() else: App.commit() app = App() index = FileApp("build/index.html") static = DirectoryApp("build", index_page=None) setup_db(app) @webob.dec.wsgify def morepath_with_static_absorb(request): popped = request.path_info_pop() if popped == "api": return request.get_response(app) elif popped == "static": return request.get_response(static) else: return request.get_response(index) return morepath_with_static_absorb
def test_update_group(): c = Client(App()) response = c.post( "/login", json.dumps({ "email": "*****@*****.**", "password": "******" })) headers = {"Authorization": response.headers["Authorization"]} updateted_group_json = json.dumps( {"users": ["*****@*****.**", "*****@*****.**"]}) c.put("/groups/3", updateted_group_json, headers=headers) with db_session: g = Group[3] assert User[2] in g.users assert User[3] in g.users updateted_group_json = json.dumps({"name": "Moderator"}) response = c.put("/groups/1", updateted_group_json, headers=headers, status=409) assert response.json == {"validationError": "Group already exists"} updateted_group_json = json.dumps({"name": "Guru"}) c.put("/groups/1", updateted_group_json, headers=headers) with db_session: assert Group[1].name == "Guru"
def test_send_reset_email(smtp): c = Client(App(), extra_environ=dict(REMOTE_ADDR="127.0.0.1")) new_user_json = json.dumps( {"nickname": "NewUser", "email": "*****@*****.**", "password": "******"} ) c.post("/users", new_user_json, status=201) assert len(smtp.outbox) == 2 response = c.post( "/reset", json.dumps({"email": "*****@*****.**"}), status=403 ) assert response.json == {"validationError": "Email not found"} response = c.post( "/reset", json.dumps({"email": "*****@*****.**"}), status=403 ) assert response.json == { "validationError": "Your email must be confirmed before resetting the password." } c.get( "/users/4/confirm/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C3dnsw.2meomRPK3wnYwB2AERt2ygjFaRE", status=302, ) response = c.post("/reset", json.dumps({"email": "*****@*****.**"})) assert len(smtp.outbox) == 3 message = smtp.outbox[2] assert message["subject"] == "Password Reset Requested" assert message["To"] == "*****@*****.**"
def test_sorted_user_collection(): c = Client(App()) with db_session: User[1].email_confirmed = True response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} response = c.get("/users?sortby=nickname", headers=headers) assert response.json["users"][0]["nickname"] == "Jürgen" response = c.get("/users?sortby=email&sortdir=desc", headers=headers) assert response.json["users"][0]["email"] == "*****@*****.**" response = c.get("/users?sortby=emailConfirmed", headers=headers) assert response.json["users"][0]["nickname"] == "Mary" response = c.get("/users?sortby=lastLogin", headers=headers) assert response.json["users"][0]["nickname"] == "Mary" response = c.get("/users?sortby=registerIP", headers=headers) assert response.json["users"][0]["nickname"] == "Leader"
def test_reset_nonce(): c = Client(App()) response = c.get("/users/2/signout", status=403) assert response.body == ( b"403 Forbidden\n\nAccess was denied to this resource.\n\n " ) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} with db_session: original_nonce = User[2].nonce c.get("/users/2/signout", headers=headers) with db_session: assert User[2].nonce != original_nonce response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} with db_session: original_nonce = User[2].nonce c.get("/users/2/signout", headers=headers) with db_session: assert User[2].nonce != original_nonce
def test_add_group(): c = Client(App()) response = c.post( "/login", json.dumps({ "email": "*****@*****.**", "password": "******" })) headers = {"Authorization": response.headers["Authorization"]} new_group_json = json.dumps({"name": "NewGroup"}) response = c.post("/groups", new_group_json, headers=headers, status=201) assert response.json == {"@id": "/groups/4"} with db_session: assert Group.exists(name="NewGroup") response = c.post("/groups", new_group_json, headers=headers, status=409) assert response.json == {"validationError": "Group already exists"} with_users_json = json.dumps({ "name": "UserGroup", "users": ["*****@*****.**", "*****@*****.**", "*****@*****.**"], }) c.post("/groups", with_users_json, headers=headers) with db_session: assert Group.exists(name="UserGroup") assert User[1] in Group.get(name="UserGroup").users assert User[2] in Group.get(name="UserGroup").users assert User[3] in Group.get(name="UserGroup").users
def test_list(): c = Client(App()) response = c.get("/todos") todo_list = { "todos": [ { "@id": "http://localhost/todos/0", "title": "Code", "completed": True }, { "@id": "http://localhost/todos/1", "title": "Test", "completed": False }, { "@id": "http://localhost/todos/2", "title": "Document", "completed": False, }, { "@id": "http://localhost/todos/3", "title": "Release", "completed": False }, ] } assert response.json == todo_list
def test_add_todo(): c = Client(App()) new_todo_json = json.dumps({"title": "Something else", "completed": False}) response = c.post('/todos', new_todo_json) new_todo_response = {"@id": "http://localhost/todos/4", "title": "Something else", "completed": False} assert response.json == new_todo_response
def test_todo(): c = Client(App()) response = c.get("/todos/0") assert response.json == { "@id": "http://localhost/todos/0", "title": "Code", "completed": True, }
def test_group(): c = Client(App()) response = c.get("/groups/1") group = { "@id": "/groups/1", "name": "Admin", "users": ["*****@*****.**"] } assert_dict_contains_subset(group, response.json)
def test_change_todo(): c = Client(App()) changed_todo_json = json.dumps( {"title": "Changed Test", "completed": True} ) response = c.put('/todos/1', changed_todo_json) changed_todo_response = {"@id": "http://localhost/todos/1", "title": "Changed Test", "completed": True} assert response.json == changed_todo_response
def test_reset_password(smtp): c = Client(App(), extra_environ=dict(REMOTE_ADDR="127.0.0.1")) new_user_json = json.dumps( {"nickname": "NewUser", "email": "*****@*****.**", "password": "******"} ) c.post("/users", new_user_json, status=201) assert len(smtp.outbox) == 1 response = c.get( "/users/4/reset/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.WrongToken.JrUGhlAxao46VsQevI", status=302, ) flash = ( urlsafe_b64encode(b"The password reset link is invalid or has been expired") .replace(b"=", b"") .decode("utf-8") ) assert "302 Found" in response.text assert "flash=" + flash in response.text assert "flashtype=error" in response.text response = c.get( "/users/4/reset/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C40RUQ.5JhlEE36_JrUGhlAxao46VsQevI", status=302, ) flash = ( urlsafe_b64encode(b"Your email must be confirmed before resetting the password") .replace(b"=", b"") .decode("utf-8") ) assert "302 Found" in response.text assert "flash=" + flash in response.text assert "flashtype=error" in response.text c.get( "/users/4/confirm/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C3dnsw.2meomRPK3wnYwB2AERt2ygjFaRE", status=302, ) response = c.get( "/users/4/reset/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C40RUQ.5JhlEE36_JrUGhlAxao46VsQevI", status=302, ) assert response.location == ( "http://localhost/newpassword?%40id=%2Fusers%2F4%2Freset%2F" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C40RUQ.5JhlEE36_JrUGhlAxao46VsQevI" )
def test_delete_todo(): c = Client(App()) response = c.delete('/todos/2') todo_list = {"todos": [ {"@id": "http://localhost/todos/0", "title": "Code", "completed": True}, {"@id": "http://localhost/todos/1", "title": "Test", "completed": False}, {"@id": "http://localhost/todos/3", "title": "Release", "completed": False} ]} assert response.json == todo_list
def test_root(): app = App() c = Client(app) response = c.get("/") assert response.json == { "collections": { "users": { "@id": "/users" }, "groups": { "@id": "/groups" } } }
def test_confirm_email(): c = Client(App(), extra_environ=dict(REMOTE_ADDR="127.0.0.1")) new_user_json = json.dumps( {"nickname": "NewUser", "email": "*****@*****.**", "password": "******"} ) c.post("/users", new_user_json, status=201) response = c.get("/users/4/confirm/" + "Im5ld.WrongToken.jFaRE", status=302) flash = ( urlsafe_b64encode(b"The confirmation link is invalid or has been expired") .replace(b"=", b"") .decode("utf-8") ) assert "302 Found" in response.text assert "flash=" + flash in response.text assert "flashtype=error" in response.text response = c.get( "/users/4/confirm/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C3dnsw.2meomRPK3wnYwB2AERt2ygjFaRE", status=302, ) flash = ( urlsafe_b64encode(b"Thank you for confirming your email address") .replace(b"=", b"") .decode("utf-8") ) assert "302 Found" in response.text assert "flash=" + flash in response.text assert "flashtype=success" in response.text response = c.get( "/users/4/confirm/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C3dnsw.2meomRPK3wnYwB2AERt2ygjFaRE", status=302, ) flash = ( urlsafe_b64encode(b"Your email is already confirmed. Please log in.") .replace(b"=", b"") .decode("utf-8") ) assert "302 Found" in response.text assert "flash=" + flash in response.text assert "flashtype=info" in response.text
def test_delete_user(): c = Client(App()) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} with db_session: assert User.exists(nickname="Mary") c.delete("/users/2", headers=headers) with db_session: assert not User.exists(nickname="Mary")
def test_user_collection_combined_query(): c = Client(App()) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} response = c.get( "/users?search=example.com&sortby=nickname&page=1&pagesize=2", headers=headers ) assert len(response.json["users"]) == 2 assert response.json["pages"] == 2 assert response.json["users"][0]["nickname"] == "Jürgen"
def test_update_password(smtp): c = Client(App(), extra_environ=dict(REMOTE_ADDR="127.0.0.1")) new_user_json = json.dumps( {"nickname": "NewUser", "email": "*****@*****.**", "password": "******"} ) c.post("/users", new_user_json, status=201) assert len(smtp.outbox) == 1 update_password_json = json.dumps({"password": "******"}) response = c.put( "/users/4/reset/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.WrongToken.JrUGhlAxao46VsQevI", update_password_json, status=403, ) assert response.json == { "validationError": "The password reset link is invalid or has been expired" } response = c.put( "/users/4/reset/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C40RUQ.5JhlEE36_JrUGhlAxao46VsQevI", update_password_json, status=403, ) assert response.json == { "validationError": "Your email must be confirmed before resetting the password" } c.get( "/users/4/confirm/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C3dnsw.2meomRPK3wnYwB2AERt2ygjFaRE", status=302, ) response = c.put( "/users/4/reset/" + "Im5ld3VzZXJAZXhhbXBsZS5jb20i.C40RUQ.5JhlEE36_JrUGhlAxao46VsQevI", update_password_json, ) ph = PasswordHasher() with db_session: assert ph.verify(User[4].password, "new_secret")
def test_refresh_token(): app = App() c = Client(app) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} response = c.get("/refresh", headers=headers) jwtauth_settings = app.settings.jwtauth.__dict__.copy() identity_policy = JWTIdentityPolicy(**jwtauth_settings) authtype, token = response.headers["Authorization"].split(" ", 1) claims_set_decoded = identity_policy.decode_jwt(token) assert identity_policy.get_userid(claims_set_decoded) == "*****@*****.**" with db_session: # set new nonce to invalid current tokens for this user User[2].nonce = uuid4().hex response = c.get("/refresh", headers=headers, status=403) assert response.json == {"validationError": "Could not refresh your token"} now = timegm(datetime.utcnow().utctimetuple()) with db_session: nonce = User.get(email="*****@*****.**").nonce claims_set = { "sub": "*****@*****.**", "uid": "/users/2", "refresh_until": now - 3, "nonce": nonce, "exp": now + 3, } token = identity_policy.encode_jwt(claims_set) headers = {"Authorization": "JWT " + token} response = c.get("/refresh", headers=headers, status=403) assert response.json == {"validationError": "Your session has expired"}
def test_paginated_user_collection(): c = Client(App()) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} response = c.get("/users?page=1&pagesize=2", headers=headers) assert len(response.json["users"]) == 2 assert response.json["pages"] == 2 response = c.get("/users?page=2&pagesize=2", headers=headers) assert len(response.json["users"]) == 1 assert response.json["pages"] == 2
def test_delete_group(): c = Client(App()) response = c.post( "/login", json.dumps({ "email": "*****@*****.**", "password": "******" })) headers = {"Authorization": response.headers["Authorization"]} with db_session: assert Group.exists(name="Moderator") c.delete("/groups/2", headers=headers) with db_session: assert not Group.exists(name="Moderator")
def test_groups_collection(): c = Client(App()) response = c.post( "/login", json.dumps({ "email": "*****@*****.**", "password": "******" })) headers = {"Authorization": response.headers["Authorization"]} response = c.get("/groups", headers=headers) group_1 = { "@id": "/groups/1", "name": "Admin", "users": ["*****@*****.**"] } assert_dict_contains_subset(group_1, response.json["groups"][0])
def test_login(): app = App() c = Client(app) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}), status=403, ) assert response.json == {"validationError": "Invalid email or password"} response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}), status=403, ) assert response.json == {"validationError": "Invalid email or password"} response = c.post( "/login", json.dumps({"email": "test@example", "password": "******"}), status=403, ) assert response.json == {"validationError": "Invalid email or password"} response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}), status=422, ) assert response.json == {"password": ["min length is 5"]} response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) jwtauth_settings = app.settings.jwtauth.__dict__.copy() identity_policy = JWTIdentityPolicy(**jwtauth_settings) authtype, token = response.headers["Authorization"].split(" ", 1) claims_set_decoded = identity_policy.decode_jwt(token) assert identity_policy.get_userid(claims_set_decoded) == "*****@*****.**"
def test_user_collection(): c = Client(App()) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} response = c.get("/users", headers=headers) user_1 = { "@id": "/users/1", "nickname": "Leader", "email": "*****@*****.**", "emailConfirmed": False, "isAdmin": True, "registerIP": "", } assert_dict_contains_subset(user_1, response.json["users"][0]) user_2 = { "@id": "/users/2", "nickname": "Mary", "email": "*****@*****.**", "emailConfirmed": False, "isAdmin": False, "registerIP": "", } assert_dict_contains_subset(user_2, response.json["users"][1]) user_3 = { "@id": "/users/3", "nickname": "Jürgen", "email": "*****@*****.**", "emailConfirmed": False, "isAdmin": False, "registerIP": "", } assert_dict_contains_subset(user_3, response.json["users"][2])
def test_user(): c = Client(App()) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} response = c.get("/users/2", headers=headers) user = { "@id": "/users/2", "nickname": "Mary", "email": "*****@*****.**", "isAdmin": False, "emailConfirmed": False, "registerIP": "", } assert_dict_contains_subset(user, response.json)
def test_search_user_collection(): c = Client(App()) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} response = c.get("/users?search=" + urllib.parse.quote("jürgen"), headers=headers) assert len(response.json["users"]) == 1 assert response.json["users"][0]["nickname"] == "Jürgen" response = c.get("/[email protected]", headers=headers) assert len(response.json["users"]) == 1 assert response.json["users"][0]["nickname"] == "Leader" response = c.get("/users?search=example.com", headers=headers) assert len(response.json["users"]) == 3
def test_add_user(smtp): assert len(smtp.outbox) == 0 c = Client(App(), extra_environ=dict(REMOTE_ADDR="127.0.0.1")) new_user_json = json.dumps( {"nickname": "NewUser", "email": "*****@*****.**", "password": "******"} ) response = c.post("/users", new_user_json, status=201) with db_session: assert User.exists(nickname="NewUser") assert User.get(nickname="NewUser").register_ip == "127.0.0.1" assert len(smtp.outbox) == 1 message = smtp.outbox[0] assert message["subject"] == "Confirm Your Email Address" assert message["To"] == "*****@*****.**" response = c.post("/users", new_user_json, status=409) assert response.json == {"validationError": "Email already exists"} assert len(smtp.outbox) == 1 with db_session: new_editor_json = json.dumps( { "nickname": "NewEditor", "email": "*****@*****.**", "password": "******", "groups": ["Editor"], } ) c.post("/users", new_editor_json) assert User.exists(nickname="NewEditor") assert Group.get(name="Editor") in User.get(nickname="NewEditor").groups assert User.get(nickname="NewEditor").email == "*****@*****.**" assert len(smtp.outbox) == 2 message = smtp.outbox[1] assert message["subject"] == "Confirm Your Email Address" assert message["To"] == "*****@*****.**" new_user_json = json.dumps( { "nickname": "NewUser", "email": "*****@*****.**", "password": "******", } ) response = c.post("/users", new_user_json, status=422) assert response.json == {"email": ["Email could not be delivered"]} new_user_json = json.dumps( {"nickname": "NewUser", "email": "newuser@example", "password": "******"} ) response = c.post("/users", new_user_json, status=422) assert response.json == {"email": ["Not valid email"]} new_user_json = json.dumps( { "nickname": 123, "email": "*****@*****.**", "password": "******", } ) response = c.post("/users", new_user_json, status=422) assert response.json == {"nickname": ["must be of string type"]}
def test_root(): c = Client(App()) response = c.get("/") assert response.json == {"collection": "http://localhost/todos"}
from server import App, BaseView import utils import asyncio import os import datetime import serializers from bson import ObjectId from settings import db, host, port app = App() @app.route('/login/') class LoginView(BaseView): @asyncio.coroutine def post(self): '''do the login :)''' email = self.request.data.get('email') password = self.request.data.get('password') user = yield from db.users.find_one({'email': email}) if user: password_hash = yield from utils.get_password_hash( user['salt'], password.encode()) if user['password'] == password_hash: user['last_login'] = datetime.datetime.now() yield from db.users.save(user) user['token'] = yield from utils.generate_token(user) yield from serializers.user(user)
from server import App, BaseView import utils import asyncio import os import datetime import serializers from bson import ObjectId from settings import db, host, port app = App() @app.route('/login/') class LoginView(BaseView): @asyncio.coroutine def post(self): '''do the login :)''' email = self.request.data.get('email') password = self.request.data.get('password') user = yield from db.users.find_one({ 'email': email }) if user: password_hash = yield from utils.get_password_hash( user['salt'], password.encode() ) if user['password'] == password_hash:
def test_update_user(smtp): c = Client(App()) response = c.post( "/login", json.dumps({"email": "*****@*****.**", "password": "******"}) ) headers = {"Authorization": response.headers["Authorization"]} update_user_json = json.dumps({"nickname": "Guru"}) c.put("/users/1", update_user_json, headers=headers) with db_session: assert User[1].nickname == "Guru" update_user_json = json.dumps({"nickname": "Guru"}) c.put("/users/1", update_user_json, headers=headers) with db_session: assert User[1].nickname == "Guru" update_user_json = json.dumps({"email": "guru@example"}) response = c.put("/users/1", update_user_json, headers=headers, status=422) assert response.json == {"email": ["Not valid email"]} update_user_json = json.dumps({"email": "*****@*****.**"}) c.put("/users/2", update_user_json, headers=headers) with db_session: assert User[2].email == "*****@*****.**" assert len(smtp.outbox) == 1 message = smtp.outbox[0] assert message["subject"] == "Confirm Your Email Address" assert message["To"] == "*****@*****.**" response = c.put("/users/2", update_user_json, headers=headers, status=409) assert response.json == {"validationError": "Email already exists"} assert len(smtp.outbox) == 1 update_user_json = json.dumps({"password": "******"}) c.put("/users/1", update_user_json, headers=headers) ph = PasswordHasher() with db_session: assert ph.verify(User[1].password, "secret0") update_user_json = json.dumps({"groups": ["Moderator"]}) c.put("/users/3", update_user_json, headers=headers) with db_session: u = User[3] editor = Group.get(name="Editor") moderator = Group.get(name="Moderator") assert editor not in u.groups assert moderator in u.groups update_user_json = json.dumps({"groups": []}) c.put("/users/3", update_user_json, headers=headers) with db_session: u = User[3] editor = Group.get(name="Editor") moderator = Group.get(name="Moderator") assert editor not in u.groups assert moderator not in u.groups