async def test_request_email_confirmation_confirmed(): auth_service = AuthService() auth_service._user = User(2, "user", False) with pytest.raises(HTTPException) as e: await auth_service.request_email_confirmation() assert e.type is HTTPException assert e.value.args[0] == 400
async def test_get_email_confirmation_status(user: User, email: str, confirmed: bool): auth_service = AuthService() auth_service._user = user status = await auth_service.get_email_confirmation_status() assert status.get("email") == email assert status.get("confirmed") == confirmed auth_service._user = user status = await auth_service.get_email_confirmation_status() assert status.get("email") == email assert status.get("confirmed") is confirmed
def auth_service_setup(): AuthService.setup( UsersRepo(MockDatabaseBackend("test"), MockCacheBackend(), []), auth_backend, False, "RU", "http://127.0.0.1", "127.0.0.1", RECAPTCHA_SECRET, None, None, None, None, None, )
async def register(*, request: Request, response: Response): data = await request.json() service = AuthService() tokens = await service.register(data) set_tokens_in_response(response, tokens) return None
async def test_login(login: str, password: str): auth_service = AuthService() tokens = await auth_service.login({ "login": login, "password": password }, "127.0.0.1") # TODO assert isinstance(tokens, dict)
async def login(*, request: Request, response: Response): data = await request.json() service = AuthService() ip = request.client.host tokens = await service.login(data, ip) set_tokens_in_response(response, tokens) return None
async def test_refresh_access_token() -> str: auth_service = AuthService() refresh_token = auth_backend.create_refresh_token({ "id": 1, "username": "******", "permissions": [], "type": "refresh", }) access_token = await auth_service.refresh_access_token(refresh_token) assert isinstance(access_token, str)
async def change_username( *, id: int, username: str = Body("", embed=True), user: User = Depends(get_authenticated_user), ): service = AuthService(user) if user.id == id or user.is_admin: return await service.change_username(id, username) else: raise HTTPException(403)
async def refresh_access_token( *, request: Request, response: Response, ): service = AuthService() refresh_token = request.cookies.get(refresh_cookie_name) if refresh_token is None: raise HTTPException(401) access_token = await service.refresh_access_token(refresh_token) set_access_token_in_response(response, access_token) return {"access": access_token}
async def test_confirm_email(): auth_service = AuthService() email = "*****@*****.**" token = create_random_string() token_hash = hash_string(token) await auth_service._repo.request_email_confirmation(email, token_hash) with pytest.raises(HTTPException) as e: await auth_service.confirm_email("wrongtoken") assert e.type is HTTPException assert e.value.args[0] == 403 # TODO: 400 maybe await auth_service.confirm_email(token) item = await auth_service._repo.get_by_email(email) assert item.get("confirmed")
async def test_change_username(): auth_service = AuthService(User(1, "admin", True)) await auth_service.change_username(2, "newusername") # admin assert await auth_service._repo.get_by_username("newusername") is not None assert await auth_service._repo.get_by_username("username") is None with pytest.raises(HTTPException) as e: await auth_service.change_username(2, "admin") # exists assert e.type is HTTPException assert e.value.args[0] == 400 with pytest.raises(HTTPException) as e: await auth_service.change_username(1, "admin") # same assert e.type is HTTPException assert e.value.args[0] == 400 await auth_service.change_username(1, "newadmin") # own assert await auth_service._repo.get_by_username("newadmin") is not None assert await auth_service._repo.get_by_username("admin") is None
async def test_register( email: str, username: str, password1: str, password2: str, valid_data: bool, captcha: str, valid_captcha: bool, ): auth_service = AuthService() with mock.patch( "fastapi_auth.services.auth.validate_captcha", mock.AsyncMock(return_value=valid_captcha), ) as mock_validate_captcha: if not valid_captcha: with pytest.raises(HTTPException) as e: await auth_service.register({ "email": email, "username": username, "password1": password1, "password2": password2, "captcha": captcha, }) assert e.type is HTTPException assert e.value.args[0] == 400 else: res = await auth_service.register({ "email": email, "username": username, "password1": password1, "password2": password2, "captcha": captcha, }) assert isinstance(res, dict) assert isinstance(res.get("access"), str) assert isinstance(res.get("refresh"), str) mock_validate_captcha.assert_awaited_once_with(captcha, RECAPTCHA_SECRET)
async def test_request_email_confirmation(): auth_service = AuthService() auth_service._user = User(3, "anotheruser", False) res = await auth_service.request_email_confirmation() assert res is None
def get_router( repo: UsersRepo, auth_backend: JWTBackend, get_authenticated_user: Callable, debug: bool, language: str, base_url: str, site: str, access_cookie_name: str, refresh_cookie_name: str, access_expiration: int, refresh_expiration: int, recaptcha_secret: str, smtp_username: str, smtp_password: str, smtp_host: str, smtp_tls: int, display_name: str, ) -> APIRouter: AuthService.setup( repo, auth_backend, debug, language, base_url, site, recaptcha_secret, smtp_username, smtp_password, smtp_host, smtp_tls, display_name, ) def set_access_token_in_response(response, token: str) -> None: response.set_cookie( key=access_cookie_name, value=token, secure=not debug, httponly=True, max_age=access_expiration, ) def set_refresh_token_in_response(response, token: str) -> None: response.set_cookie( key=refresh_cookie_name, value=token, secure=not debug, httponly=True, max_age=refresh_expiration, ) def set_tokens_in_response(response, tokens: Dict[str, str]) -> None: access_token = tokens.get("access") refresh_token = tokens.get("refresh") set_access_token_in_response(response, access_token) set_refresh_token_in_response(response, refresh_token) router = APIRouter() @router.post("/register", name="auth:register") async def register(*, request: Request, response: Response): data = await request.json() service = AuthService() tokens = await service.register(data) set_tokens_in_response(response, tokens) return None @router.post("/login", name="auth:login") async def login(*, request: Request, response: Response): data = await request.json() service = AuthService() ip = request.client.host tokens = await service.login(data, ip) set_tokens_in_response(response, tokens) return None @router.post("/logout", name="auth:logout") async def logout(*, response: Response): response.delete_cookie(access_cookie_name) response.delete_cookie(refresh_cookie_name) return None @router.post("/token", name="auth:token") async def token(*, user: User = Depends(get_authenticated_user)): return user.data @router.post("/token/refresh", name="auth:refresh_access_token") async def refresh_access_token( *, request: Request, response: Response, ): service = AuthService() refresh_token = request.cookies.get(refresh_cookie_name) if refresh_token is None: raise HTTPException(401) access_token = await service.refresh_access_token(refresh_token) set_access_token_in_response(response, access_token) return {"access": access_token} @router.get("/confirm", name="auth:get_email_confirmation_status") async def get_email_confirmation_status( *, user: User = Depends(get_authenticated_user)): service = AuthService(user) return await service.get_email_confirmation_status() @router.post("/confirm", name="auth:request_email_confirmation") async def request_email_confirmation( *, user: User = Depends(get_authenticated_user)): service = AuthService(user) return await service.request_email_confirmation() @router.post("/confirm/{token}", name="auth:confirm_email") async def confirm_email(*, token: str): service = AuthService() return await service.confirm_email(token) @router.post("/{id}/change_username", name="auth:change_username") async def change_username( *, id: int, username: str = Body("", embed=True), user: User = Depends(get_authenticated_user), ): service = AuthService(user) if user.id == id or user.is_admin: return await service.change_username(id, username) else: raise HTTPException(403) return router
async def confirm_email(*, token: str): service = AuthService() return await service.confirm_email(token)
async def request_email_confirmation( *, user: User = Depends(get_authenticated_user)): service = AuthService(user) return await service.request_email_confirmation()
async def get_email_confirmation_status( *, user: User = Depends(get_authenticated_user)): service = AuthService(user) return await service.get_email_confirmation_status()