Skip to content

Commit

Permalink
feat: add activity logs
Browse files Browse the repository at this point in the history
  • Loading branch information
flavien-hugs committed Dec 19, 2024
1 parent 395a7c9 commit a82ce31
Show file tree
Hide file tree
Showing 11 changed files with 413 additions and 57 deletions.
6 changes: 5 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ FRONTEND_PATH_RESET_PASSWORD=<ChangeMe>
FRONTEND_PATH_ACTIVATE_ACCOUNT=<ChangeMe>
FRONTEND_PATH_LOGIN=<ChangeMe>
REGISTER_WITH_EMAIL=<ChangeMe>
MONGO_FS_BUCKET_NAME=<ChangeMe>
LIST_ROLES_ENDPOINT_SECURITY_ENABLED=<ChangeMe>
REGISTER_USER_ENDPOINT_SECURITY_ENABLED=<ChangeMe>

Expand Down Expand Up @@ -79,3 +78,8 @@ REDIS_PASSWORD=unsta
REDIS_LOG_LEVEL=warning
REDIS_EXPIRE_CACHE=300
CACHE_DB_URL=redis://redis:6379/0

# VALIDATE TOKEN AND TRAILHUB CLIENT ENDPOINT
API_AUTH_URL_BASE=https://telemed-test.carein.cloud
API_TRAILHUB_ENDPOINT=/logs
API_AUTH_VALIDATE_TOKEN_ENDPOINT=/check-validate-access-token
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pydantic-settings = "^2.5.2"
pwdlib = {extras = ["argon2", "bcrypt"], version = "^0.2.1"}
user-agents = "^2.2.0"
python-multipart = "^0.0.12"
cachetools = "^5.5.0"


[tool.poetry.group.test.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion src/common
8 changes: 6 additions & 2 deletions src/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class AuthBaseConfig(BaseSettings):
LIST_PARAMETERS_ENDPOINT_SECURITY_ENABLED: Optional[bool] = Field(
..., alias="LIST_PARAMETERS_ENDPOINT_SECURITY_ENABLED"
)
USE_GRIDFS_STORAGE: Optional[bool] = Field(default=False, alias="USE_GRIDFS_STORAGE")
USE_TRACK_ACTIVITY_LOGS: Optional[bool] = Field(default=True, alias="USE_TRACK_ACTIVITY_LOGS")

# USER MODEL NAME
USER_MODEL_NAME: str = Field(..., alias="USER_MODEL_NAME")
Expand All @@ -40,7 +40,6 @@ class AuthBaseConfig(BaseSettings):

# DATABASE CONFIG
MONGO_DB: str = Field(..., alias="MONGO_DB")
MONGO_FS_BUCKET_NAME: str = Field(default="auth", alias="MONGO_FS_BUCKET_NAME")
MONGODB_URI: str = Field(..., alias="MONGODB_URI")

# REDIS CONFIG
Expand All @@ -52,6 +51,11 @@ class AuthBaseConfig(BaseSettings):
RATE_LIMIT_REQUEST: Optional[int] = Field(default=5, alias="RATE_LIMIT_REQUEST")
RATE_LIMIT_INTERVAL: Optional[int] = Field(default=3600, alias="RATE_LIMIT_INTERVAL")

# VALIDATE TOKEN AND TRAILHUB CLIENT ENDPOINT
API_AUTH_URL_BASE: str = Field(..., alias="API_AUTH_URL_BASE")
API_TRAILHUB_ENDPOINT: str = Field(..., alias="API_TRAILHUB_ENDPOINT")
API_AUTH_VALIDATE_TOKEN_ENDPOINT: str = Field(..., alias="API_AUTH_VALIDATE_TOKEN_ENDPOINT")


@lru_cache
def get_settings() -> AuthBaseConfig:
Expand Down
201 changes: 178 additions & 23 deletions src/routers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from slugify import slugify

from src.common.helpers.caching import custom_key_builder, delete_custom_key
from src.common.services.trailhub_client import send_event
from src.config import enable_endpoint, settings
from src.middleware import AuthorizedHTTPBearer
from src.models import User
Expand All @@ -22,19 +23,41 @@
VerifyOTP,
)
from src.services import auth
from src.shared import mail_service, sms_service
from src.shared import API_TRAILHUB_ENDPOINT, API_VERIFY_ACCESS_TOKEN_ENDPOINT, mail_service, sms_service

