async def test_update_one_user_as_supervisor(users, supervisor1_client): new_changes = { "full_name": "this name surely doesnt exist", "password": "******", } # With id res = await supervisor1_client.patch("/users/{}".format(users[0]["id"]), json=new_changes) assert res.status == 200 body = await res.json() assert "data" in body assert isinstance(body["data"], dict) updated_user = await get_one(User, internal_id=1) updated_user = updated_user.to_dict() ## Assert the new password has been updated assert profile_created_from_origin( { **body["data"], "password": hash_password(new_changes["password"]) }, updated_user, ) # User doesnt exist res = await supervisor1_client.patch("/users/{}".format("9" * 32), json=new_changes) assert res.status == 404 # Update to a weak password new_changes = {"password": "******"} res = await supervisor1_client.patch("/users/{}".format(users[1]["id"]), json=new_changes) assert res.status == 400
async def test_update_anonymous_as_self(visitors, anonymous1_client): new_changes = { "name": "this name surely doesnt exist", "password": "******", } # With id res = await anonymous1_client.patch("/visitors/{}".format( visitors[-4]["id"]), json=new_changes) assert res.status == 200 body = await res.json() assert "data" in body assert isinstance(body["data"], dict) updated_user = await get_one(Visitor, id=visitors[-4]["id"]) updated_user = updated_user.to_dict() ## Assert the new password has been updated assert profile_created_from_origin( { **body["data"], "password": hash_password(new_changes["password"]) }, updated_user, ignore={"updated_at"}, )
async def modify(cls, get_kwargs, update_kwargs): if "password" in update_kwargs: password = update_kwargs["password"] validate_password_strength(password) update_kwargs["password"] = hash_password(password) return await super(BaseUser, cls).modify(get_kwargs, update_kwargs)
async def add(cls, password=None, **kwargs): # Follow guidelines from OWASP # https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html if password: validate_password_strength(password) password = hash_password(password) return await super(BaseUser, cls).add(password=password, **kwargs)
async def setup_db(): "Re-setup the DB" # Create a test org org_data = _orgs[0] org = await Organisation(**org_data).create() # Register the global settings for setting in _settings: try: await Setting(**setting).create() except UniqueViolationError: pass # Register the user roles for user_role in _user_roles: try: await UserRole(**user_role).create() except UniqueViolationError: pass # Register the permissions for key, roles in DEFAULT_PERMISSIONS.items(): for role_id in roles: try: await RolePermission(**{"name": key, "role_id": role_id}).create() except UniqueViolationError: pass # Register all users under the same org for user in _users: _user = deepcopy(user) _user["password"] = hash_password(_user["password"]) await User(**_user, organisation_id=org.id).create() # Register the visitors for visitor in _visitors: _visitor = deepcopy(visitor) # Anonymous users don't have passwords if "password" in _visitor: _visitor["password"] = hash_password(_visitor["password"]) await Visitor(**_visitor).create()
async def test_update_user_as_admin(users, admin1_client): new_changes = { "full_name": "this name surely doesnt exist", "password": "******", } res = await admin1_client.patch("/users/{}".format(users[5]["id"]), json=new_changes) assert res.status == 200 body = await res.json() assert "data" in body assert isinstance(body["data"], dict) updated_user = await get_one(User, internal_id=6) updated_user = updated_user.to_dict() ## Assert the new password has been updated assert profile_created_from_origin( { **body["data"], "password": hash_password(new_changes["password"]) }, updated_user, ) # Admin can update supervisor res = await admin1_client.patch("/users/{}".format(users[-3]["id"]), json=new_changes) assert res.status == 200 body = await res.json() assert "data" in body assert isinstance(body["data"], dict) updated_user = await get_one(User, id=users[-3]["id"]) updated_user = updated_user.to_dict() ## Assert the new password has been updated assert profile_created_from_origin( { **body["data"], "password": hash_password(new_changes["password"]) }, updated_user, )
async def login(cls, email=None, password=None, *, is_anonymous=False, **kwargs): user = None if not is_anonymous: if not email: raise InvalidUsage("Missing field 'email' in request's body.") if not password: raise InvalidUsage( "Missing field 'password' in request's body.") password = hash_password(password) try: user = await cls.get(email=email, password=password, **kwargs) except NotFound: pass if not user: raise LoginFailureError() # Invalidate the staff if he is disabled if "role_id" in user and user["disabled"]: raise Unauthorized( "Your account have been disabled. Please contact your supervisor." ) else: # Anonymous login kwargs["is_anonymous"] = True user = await cls.add(**kwargs) # Only store minimum info for user fields = { "id", "full_name", "display_name", "name", "email", "role_id", "organisation_id", "is_anonymous", "disabled", } for key in list(user.keys()): if key not in fields: user.pop(key, None) return user
async def test_update_last_seen_message_of_staff(supervisor1_client): # Create a lot more visitors to test visitors = [get_fake_visitor() for _ in range(3)] for visitor in visitors: _visitor = deepcopy(visitor) # Anonymous users don't have passwords if "password" in _visitor: _visitor["password"] = hash_password(_visitor["password"]) await Visitor(**_visitor).create() # Create some dummy chat messages created_at = 1 chat_messages = {} for visitor in visitors[::-1]: chat = await Chat.add(visitor_id=visitor["id"]) for sequence_num in range(4): content = {"content": fake.sentence(nb_words=10)} chat_msg = { "chat_id": chat["id"], "sequence_num": sequence_num, "content": content, "sender": None, "created_at": created_at, } created_at += 1 created_msg = await ChatMessage.add(**chat_msg) chat_messages.setdefault(chat["id"], []).append(created_msg) for chat_id, value in chat_messages.items(): chat = await Chat.get(id=chat_id) res = await supervisor1_client.patch( "/visitors/{}/last_seen".format(chat["visitor_id"]), json={"last_seen_msg_id": value[2]["id"]}, ) assert res.status == 200 body = await res.json() assert "data" in body assert isinstance(body["data"], dict) assert body["data"]["last_seen_msg_id"] == value[2]["id"]
async def test_get_visitors_most_recent(users, supervisor1_client): # Create a lot more visitors to test visitors = [get_fake_visitor() for _ in range(32)] for visitor in visitors: _visitor = deepcopy(visitor) # Anonymous users don't have passwords if "password" in _visitor: _visitor["password"] = hash_password(_visitor["password"]) await Visitor(**_visitor).create() # Create some dummy chat messages created_at = 1 staff = users[-5] for visitor in visitors[::-1]: chat = await Chat.add(visitor_id=visitor["id"]) for sequence_num in range(3): content = {"content": fake.sentence(nb_words=10)} chat_msg = { "chat_id": chat["id"], "sequence_num": sequence_num, "content": content, "sender": None, "created_at": created_at, } created_at += 1 await ChatMessage.add(**chat_msg) # Let a staff send a message, as staffs can only fetch visitors # that chatted with the staffs from his org await ChatMessage.add( **{ "chat_id": chat["id"], "sequence_num": sequence_num + 1, "content": { "content": fake.sentence(nb_words=10) }, "sender": staff["id"], "created_at": created_at, }) # Get the most recent visitors that chatted with the staffs from org res = await supervisor1_client.get("/visitors/most_recent") assert res.status == 200 body = await res.json() assert "data" in body assert isinstance(body["data"], list) assert len(body["data"]) == 15 assert "links" in body and "next" in body["links"] for expected, actual in zip(visitors, body["data"]): assert profile_created_from_origin(expected, actual) # Ensure that the next links work as well next_page_link = get_next_page_link(body) res = await supervisor1_client.get(next_page_link) assert res.status == 200 body = await res.json() assert "data" in body assert isinstance(body["data"], list) assert len(body["data"]) == 15 assert "links" in body and "next" in body["links"] for expected, actual in zip(visitors[15:], body["data"]): assert profile_created_from_origin(expected, actual) # Last page next_page_link = get_next_page_link(body) res = await supervisor1_client.get(next_page_link) assert res.status == 200 assert res.status == 200 body = await res.json() assert "data" in body assert isinstance(body["data"], list) assert len(body["data"]) == 2 assert "links" in body and "next" in body["links"] for expected, actual in zip(visitors[30:], body["data"]): assert profile_created_from_origin(expected, actual)