init auth-service

This commit is contained in:
2023-09-27 16:01:41 +01:00
parent 7192f11059
commit 0ae3ee3af4
40 changed files with 2616 additions and 2 deletions

View File

@@ -0,0 +1,75 @@
import base64
from typing import Any, List
from pydantic import computed_field
from pydantic.fields import FieldInfo
from pydantic_settings import BaseSettings, EnvSettingsSource
from pydantic_settings.main import BaseSettings
from pydantic_settings.sources import PydanticBaseSettingsSource
class ConfigSource(EnvSettingsSource):
"""Responsible for loading config options from environment variables."""
def prepare_field_value(self, field_name: str, field: FieldInfo, value: Any, value_is_complex: bool) -> Any:
if field_name == "kafka_brokers":
# Comma delimit the kafka brokers.
if value == None:
return None
return value.split(",")
elif field_name == "jwt_public_key" or field_name == "jwt_private_key":
# Decode the JWT public and private keys from base64.
if value == None:
return None
return base64.standard_b64decode(value).decode(encoding="utf-8")
return super().prepare_field_value(field_name, field, value, value_is_complex)
class Config(BaseSettings):
"""The service configuration loaded from environment
variables.
Attributes:
postgres_user (str): Loaded from the 'POSTGRES_USER' envvar.
postgres_pass (str): Loaded from the 'POSTGRES_PASS' envvar.
postgres_host (str): Loaded from the 'POSTGRES_HOST' envvar.
postgres_database (str): Loaded from the 'POSTGRES_DATABASE' envvar.
kafka_brokers (list[str]): Loaded and comma delmited from the 'KAFKA_BROKERS' envvar.
jwt_public_key (str): Loaded and decoded, from base64, from the 'JWT_PUBLIC_KEY' envvar.
jwt_private_key (str): Loaded and decoded, from base64, from the 'JWT_PRIVATE_KEY' envvar.
password_pepper (str): Loaded from the 'PASSWORD_PEPPER' envvar.
postgres_dsn (str): Computed when accessed the first time. (@property)
"""
postgres_user: str
postgres_pass: str
postgres_host: str
postgres_database: str
kafka_brokers: List[str]
jwt_public_key: str
jwt_private_key: str
password_pepper: str
@computed_field
@property
def postgres_dsn(self) -> str:
"""Uses the postgres_user, postgres_pass, postgres_host,
and postgres_database options to assemble a DSN.
Returns:
str: DSN for connecting to the database.
"""
return "postgresql+asyncpg://{user}:{password}@{host}/{db}".format(
user=self.postgres_user,
password=self.postgres_pass,
host=self.postgres_host,
db=self.postgres_database
)
@classmethod
def settings_customise_sources(cls, settings_cls: type[BaseSettings], *args, **kwargs) -> tuple[PydanticBaseSettingsSource, ...]:
return (ConfigSource(settings_cls), )

View File

@@ -0,0 +1,59 @@
from enum import Enum, auto
from grpc import RpcContext, StatusCode
class ServiceErrorCode(Enum):
"""Error codes used for classifying ServiceExceptions."""
INVALID_ARGUMENT = auto()
CONFLICT = auto()
NOT_FOUND = auto()
INVALID_CREDENTIALS = auto()
SERVICE_ERROR = auto()
__RPC_CODE_MAP__ = {
INVALID_ARGUMENT: StatusCode.INVALID_ARGUMENT,
CONFLICT: StatusCode.ALREADY_EXISTS,
NOT_FOUND: StatusCode.NOT_FOUND,
INVALID_CREDENTIALS: StatusCode.UNAUTHENTICATED,
SERVICE_ERROR: StatusCode.INTERNAL
}
def to_rpc_code(self) -> StatusCode:
"""Convert a service error code to a gRPC status code.
Returns:
The mapped RPC status code, if found, otherwise gRPC Unknown status code.
"""
return self.__class__.__RPC_CODE_MAP__.get(self.value, StatusCode.UNKNOWN)
class ServiceException(Exception):
"""This exception provides an interface to convert service errors
into gRPC errors, which can then be returned to the caller.
Args:
msg (str): Error message.
error_code (ServiceErrorCode): Categorisation code for the error.
Attributes:
msg (str): The error message.
error_code (ServiceErrorCode): Categorisation code for the error.
"""
def __init__(self, msg: str, error_code: ServiceErrorCode) -> None:
super().__init__(msg)
self.msg = msg
self.error_code = error_code
def apply_to_rpc(self, context: RpcContext) -> None:
"""Apply the exception to an RPC context.
Args:
context (grpc.RpcContext): The context to apply to.
"""
context.set_code(self.error_code.to_rpc_code())
context.set_details(self.msg)