auth_router = APIRouter(prefix="", tags=["AUTH"], redirect_slashes=False)

service_appname_slug = slugify(settings.APP_NAME)


@auth_router.post("/signup", summary="Signup", status_code=status.HTTP_201_CREATED)
async def register(bg: BackgroundTasks, payload: RequestChangePassword = Body(...)):
async def register(request: Request, bg: BackgroundTasks, payload: RequestChangePassword = Body(...)):
if settings.REGISTER_WITH_EMAIL:
return await auth.signup_with_email(bg, payload.email)
result = await auth.signup_with_email(bg, payload.email)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.email}' has signed up.",
user_id=None,
)
return result
else:
return await auth.signup_with_phonenumber(bg, payload)
result = await auth.signup_with_phonenumber(bg, payload)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.phonenumber}' has signed up successfully.",
user_id=None,
)
return result


if bool(settings.REGISTER_WITH_EMAIL):
Expand All @@ -47,13 +70,39 @@ async def register(bg: BackgroundTasks, payload: RequestChangePassword = Body(..
summary="Complete registration if you are registered with an e-mail address.",
description="Complete registration if you are registered with an e-mail address.",
)
async def register_completed(token: str, bg: BackgroundTasks, payload: UserBaseSchema = Body(...)):
return await auth.completed_register_with_email(token, payload, bg)
async def register_completed(
request: Request, token: str, bg: BackgroundTasks, payload: UserBaseSchema = Body(...)
):
result = await auth.completed_register_with_email(token, payload, bg)

if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.phonenumber}' has completed registration.",
user_id=None,
)

return result


@auth_router.post("/login", summary="Login", status_code=status.HTTP_200_OK)
async def login(request: Request, payload: LoginUser = Body(...)):
return await auth.login(request, payload)
async def login(request: Request, bg: BackgroundTasks, payload: LoginUser = Body(...)):
result = await auth.login(request, payload)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=settings.API_AUTH_VALIDATE_TOKEN_ENDPOINT,
trailhub_url=settings.API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.phonenumber}' has logged in.",
user_id=None,
)
return result


if not bool(settings.REGISTER_WITH_EMAIL):
Expand All @@ -64,12 +113,34 @@ async def login(request: Request, payload: LoginUser = Body(...)):
summary="Verify OTP Code",
status_code=status.HTTP_200_OK,
)
async def verif_otp_code(payload: VerifyOTP = Body(...)):
return await auth.verify_otp(payload)
async def verif_otp_code(request: Request, bg: BackgroundTasks, payload: VerifyOTP = Body(...)):
result = await auth.verify_otp(payload)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.phonenumber}' has verified OTP code.",
user_id=None,
)
return result

@auth_router.post("/resend-otp", summary="Resend OTP Code", status_code=status.HTTP_200_OK)
async def resend_otp_code(bg: BackgroundTasks, payload: PhonenumberModel = Body(...)):
return await auth.resend_otp(bg, payload)
async def resend_otp_code(request: Request, bg: BackgroundTasks, payload: PhonenumberModel = Body(...)):
result = await auth.resend_otp(bg, payload)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.phonenumber}' has resent OTP code.",
user_id=None,
)
return result


@auth_router.get(
Expand Down Expand Up @@ -105,40 +176,104 @@ async def check_validate_access_token(token: str):


@auth_router.put("/change-password/{id}", summary="Set up a password for the user.", status_code=status.HTTP_200_OK)
async def change_password(id: PydanticObjectId, payload: ChangePassword = Body(...)):
return await auth.change_password(user_id=id, payload=payload)
async def change_password(
request: Request, bg: BackgroundTasks, id: PydanticObjectId, payload: ChangePassword = Body(...)
):
result = await auth.change_password(user_id=id, payload=payload)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message="has changed password.",
user_id=str(id),
)
return result


if bool(settings.REGISTER_WITH_EMAIL):

