test: cover auth and SMS flows
This commit is contained in:
75
tests/test_grpc_auth.py
Normal file
75
tests/test_grpc_auth.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import grpc
|
||||
import pytest
|
||||
|
||||
from gapido_auth.application import auth_service as auth_module
|
||||
from gapido_auth.application.auth_service import AuthConfig, AuthService
|
||||
from gapido_auth.application.security import JwtTokenCodec
|
||||
from gapido_auth.generated import auth_pb2, auth_pb2_grpc
|
||||
from gapido_auth.transport.grpc.auth_servicer import AuthGrpcServicer
|
||||
from tests.fakes import (
|
||||
FakeOtpStore,
|
||||
FakeRefreshSessionRepository,
|
||||
FakeSmsPublisher,
|
||||
FakeUserRepository,
|
||||
)
|
||||
|
||||
|
||||
def build_grpc_service() -> AuthService:
|
||||
return AuthService(
|
||||
users=FakeUserRepository(),
|
||||
refresh_sessions=FakeRefreshSessionRepository(),
|
||||
otp_store=FakeOtpStore(),
|
||||
sms_publisher=FakeSmsPublisher(),
|
||||
token_codec=JwtTokenCodec("unit-test-secret-key", "tests", 60),
|
||||
config=AuthConfig(
|
||||
otp_secret="unit-test-secret-key",
|
||||
otp_ttl_seconds=120,
|
||||
otp_max_attempts=5,
|
||||
otp_request_limit=3,
|
||||
otp_request_window_seconds=300,
|
||||
refresh_token_ttl_seconds=3600,
|
||||
sms_template="login-otp",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_grpc_public_and_protected_methods(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setattr(auth_module, "generate_otp_code", lambda: "123456")
|
||||
server = grpc.aio.server()
|
||||
auth_pb2_grpc.add_AuthServiceServicer_to_server(
|
||||
AuthGrpcServicer(build_grpc_service()), server
|
||||
)
|
||||
port = server.add_insecure_port("127.0.0.1:0")
|
||||
await server.start()
|
||||
|
||||
try:
|
||||
channel = grpc.aio.insecure_channel(f"127.0.0.1:{port}")
|
||||
stub = auth_pb2_grpc.AuthServiceStub(channel)
|
||||
|
||||
public = await stub.PublicPing(auth_pb2.PingRequest())
|
||||
assert public.message == "public ok"
|
||||
|
||||
with pytest.raises(grpc.aio.AioRpcError) as missing_auth:
|
||||
await stub.UserOnly(auth_pb2.ProtectedRequest())
|
||||
assert missing_auth.value.code() == grpc.StatusCode.UNAUTHENTICATED
|
||||
|
||||
await stub.RequestOtp(auth_pb2.RequestOtpRequest(mobile="989120000000", purpose="login"))
|
||||
tokens = await stub.VerifyOtp(
|
||||
auth_pb2.VerifyOtpRequest(mobile="989120000000", code="123456", purpose="login")
|
||||
)
|
||||
user_response = await stub.UserOnly(
|
||||
auth_pb2.ProtectedRequest(),
|
||||
metadata=(("authorization", f"Bearer {tokens.access_token}"),),
|
||||
)
|
||||
assert user_response.role == "user"
|
||||
|
||||
with pytest.raises(grpc.aio.AioRpcError) as admin_denied:
|
||||
await stub.AdminOnly(
|
||||
auth_pb2.ProtectedRequest(),
|
||||
metadata=(("authorization", f"Bearer {tokens.access_token}"),),
|
||||
)
|
||||
assert admin_denied.value.code() == grpc.StatusCode.PERMISSION_DENIED
|
||||
finally:
|
||||
await server.stop(grace=0)
|
||||
|
||||
Reference in New Issue
Block a user