View File

@@ -0,0 +1,23 @@
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nauth.proto\x12\x0epanels.auth.v1\x1a\x1bgoogle/protobuf/empty.proto":\n\x15SetPasswordAuthMethod\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t"+\n\x18DeletePasswordAuthMethod\x12\x0f\n\x07user_id\x18\x01 \x01(\t"8\n\x13PasswordAuthRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t"`\n\tAuthToken\x12\x12\n\ntoken_type\x18\x01 \x01(\t\x12\x14\n\x0caccess_token\x18\x02 \x01(\t\x12\x15\n\rrefresh_token\x18\x03 \x01(\t\x12\x12\n\nexpires_in\x18\x04 \x01(\x032\x91\x02\n\x0bAuthService\x12T\n\x10AuthWithPassword\x12#.panels.auth.v1.PasswordAuthRequest\x1a\x19.panels.auth.v1.AuthToken"\x00\x12R\n\x0fSetPasswordAuth\x12%.panels.auth.v1.SetPasswordAuthMethod\x1a\x16.google.protobuf.Empty"\x00\x12X\n\x12DeletePasswordAuth\x12(.panels.auth.v1.DeletePasswordAuthMethod\x1a\x16.google.protobuf.Empty"\x00b\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'auth_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_globals['_SETPASSWORDAUTHMETHOD']._serialized_start = 59
_globals['_SETPASSWORDAUTHMETHOD']._serialized_end = 117
_globals['_DELETEPASSWORDAUTHMETHOD']._serialized_start = 119
_globals['_DELETEPASSWORDAUTHMETHOD']._serialized_end = 162
_globals['_PASSWORDAUTHREQUEST']._serialized_start = 164
_globals['_PASSWORDAUTHREQUEST']._serialized_end = 220
_globals['_AUTHTOKEN']._serialized_start = 222
_globals['_AUTHTOKEN']._serialized_end = 318
_globals['_AUTHSERVICE']._serialized_start = 321
_globals['_AUTHSERVICE']._serialized_end = 594

View File

@@ -0,0 +1,47 @@
from google.protobuf import empty_pb2 as _empty_pb2
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import ClassVar as _ClassVar, Optional as _Optional
DESCRIPTOR: _descriptor.FileDescriptor
class SetPasswordAuthMethod(_message.Message):
__slots__ = ['user_id', 'password']
USER_ID_FIELD_NUMBER: _ClassVar[int]
PASSWORD_FIELD_NUMBER: _ClassVar[int]
user_id: str
password: str
def __init__(self, user_id: _Optional[str]=..., password: _Optional[str]=...) -> None:
...
class DeletePasswordAuthMethod(_message.Message):
__slots__ = ['user_id']
USER_ID_FIELD_NUMBER: _ClassVar[int]
user_id: str
def __init__(self, user_id: _Optional[str]=...) -> None:
...
class PasswordAuthRequest(_message.Message):
__slots__ = ['user_id', 'password']
USER_ID_FIELD_NUMBER: _ClassVar[int]
PASSWORD_FIELD_NUMBER: _ClassVar[int]
user_id: str
password: str
def __init__(self, user_id: _Optional[str]=..., password: _Optional[str]=...) -> None:
...
class AuthToken(_message.Message):
__slots__ = ['token_type', 'access_token', 'refresh_token', 'expires_in']
TOKEN_TYPE_FIELD_NUMBER: _ClassVar[int]
ACCESS_TOKEN_FIELD_NUMBER: _ClassVar[int]
REFRESH_TOKEN_FIELD_NUMBER: _ClassVar[int]
EXPIRES_IN_FIELD_NUMBER: _ClassVar[int]
token_type: str
access_token: str
refresh_token: str
expires_in: int
def __init__(self, token_type: _Optional[str]=..., access_token: _Optional[str]=..., refresh_token: _Optional[str]=..., expires_in: _Optional[int]=...) -> None:
...

View File

@@ -0,0 +1,58 @@
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
from . import auth_pb2 as auth__pb2
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
class AuthServiceStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.AuthWithPassword = channel.unary_unary('/panels.auth.v1.AuthService/AuthWithPassword', request_serializer=auth__pb2.PasswordAuthRequest.SerializeToString, response_deserializer=auth__pb2.AuthToken.FromString)
self.SetPasswordAuth = channel.unary_unary('/panels.auth.v1.AuthService/SetPasswordAuth', request_serializer=auth__pb2.SetPasswordAuthMethod.SerializeToString, response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString)
self.DeletePasswordAuth = channel.unary_unary('/panels.auth.v1.AuthService/DeletePasswordAuth', request_serializer=auth__pb2.DeletePasswordAuthMethod.SerializeToString, response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString)
class AuthServiceServicer(object):
"""Missing associated documentation comment in .proto file."""
def AuthWithPassword(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetPasswordAuth(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def DeletePasswordAuth(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_AuthServiceServicer_to_server(servicer, server):
rpc_method_handlers = {'AuthWithPassword': grpc.unary_unary_rpc_method_handler(servicer.AuthWithPassword, request_deserializer=auth__pb2.PasswordAuthRequest.FromString, response_serializer=auth__pb2.AuthToken.SerializeToString), 'SetPasswordAuth': grpc.unary_unary_rpc_method_handler(servicer.SetPasswordAuth, request_deserializer=auth__pb2.SetPasswordAuthMethod.FromString, response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString), 'DeletePasswordAuth': grpc.unary_unary_rpc_method_handler(servicer.DeletePasswordAuth, request_deserializer=auth__pb2.DeletePasswordAuthMethod.FromString, response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString)}
generic_handler = grpc.method_handlers_generic_handler('panels.auth.v1.AuthService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
class AuthService(object):
"""Missing associated documentation comment in .proto file."""
@staticmethod
def AuthWithPassword(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.auth.v1.AuthService/AuthWithPassword', auth__pb2.PasswordAuthRequest.SerializeToString, auth__pb2.AuthToken.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def SetPasswordAuth(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.auth.v1.AuthService/SetPasswordAuth', auth__pb2.SetPasswordAuthMethod.SerializeToString, google_dot_protobuf_dot_empty__pb2.Empty.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def DeletePasswordAuth(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.auth.v1.AuthService/DeletePasswordAuth', auth__pb2.DeletePasswordAuthMethod.SerializeToString, google_dot_protobuf_dot_empty__pb2.Empty.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

View File

@@ -0,0 +1,36 @@
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nuser.proto\x12\x0epanels.user.v1\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\x96\x01\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08username\x18\x02 \x01(\t\x12\x10\n\x08is_admin\x18\x03 \x01(\x08\x12.\n\ncreated_at\x18\x04 \x01(\x0b2\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x05 \x01(\x0b2\x1a.google.protobuf.Timestamp"1\n\x0bUserMutable\x12\x15\n\x08username\x18\x01 \x01(\tH\x00\x88\x01\x01B\x0b\n\t_username">\n\x11CreateUserRequest\x12)\n\x04data\x18\x01 \x01(\x0b2\x1b.panels.user.v1.UserMutable" \n\x12GetUserByIdRequest\x12\n\n\x02id\x18\x01 \x01(\t"(\n\x14GetUserByNameRequest\x12\x10\n\x08username\x18\x01 \x01(\t"N\n\x15UpdateUserByIdRequest\x12\n\n\x02id\x18\x01 \x01(\t\x12)\n\x04data\x18\x02 \x01(\x0b2\x1b.panels.user.v1.UserMutable"V\n\x17UpdateUserByNameRequest\x12\x10\n\x08username\x18\x01 \x01(\t\x12)\n\x04data\x18\x02 \x01(\x0b2\x1b.panels.user.v1.UserMutable"#\n\x15DeleteUserByIdRequest\x12\n\n\x02id\x18\x01 \x01(\t"+\n\x17DeleteUserByNameRequest\x12\x10\n\x08username\x18\x01 \x01(\t"=\n\tUserEvent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12"\n\x04data\x18\x02 \x01(\x0b2\x14.panels.user.v1.User2\xb4\x04\n\x0bUserService\x12G\n\nCreateUser\x12!.panels.user.v1.CreateUserRequest\x1a\x14.panels.user.v1.User"\x00\x12E\n\x07GetUser\x12".panels.user.v1.GetUserByIdRequest\x1a\x14.panels.user.v1.User"\x00\x12M\n\rGetUserByName\x12$.panels.user.v1.GetUserByNameRequest\x1a\x14.panels.user.v1.User"\x00\x12K\n\nUpdateUser\x12%.panels.user.v1.UpdateUserByIdRequest\x1a\x14.panels.user.v1.User"\x00\x12S\n\x10UpdateUserByName\x12\'.panels.user.v1.UpdateUserByNameRequest\x1a\x14.panels.user.v1.User"\x00\x12M\n\nDeleteUser\x12%.panels.user.v1.DeleteUserByIdRequest\x1a\x16.google.protobuf.Empty"\x00\x12U\n\x10DeleteUserByName\x12\'.panels.user.v1.DeleteUserByNameRequest\x1a\x16.google.protobuf.Empty"\x00b\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'user_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_globals['_USER']._serialized_start = 93
_globals['_USER']._serialized_end = 243
_globals['_USERMUTABLE']._serialized_start = 245
_globals['_USERMUTABLE']._serialized_end = 294
_globals['_CREATEUSERREQUEST']._serialized_start = 296
_globals['_CREATEUSERREQUEST']._serialized_end = 358
_globals['_GETUSERBYIDREQUEST']._serialized_start = 360
_globals['_GETUSERBYIDREQUEST']._serialized_end = 392
_globals['_GETUSERBYNAMEREQUEST']._serialized_start = 394
_globals['_GETUSERBYNAMEREQUEST']._serialized_end = 434
_globals['_UPDATEUSERBYIDREQUEST']._serialized_start = 436
_globals['_UPDATEUSERBYIDREQUEST']._serialized_end = 514
_globals['_UPDATEUSERBYNAMEREQUEST']._serialized_start = 516
_globals['_UPDATEUSERBYNAMEREQUEST']._serialized_end = 602
_globals['_DELETEUSERBYIDREQUEST']._serialized_start = 604
_globals['_DELETEUSERBYIDREQUEST']._serialized_end = 639
_globals['_DELETEUSERBYNAMEREQUEST']._serialized_start = 641
_globals['_DELETEUSERBYNAMEREQUEST']._serialized_end = 684
_globals['_USEREVENT']._serialized_start = 686
_globals['_USEREVENT']._serialized_end = 747
_globals['_USERSERVICE']._serialized_start = 750
_globals['_USERSERVICE']._serialized_end = 1314

View File

@@ -0,0 +1,100 @@
from google.protobuf import empty_pb2 as _empty_pb2
from google.protobuf import timestamp_pb2 as _timestamp_pb2
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union
DESCRIPTOR: _descriptor.FileDescriptor
class User(_message.Message):
__slots__ = ['id', 'username', 'is_admin', 'created_at', 'updated_at']
ID_FIELD_NUMBER: _ClassVar[int]
USERNAME_FIELD_NUMBER: _ClassVar[int]
IS_ADMIN_FIELD_NUMBER: _ClassVar[int]
CREATED_AT_FIELD_NUMBER: _ClassVar[int]
UPDATED_AT_FIELD_NUMBER: _ClassVar[int]
id: str
username: str
is_admin: bool
created_at: _timestamp_pb2.Timestamp
updated_at: _timestamp_pb2.Timestamp
def __init__(self, id: _Optional[str]=..., username: _Optional[str]=..., is_admin: bool=..., created_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]]=..., updated_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]]=...) -> None:
...
class UserMutable(_message.Message):
__slots__ = ['username']
USERNAME_FIELD_NUMBER: _ClassVar[int]
username: str
def __init__(self, username: _Optional[str]=...) -> None:
...
class CreateUserRequest(_message.Message):
__slots__ = ['data']
DATA_FIELD_NUMBER: _ClassVar[int]
data: UserMutable
def __init__(self, data: _Optional[_Union[UserMutable, _Mapping]]=...) -> None:
...
class GetUserByIdRequest(_message.Message):
__slots__ = ['id']
ID_FIELD_NUMBER: _ClassVar[int]
id: str
def __init__(self, id: _Optional[str]=...) -> None:
...
class GetUserByNameRequest(_message.Message):
__slots__ = ['username']
USERNAME_FIELD_NUMBER: _ClassVar[int]
username: str
def __init__(self, username: _Optional[str]=...) -> None:
...
class UpdateUserByIdRequest(_message.Message):
__slots__ = ['id', 'data']
ID_FIELD_NUMBER: _ClassVar[int]
DATA_FIELD_NUMBER: _ClassVar[int]
id: str
data: UserMutable
def __init__(self, id: _Optional[str]=..., data: _Optional[_Union[UserMutable, _Mapping]]=...) -> None:
...
class UpdateUserByNameRequest(_message.Message):
__slots__ = ['username', 'data']
USERNAME_FIELD_NUMBER: _ClassVar[int]
DATA_FIELD_NUMBER: _ClassVar[int]
username: str
data: UserMutable
def __init__(self, username: _Optional[str]=..., data: _Optional[_Union[UserMutable, _Mapping]]=...) -> None:
...
class DeleteUserByIdRequest(_message.Message):
__slots__ = ['id']
ID_FIELD_NUMBER: _ClassVar[int]
id: str
def __init__(self, id: _Optional[str]=...) -> None:
...
class DeleteUserByNameRequest(_message.Message):
__slots__ = ['username']
USERNAME_FIELD_NUMBER: _ClassVar[int]
username: str
def __init__(self, username: _Optional[str]=...) -> None:
...
class UserEvent(_message.Message):
__slots__ = ['type', 'data']
TYPE_FIELD_NUMBER: _ClassVar[int]
DATA_FIELD_NUMBER: _ClassVar[int]
type: str
data: User
def __init__(self, type: _Optional[str]=..., data: _Optional[_Union[User, _Mapping]]=...) -> None:
...

View File

@@ -0,0 +1,102 @@
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
from . import user_pb2 as user__pb2
class UserServiceStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.CreateUser = channel.unary_unary('/panels.user.v1.UserService/CreateUser', request_serializer=user__pb2.CreateUserRequest.SerializeToString, response_deserializer=user__pb2.User.FromString)
self.GetUser = channel.unary_unary('/panels.user.v1.UserService/GetUser', request_serializer=user__pb2.GetUserByIdRequest.SerializeToString, response_deserializer=user__pb2.User.FromString)
self.GetUserByName = channel.unary_unary('/panels.user.v1.UserService/GetUserByName', request_serializer=user__pb2.GetUserByNameRequest.SerializeToString, response_deserializer=user__pb2.User.FromString)
self.UpdateUser = channel.unary_unary('/panels.user.v1.UserService/UpdateUser', request_serializer=user__pb2.UpdateUserByIdRequest.SerializeToString, response_deserializer=user__pb2.User.FromString)
self.UpdateUserByName = channel.unary_unary('/panels.user.v1.UserService/UpdateUserByName', request_serializer=user__pb2.UpdateUserByNameRequest.SerializeToString, response_deserializer=user__pb2.User.FromString)
self.DeleteUser = channel.unary_unary('/panels.user.v1.UserService/DeleteUser', request_serializer=user__pb2.DeleteUserByIdRequest.SerializeToString, response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString)
self.DeleteUserByName = channel.unary_unary('/panels.user.v1.UserService/DeleteUserByName', request_serializer=user__pb2.DeleteUserByNameRequest.SerializeToString, response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString)
class UserServiceServicer(object):
"""Missing associated documentation comment in .proto file."""
def CreateUser(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetUser(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetUserByName(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def UpdateUser(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def UpdateUserByName(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def DeleteUser(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def DeleteUserByName(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_UserServiceServicer_to_server(servicer, server):
rpc_method_handlers = {'CreateUser': grpc.unary_unary_rpc_method_handler(servicer.CreateUser, request_deserializer=user__pb2.CreateUserRequest.FromString, response_serializer=user__pb2.User.SerializeToString), 'GetUser': grpc.unary_unary_rpc_method_handler(servicer.GetUser, request_deserializer=user__pb2.GetUserByIdRequest.FromString, response_serializer=user__pb2.User.SerializeToString), 'GetUserByName': grpc.unary_unary_rpc_method_handler(servicer.GetUserByName, request_deserializer=user__pb2.GetUserByNameRequest.FromString, response_serializer=user__pb2.User.SerializeToString), 'UpdateUser': grpc.unary_unary_rpc_method_handler(servicer.UpdateUser, request_deserializer=user__pb2.UpdateUserByIdRequest.FromString, response_serializer=user__pb2.User.SerializeToString), 'UpdateUserByName': grpc.unary_unary_rpc_method_handler(servicer.UpdateUserByName, request_deserializer=user__pb2.UpdateUserByNameRequest.FromString, response_serializer=user__pb2.User.SerializeToString), 'DeleteUser': grpc.unary_unary_rpc_method_handler(servicer.DeleteUser, request_deserializer=user__pb2.DeleteUserByIdRequest.FromString, response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString), 'DeleteUserByName': grpc.unary_unary_rpc_method_handler(servicer.DeleteUserByName, request_deserializer=user__pb2.DeleteUserByNameRequest.FromString, response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString)}
generic_handler = grpc.method_handlers_generic_handler('panels.user.v1.UserService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
class UserService(object):
"""Missing associated documentation comment in .proto file."""
@staticmethod
def CreateUser(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.user.v1.UserService/CreateUser', user__pb2.CreateUserRequest.SerializeToString, user__pb2.User.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def GetUser(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.user.v1.UserService/GetUser', user__pb2.GetUserByIdRequest.SerializeToString, user__pb2.User.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def GetUserByName(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.user.v1.UserService/GetUserByName', user__pb2.GetUserByNameRequest.SerializeToString, user__pb2.User.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def UpdateUser(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.user.v1.UserService/UpdateUser', user__pb2.UpdateUserByIdRequest.SerializeToString, user__pb2.User.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def UpdateUserByName(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.user.v1.UserService/UpdateUserByName', user__pb2.UpdateUserByNameRequest.SerializeToString, user__pb2.User.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def DeleteUser(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.user.v1.UserService/DeleteUser', user__pb2.DeleteUserByIdRequest.SerializeToString, google_dot_protobuf_dot_empty__pb2.Empty.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def DeleteUserByName(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None):
return grpc.experimental.unary_unary(request, target, '/panels.user.v1.UserService/DeleteUserByName', user__pb2.DeleteUserByNameRequest.SerializeToString, google_dot_protobuf_dot_empty__pb2.Empty.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

View File

@@ -0,0 +1,55 @@
from time import time
from typing import Optional
from datetime import timedelta
from pydantic import BaseModel, Field, SecretStr
from auth_service.models.proto import auth_pb2
from auth_service.models.exceptions import ServiceException, ServiceErrorCode
class AuthRecord(BaseModel):
user_id: str
password: SecretStr # Hashed Password
class AuthToken(BaseModel):
token_type: str = "Bearer"
access_token: str
expires_in: int = Field(default=int(timedelta(minutes=30).total_seconds()))
# refresh_token: str # todo: implement functionality in the future
@classmethod
def to_protobuf(cls, auth_token: "AuthToken") -> auth_pb2.AuthToken:
return auth_pb2.AuthToken(**auth_token.model_dump())
class AccessTokenClaims(BaseModel):
sub: str
iat: int = Field(default_factory=lambda: int(time()))
exp: int = Field(default_factory=lambda: int(time() + timedelta(minutes=30).total_seconds()))
class AuthRepository:
"""Abstract repository interface"""
async def auth_with_password(self, user_id: str, password: str) -> AuthToken:
raise ServiceException("unimplemented internal repository method", ServiceErrorCode.SERVICE_ERROR)
async def set_password_auth_method(self, user_id: str, password: str) -> None:
raise ServiceException("unimplemented internal repository method", ServiceErrorCode.SERVICE_ERROR)
async def delete_password_auth_method(self, user_id: str) -> None:
raise ServiceException("unimplemented internal repository method", ServiceErrorCode.SERVICE_ERROR)
class AuthDBRepository(AuthRepository):
"""Abstract database repository interface"""
async def get_auth_record(self, user_id: str) -> Optional[AuthRecord]:
raise ServiceException("unimplemented internal repository method", ServiceErrorCode.SERVICE_ERROR)
async def create_password_auth_method(self, user_id: str, password: str) -> None:
raise ServiceException("unimplemented internal repository method", ServiceErrorCode.SERVICE_ERROR)
async def update_password_auth_method(self, user_id: str, password: str) -> None:
raise ServiceException("unimplemented internal repository method", ServiceErrorCode.SERVICE_ERROR)