mirror of
https://github.com/hexolan/panels.git
synced 2026-03-26 12:40:21 +00:00
185 lines
5.9 KiB
Python
185 lines
5.9 KiB
Python
import logging
|
|
import traceback
|
|
from typing import Type
|
|
|
|
from google.protobuf import empty_pb2
|
|
from grpc import RpcContext, StatusCode
|
|
|
|
from auth_service.models.exceptions import ServiceException
|
|
from auth_service.models.service import AuthRepository, AuthToken
|
|
from auth_service.models.proto import auth_pb2, auth_pb2_grpc
|
|
|
|
|
|
class AuthServicer(auth_pb2_grpc.AuthServiceServicer):
|
|
"""Contains definitions for the service's RPC methods.
|
|
|
|
The request attributes are validated and translated
|
|
from protobufs into business model form, then passed
|
|
along to the service repository to handling the
|
|
business logic.
|
|
|
|
Responses from calls to methods in the service repository
|
|
are then translated back to protobuf form to return
|
|
to the user.
|
|
|
|
Attributes:
|
|
_svc_repo (Type[AuthRepository]): The highest level service repository.
|
|
|
|
"""
|
|
def __init__(self, svc_repo: Type[AuthRepository]) -> None:
|
|
self._svc_repo = svc_repo
|
|
|
|
def _apply_error(self, context: RpcContext, code: StatusCode, msg: str) -> None:
|
|
"""Set an error on a given RPC request.
|
|
|
|
Args:
|
|
context (grpc.RpcContext): The context to apply the error to.
|
|
code (grpc.StatusCode): The gRPC status code.
|
|
msg (str): The error details.
|
|
|
|
"""
|
|
context.set_code(code)
|
|
context.set_details(msg)
|
|
|
|
def _apply_unknown_error(self, context: RpcContext) -> None:
|
|
"""Apply a de facto error fallback message.
|
|
|
|
Args:
|
|
context (grpc.RpcContext): The context to apply the error to.
|
|
|
|
"""
|
|
self._apply_error(context, StatusCode.UNKNOWN, "unknown error occured")
|
|
|
|
async def AuthWithPassword(self, request: auth_pb2.PasswordAuthRequest, context: RpcContext) -> auth_pb2.AuthToken:
|
|
"""AuthWithPassword RPC Call
|
|
|
|
Args:
|
|
request (auth_pb2.PasswordAuthRequest): The request parameters.
|
|
context (grpc.RpcContext): The context of the RPC call.
|
|
|
|
Returns:
|
|
auth_pb2.AuthToken: With a succesfully authentication.
|
|
|
|
"""
|
|
# validate the request inputs
|
|
if request.user_id == "":
|
|
self._apply_error(
|
|
context,
|
|
code=StatusCode.INVALID_ARGUMENT,
|
|
msg="user not provided"
|
|
)
|
|
return
|
|
|
|
if request.password == "":
|
|
self._apply_error(
|
|
context,
|
|
code=StatusCode.INVALID_ARGUMENT,
|
|
msg="password not provided"
|
|
)
|
|
return
|
|
|
|
if len(request.password) < 8:
|
|
self._apply_error(
|
|
context,
|
|
code=StatusCode.INVALID_ARGUMENT,
|
|
msg="invalid password"
|
|
)
|
|
return
|
|
|
|
# Attempt to authenticate the user
|
|
try:
|
|
token = await self._svc_repo.auth_with_password(request.user_id, request.password)
|
|
except ServiceException as err:
|
|
err.apply_to_rpc(context)
|
|
return
|
|
except Exception:
|
|
logging.error(traceback.format_exc())
|
|
self._apply_unknown_error(context)
|
|
return
|
|
|
|
# Convert token to protobuf
|
|
return AuthToken.to_protobuf(token)
|
|
|
|
async def SetPasswordAuth(self, request: auth_pb2.SetPasswordAuthMethod, context: RpcContext) -> empty_pb2.Empty:
|
|
"""SetPasswordAuth RPC Call
|
|
|
|
Args:
|
|
request (auth_pb2.SetPasswordAuthMethod): The request parameters.
|
|
context (grpc.RpcContext): The context of the RPC call.
|
|
|
|
Returns:
|
|
empty_pb2.Empty: Empty protobuf response (in effect returns None).
|
|
|
|
"""
|
|
# validate the request inputs
|
|
if request.user_id == "":
|
|
self._apply_error(
|
|
context,
|
|
code=StatusCode.INVALID_ARGUMENT,
|
|
msg="user id not provided"
|
|
)
|
|
return
|
|
|
|
if request.password == "":
|
|
self._apply_error(
|
|
context,
|
|
code=StatusCode.INVALID_ARGUMENT,
|
|
msg="password not provided"
|
|
)
|
|
return
|
|
|
|
if len(request.password) < 8:
|
|
self._apply_error(
|
|
context,
|
|
code=StatusCode.INVALID_ARGUMENT,
|
|
msg="password must be at least 8 characters"
|
|
)
|
|
return
|
|
|
|
# Attempt to create the auth method
|
|
try:
|
|
await self._svc_repo.set_password_auth_method(request.user_id, request.password)
|
|
except ServiceException as err:
|
|
err.apply_to_rpc(context)
|
|
return
|
|
except Exception:
|
|
logging.error(traceback.format_exc())
|
|
self._apply_unknown_error(context)
|
|
return
|
|
|
|
# Success
|
|
return empty_pb2.Empty()
|
|
|
|
async def DeletePasswordAuth(self, request: auth_pb2.DeletePasswordAuthMethod, context: RpcContext) -> empty_pb2.Empty:
|
|
"""DeletePasswordAuth RPC Call
|
|
|
|
Args:
|
|
request (auth_pb2.DeletePasswordAuthMethod): The request parameters.
|
|
context (grpc.RpcContext): The context of the RPC call.
|
|
|
|
Returns:
|
|
empty_pb2.Empty: Empty protobuf response (in effect returns None).
|
|
|
|
"""
|
|
# Ensure a user id is provided
|
|
if request.user_id == "":
|
|
self._apply_error(
|
|
context,
|
|
code=StatusCode.INVALID_ARGUMENT,
|
|
msg="user id not provided"
|
|
)
|
|
return
|
|
|
|
# Attempt to delete the auth method
|
|
try:
|
|
await self._svc_repo.delete_password_auth_method(request.user_id, request.password)
|
|
except ServiceException as err:
|
|
err.apply_to_rpc(context)
|
|
return
|
|
except Exception:
|
|
logging.error(traceback.format_exc())
|
|
self._apply_unknown_error(context)
|
|
return
|
|
|
|
# Success
|
|
return empty_pb2.Empty() |