async def test_positive_register_w_email_and_name(test_cli): global username username = None while username is None: i = random.randint(1, 10000) username = f"amichay.oren+{i}@gmail.com" if User.username_exists(username): username = None data = { "username": username, "password": "******", "email": username, "name": "Amichay Oren", } resp = await test_cli.post("/users", data=json.dumps(data)) assert resp.status == 201 data = {"username": username, "password": "******"} resp = await test_cli.post("/auth", data=json.dumps(data)) resp_json = await resp.json() print(resp_json) global access_token access_token = resp_json["access_token"] global refresh_token refresh_token = resp_json["refresh_token"] assert access_token is not None assert refresh_token is not None assert resp.status == 200
def test_cli(loop, app, sanic_client): global username while username is None: i = random.randint(1, 10000) username = f"amichay.oren+{i}@gmail.com" if User.username_exists(username): username = None return loop.run_until_complete(sanic_client(app))
def retrieve_user(request, *args, **kwargs): if "user_id" in kwargs: user_id = kwargs.get("user_id") else: if "payload" in kwargs: payload = kwargs.get("payload") else: payload = request.app.auth.extract_payload(request) user_id = payload.get("user_id") return User.get_by_user_id(user_id)
async def test_positive_register_w_email(test_cli): global username username = None while username is None: i = random.randint(1, 10000) username = f"amichay.oren+{i}@gmail.com" if User.username_exists(username): username = None data = {"username": username, "password": "******", "email": username} resp = await test_cli.post("/users", data=json.dumps(data)) assert resp.status == 201
async def delete_user(request, *args, **kwargs): try: requested_user_id = int(request.path.split("/")[2]) except ValueError as e: raise InvalidUsage(e) user_from_token = retrieve_user(request, args, kwargs) if user_from_token is None: raise InvalidUsage("invalid parameter (maybe expired?)") user = User.get_by_user_id(requested_user_id) if user is None: raise InvalidUsage("invalid user") if ( "admin" not in user_from_token.scopes and "manager" not in user_from_token.scopes ): if requested_user_id != user_from_token.user_id: raise Forbidden(f"user can only update self") user = User.get_by_user_id(requested_user_id) if not user: raise InvalidUsage("invalid parameter") if ( "manager" in user_from_token.scopes and "admin" not in user_from_token.scopes and ("manager" in user.scopes or "admin" in user.scopes) ): if requested_user_id != user_from_token.user_id: raise Forbidden(f"manager can only update manager") user.expire(user_from_token.user_id) return response.HTTPResponse(status=204)
async def register(request, *args, **kwargs): if ( request.json is None or "username" not in request.json or "password" not in request.json ): raise InvalidUsage("invalid payload (should be {username, password})") password = request.json["password"] if not password_validator(password): raise InvalidUsage("password does not match minimum requirements") username = request.json["username"] if User.username_exists(username): raise Conflict(f"username {username} already exists") email = request.json["email"] if "email" in request.json else None name = request.json["name"] if "name" in request.json else None user = User( None, username, encrypt(request.json["password"]), ["user"], email, name ) user.save() return response.HTTPResponse(status=201)
async def test_positive_get_users_by_manager(test_cli): # check who i am global access_token headers = {"Authorization": f"Bearer {access_token}"} resp = await test_cli.get("/auth/me", headers=headers) resp_json = await resp.json() print(resp_json) assert resp.status == 200 my_user_id = resp_json["me"]["user_id"] # promote to manager data = {"scopes": ["user", "manager"]} headers = {"Authorization": f"Bearer {access_token}"} resp = await test_cli.patch(f"/users/{my_user_id}/scopes", headers=headers, data=json.dumps(data)) assert resp.status == 204 # re-login to get access token w/ new scope data = {"username": username, "password": "******"} resp = await test_cli.post("/auth", data=json.dumps(data)) resp_json = await resp.json() print(resp_json) access_token = resp_json["access_token"] refresh_token = resp_json["refresh_token"] assert access_token is not None assert refresh_token is not None assert resp.status == 200 # get users headers = {"Authorization": f"Bearer {access_token}"} resp = await test_cli.get("/users", headers=headers) resp_json = await resp.json() print(resp_json) for row in resp_json: user = User( user_id=row["user_id"], username=row["username"], hashed_password=row["hashed_password"], scopes=row["scopes"], email=row["email"], name=row["name"], ) assert False == ("manager" in user.scopes or "admin" in user.scopes) assert resp.status == 200
async def update_user(request, *args, **kwargs): if request.json is None: raise InvalidUsage("invalid payload (empty payload not allowed)") try: requested_user_id = int(request.path.split("/")[2]) except ValueError as e: raise InvalidUsage(e) user_from_token = retrieve_user(request, args, kwargs) if user_from_token is None: raise InvalidUsage("invalid parameter (maybe expired?)") if ( "admin" not in user_from_token.scopes and "manager" not in user_from_token.scopes ): if requested_user_id != user_from_token.user_id: raise Forbidden(f"user can only update self") user = User.get_by_user_id(requested_user_id) if not user: raise InvalidUsage("invalid parameter") if ( "manager" in user_from_token.scopes and "admin" not in user_from_token.scopes and ("manager" in user.scopes or "admin" in user.scopes) ): if requested_user_id != user_from_token.user_id: raise Forbidden(f"manager can only update manager") if "password" in request.json: password = request.json["password"] if not password_validator(password): raise InvalidUsage("password does not match minimum requirements") user.update_password(encrypt(password)) if "email" in request.json: user.update_email(request.json["email"]) if "name" in request.json: user.update_name(request.json["name"]) user.save(modifying_user_id=user_from_token.user_id) return response.HTTPResponse(status=204)
async def authenticate(request, *args, **kwargs): if request.json is None: raise exceptions.AuthenticationFailed("missing payload") username = request.json.get("username", None) password = request.json.get("password", None) if not username or not password: raise exceptions.AuthenticationFailed("Missing username or password.") user = User.get_by_username(username) if user is None: raise exceptions.AuthenticationFailed("User not found.") if not bcrypt.checkpw(password.encode("utf-8"), user.hashed_password.encode("utf-8")): raise exceptions.AuthenticationFailed("Password is incorrect.") return user
async def get_users(request, *args, **kwargs): page = int(request.args["page"][0]) if "page" in request.args else 0 limit = int(request.args["count"][0]) if "count" in request.args else 10 if page < 0 or limit <= 0: raise InvalidUsage("invalid paging (page >= 0 and count > 0)") user_from_token = retrieve_user(request, args, kwargs) if user_from_token is None: raise InvalidUsage("invalid parameter (maybe expired?)") user_id = user_from_token.user_id user = User.get_by_user_id(user_id) try: rc = user.get_users(page, limit) except Exception as e: raise InvalidUsage(e) return response.json(rc, status=200)
async def update_user_scope(request, *args, **kwargs): if request.json is None: raise InvalidUsage("invalid payload (empty payload not allowed)") try: requested_user_id = int(request.path.split("/")[2]) except ValueError as e: raise InvalidUsage(e) user_from_token = retrieve_user(request, args, kwargs) if user_from_token is None: raise InvalidUsage("invalid parameter (maybe expired?)") user = User.get_by_user_id(requested_user_id) if user is None: raise InvalidUsage("invalid user") if "scopes" in request.json: print(request.json) user.update_scopes(request.json["scopes"]) user.save(modifying_user_id=user_from_token.user_id) return response.HTTPResponse(status=204)
async def test_positive_admin_update_user(test_cli): global access_token # check who i am headers = {"Authorization": f"Bearer {access_token}"} resp = await test_cli.get("/auth/me", headers=headers) resp_json = await resp.json() print(resp_json) assert resp.status == 200 # update me my_user_id = resp_json["me"]["user_id"] data = {"scopes": ["user", "manager", "admin"]} headers = {"Authorization": f"Bearer {access_token}"} resp = await test_cli.patch(f"/users/{my_user_id}/scopes", headers=headers, data=json.dumps(data)) assert resp.status == 204 manager_access_token = access_token # register second global username username = None while username is None: i = random.randint(1, 10000) username = f"amichay.oren+{i}" if User.username_exists(username): username = None data = { "username": username, "password": "******", "name": "Amichay Oren", "email": f"{username}@gmail.com", } resp = await test_cli.post("/users", data=json.dumps(data)) assert resp.status == 201 # login second data = {"username": username, "password": "******"} resp = await test_cli.post("/auth", data=json.dumps(data)) resp_json = await resp.json() print(resp_json) access_token = resp_json["access_token"] refresh_token = resp_json["refresh_token"] assert access_token is not None assert refresh_token is not None assert resp.status == 200 # check who is second headers = {"Authorization": f"Bearer {access_token}"} resp = await test_cli.get("/auth/me", headers=headers) resp_json = await resp.json() print(resp_json) assert resp.status == 200 new_manager_user_id = resp_json["me"]["user_id"] # first admin update second user new_name = "some new name" data = {"name": new_name} headers = {"Authorization": f"Bearer {manager_access_token}"} resp = await test_cli.patch(f"/users/{new_manager_user_id}", headers=headers, data=json.dumps(data)) assert resp.status == 204