@auth_router.post("/request-password-reset", summary="Request a password reset.", status_code=status.HTTP_200_OK)
async def request_password_reset_with_email(bg: BackgroundTasks, payload: EmailModelMixin = Body(...)):
return await auth.request_password_reset_with_email(bg=bg, email=payload.email)
async def request_password_reset_with_email(
request: Request, bg: BackgroundTasks, payload: EmailModelMixin = Body(...)
):
result = await auth.request_password_reset_with_email(bg=bg, email=payload.email)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.email}' has requested a password reset.",
user_id=None,
)
return result


if not bool(settings.REGISTER_WITH_EMAIL):

@auth_router.post("/request-password-reset", summary="Request a password reset.", status_code=status.HTTP_200_OK)
async def request_password_reset_with_phonenumber(bg: BackgroundTasks, payload: PhonenumberModel = Body(...)):
return await auth.request_password_reset_with_phonenumber(bg=bg, payload=payload)
async def request_password_reset_with_phonenumber(
request: Request, bg: BackgroundTasks, payload: PhonenumberModel = Body(...)
):
result = await auth.request_password_reset_with_phonenumber(bg=bg, payload=payload)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"{payload.phonenumber} has requested a password reset.",
user_id=None,
)
return result


if bool(settings.REGISTER_WITH_EMAIL):

@auth_router.post("/reset-password-completed", summary="Request a password reset.", status_code=status.HTTP_200_OK)
async def email_reset_password_completed(
request: Request,
bg: BackgroundTasks,
token: str = Query(..., alias="token", description="Reset password token"),
payload: ChangePassword = Body(...),
):
return await auth.reset_password_completed_with_email(bg, token=token, payload=payload)
result = await auth.reset_password_completed_with_email(bg, token=token, payload=payload)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message="has reset password.",
user_id=None,
)
return result


if not bool(settings.REGISTER_WITH_EMAIL):

@auth_router.post("/reset-password-completed", summary="Request a password reset.", status_code=status.HTTP_200_OK)
async def phonenumber_reset_password_completed(payload: ChangePasswordWithOTPCode = Body(...)):
return await auth.reset_password_completed_with_phonenumber(payload)
async def phonenumber_reset_password_completed(
request: Request, bg: BackgroundTasks, payload: ChangePasswordWithOTPCode = Body(...)
):
result = await auth.reset_password_completed_with_phonenumber(payload)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=bg,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.phonenumber}' has reset password.",
user_id=None,
)
return result


if bool(enable_endpoint.SHOW_CHECK_USER_ATTRIBUTE_ENDPOINT):
Expand All @@ -155,15 +290,35 @@ async def check_user_attributes(


@auth_router.post("-sms", summary="Send a message", status_code=status.HTTP_200_OK, include_in_schema=False)
async def send_sms(background: BackgroundTasks, payload: SendSmsMessage = Body(...)):
async def send_sms(request: Request, background: BackgroundTasks, payload: SendSmsMessage = Body(...)):
phone = payload.phone_number.replace("+", "")
await sms_service.send_sms(background, recipient=phone, message=payload.message)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=background,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.phone_number}' has sent a message.",
user_id=None,
)
return {"message": "SMS sent successfully."}


@auth_router.post("-email", summary="Send a e-mail", status_code=status.HTTP_200_OK, include_in_schema=False)
async def send_email(background: BackgroundTasks, payload: SendEmailMessage = Body(...)):
async def send_email(request: Request, background: BackgroundTasks, payload: SendEmailMessage = Body(...)):
mail_service.send_email_background(
background, recipients=payload.recipients, subject=payload.subject, body=payload.message
)
if settings.USE_TRACK_ACTIVITY_LOGS:
await send_event(
request=request,
bg=background,
oauth_url=API_VERIFY_ACCESS_TOKEN_ENDPOINT,
trailhub_url=API_TRAILHUB_ENDPOINT,
source=settings.APP_NAME.lower(),
message=f"'{payload.recipients}' has sent a message.",
user_id=None,
)
return {"message": "E-mail sent successfully."}
Loading

0 comments on commit a82ce31

Please sign in to comment.