Skip to content

Commit

Permalink
add the html templates
Browse files Browse the repository at this point in the history
  • Loading branch information
meln1k committed Jan 12, 2024
1 parent f7c7afd commit 0c0df08
Show file tree
Hide file tree
Showing 8 changed files with 1,174 additions and 35 deletions.
16 changes: 5 additions & 11 deletions fixbackend/auth/user_verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,19 @@

from fixbackend.auth.models import User
from fixbackend.notification.email_service import EmailService, EmailServiceDependency
from fixbackend.notification.messages import VerifyEmail


class UserVerifier(ABC):
def plaintext_email_content(self, request: Request, token: str) -> str:
def email_content(self, *, request: Request, user_email: str, token: str) -> VerifyEmail:
# redirect is defined by the UI - use / as safe fallback
redirect_url = request.query_params.get("redirectUrl", "/")
verification_link = request.base_url
verification_link = verification_link.replace(
path="/auth/verify-email", query=f"token={token}&redirectUrl={redirect_url}"
)

body_text = f"Hello fellow FIX user, click this link to verify your email. {verification_link}"

return body_text
return VerifyEmail(recipient=user_email, verification_link=str(verification_link))

@abstractmethod
async def verify(self, user: User, token: str, request: Optional[Request]) -> None:
Expand All @@ -45,14 +44,9 @@ def __init__(self, email_service: EmailService) -> None:

async def verify(self, user: User, token: str, request: Optional[Request]) -> None:
assert request
body_text = self.plaintext_email_content(request, token)
message = self.email_content(request=request, user_email=user.email, token=token)

await self.email_service.send_email(
to=user.email,
subject="FIX: verify your e-mail address",
text=body_text,
html=None,
)
await self.email_service.send_message(message=message)


def get_user_verifier(email_service: EmailServiceDependency) -> UserVerifier:
Expand Down
6 changes: 5 additions & 1 deletion fixbackend/notification/email_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from fastapi import Depends

from fixbackend.config import Config, ConfigDependency
from fixbackend.notification.messages import EmailMessage


class EmailService(ABC):
Expand All @@ -36,6 +37,9 @@ async def send_email(
"""Send an email to the given address."""
raise NotImplementedError()

async def send_message(self, *, message: EmailMessage) -> None:
await self.send_email(to=message.recipient, subject=message.subject(), text=message.text(), html=message.html())


class ConsoleEmailService(EmailService):
async def send_email(
Expand All @@ -48,7 +52,7 @@ async def send_email(
print(f"Sending email to {to} with subject {subject}")
print(f"text: {text}")
if html:
print(f"html: {html}")
print(f"html (first 100 chars): {html[:100]}")


class EmailServiceImpl(EmailService):
Expand Down
91 changes: 91 additions & 0 deletions fixbackend/notification/messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Copyright (c) 2023. Some Engineering
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from typing import Any, Union
from attrs import frozen

from pathlib import Path
from jinja2 import Environment, FileSystemLoader
from functools import lru_cache


@lru_cache(maxsize=1)
def get_env() -> Environment:
return Environment(loader=FileSystemLoader(Path(__file__).parent / "templates"))


def render(template_name: str, **kwargs: Any) -> str:
template = get_env().get_template(template_name)
return template.render(**kwargs)


@frozen(kw_only=True)
class Signup:
recipient: str

def subject(self) -> str:
return "Welcome to fix!"

def text(self) -> str:
return f"Welcome to fix, {self.recipient}!"

def html(self) -> str:
return render("signup.html", title=self.subject(), email=self.recipient)


@frozen(kw_only=True)
class Invite:
inviter: str
invitation_link: str
recipient: str

def subject(self) -> str:
return "You've been invited to join fix!"

def text(self) -> str:
text = (
f"{self.inviter} has invited you to join their workspace. "
"Please click on the link below to accept the invitation. \n\n"
f"{self.invitation_link}"
)
return text

def html(self) -> str:
return render(
"invite.html",
title=self.subject(),
inviter=self.inviter,
invitation_link=self.invitation_link,
email=self.recipient,
)


@frozen(kw_only=True)
class VerifyEmail:
recipient: str
verification_link: str

def subject(self) -> str:
return "FIX: verify your e-mail address"

def text(self) -> str:
return f"Hello fellow FIX user, click this link to verify your email. {self.verification_link}"

def html(self) -> str:
return render(
"verify_email.html", title=self.subject(), email=self.recipient, verification_link=self.verification_link
)


EmailMessage = Union[Signup, Invite, VerifyEmail]
Loading

0 comments on commit 0c0df08

Please sign in to comment.