Skip to content

Commit

Permalink
Merge pull request #1 from JohnGrubba/dev
Browse files Browse the repository at this point in the history
SignUp E-Mail
  • Loading branch information
JohnGrubba authored Jun 25, 2024
2 parents b0328b5 + 695f70b commit 471a024
Show file tree
Hide file tree
Showing 22 changed files with 117 additions and 50 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
**.venv
**.env
**config.json
**config.json
**.pyc
8 changes: 4 additions & 4 deletions config/email/ConfirmEmail.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
<meta name="x-apple-disable-message-reformatting">
<!--[if !mso]><!-->
<meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]-->
<title></title>
<title>Confirm your Email</title>
</head>

<body class="clean-body u_body"
style="margin: 0;padding: 0;-webkit-text-size-adjust: 100%;background-color: #ecf0f1;color: #000000">
<h1>Did you just sign up as {{username}}</h1>
<h1>Did you just sign up as {username}</h1>
<p>If it was you, then enter this code to confirm your email address:</p>
<h2>{{code}}</h2>
<h2>{code}</h2>
<p>If it wasn't you, then ignore this email.</p>
<p>This code expires in {{time}}</p>
<p>This code expires in {time} minutes.</p>
</body>

</html>
7 changes: 0 additions & 7 deletions config/email/ConfirmEmail.md

This file was deleted.

2 changes: 1 addition & 1 deletion config/email/WelcomeEmail.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

<body class="clean-body u_body"
style="margin: 0;padding: 0;-webkit-text-size-adjust: 100%;background-color: #ecf0f1;color: #000000">
<h1>This is a Template Welcome Message. Welcome to EZAuth {{username}}</h1>
<h1>This is a Template Welcome Message. Welcome to EZAuth {username}</h1>
</body>

</html>
6 changes: 0 additions & 6 deletions config/email/WelcomeMail.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/getting-started/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Make sure that all parameters are set correctly before starting the service.
| Parameter | Description |
|------------|-------------|
| `signup.enable_conf_email` | **Datatype:** Boolean <br> **Default:** `false` <br> Enable or disable the confirmation E-Mail for new users. |
| `signup.conf_code_expiry` | **Datatype:** Integer <br> **Default:** `3600` <br> The time in seconds until the confirmation code expires. |
| `signup.conf_code_expiry` | **Datatype:** Integer <br> **Default:** `5` <br> The time in minutes until the confirmation code expires. |
| `signup.enable_welcome_email` | **Datatype:** Boolean <br> **Default:** `false` <br> Enable or disable the welcome E-Mail for new users. |

### Email Configuration
Expand Down
33 changes: 33 additions & 0 deletions docs/getting-started/email_config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Default E-Mail Templates

EZAuth uses a set of default E-mail templates to send out e-mails to users. These templates are stored in the `config/email` folder. You can customize these templates as per your requirements.

!!! Info "E-Mail Subject"
EZAuth will automatically use the HTML `<title></title>` tag to specify the subject of the e-mail.

## Required E-Mail Templates

??? Warning "Required Templates"
Only edit those templates and don't delete them. If you delete them, the service will not work as expected.

### 1. **Email Verification**
- Can be enabled in the `config.json` file.
- File Name: `ConfirmEmail.html`

#### Additional Placeholders
- `{{code}}`: The confirmation code to confirm the email address.
- `{{time}}`: Time remaining before the confirmation code expires in minutes. (e.g. 5)

!!! Info "Default Placeholders"
Every E-Mail template which is directed at a registered user will be able to use any of the properties of the user in the database. This includes the `username`, `email`, `id`, and any other property you might have added to the user object.

### 2. **Welcome Email**
- Can be enabled in the `config.json` file.
- Will be sent out after the user has successfully verified their email address.
- File Name: `WelcomeMail.html`

# Custom E-Mail Templates

!!! Info "Work in Progress"
This feature is still in development and might not work as expected.
You can also create custom E-mail templates and use them in the service. To use a custom E-mail template you need to specify the path to the template in the `config.json` file.
10 changes: 9 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,12 @@
- **Customizable**: You can customize the service to your needs.
- **Self-hosted**: You have full control over your user data.
- **Secure**: The service is designed with security in mind.
- **Easy to use**: The service is easy to set up and use.
- **Easy to use**: The service is easy to set up and use.

## Customizability

- **Email Templates**: You can customize all emails sent by the service.
- **User Data**: You can add custom fields to the user object which can be accessed in the email templates.
This is possible by using `MongoDB` as the database.
- **Database Configuration**: You can configure the database connection to your needs.
- **And much more..**
3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ nav:
- Home: index.md
- Getting Started:
- Installation / Setup: getting-started/setup.md
- Configuration: getting-started/configuration.md
- Basic Configuration: getting-started/configuration.md
- E-Mail Templates: getting-started/email_config.md
theme:
name: material
logo: "ezauth_logo.png"
Expand Down
Binary file removed src/__pycache__/main.cpython-312.pyc
Binary file not shown.
Binary file removed src/api/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file removed src/api/__pycache__/model.cpython-312.pyc
Binary file not shown.
Binary file removed src/api/__pycache__/signup.cpython-312.pyc
Binary file not shown.
8 changes: 7 additions & 1 deletion src/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import RedirectResponse
from api.signup import router as signupRouter
import logging

app = FastAPI()
logging.basicConfig(format="%(asctime)s - %(message)s", level=logging.INFO)

app = FastAPI(
title="EZAuth API",
description="EZAuth is a high performance self-hosted and fully customizable authentication service",
)

origins = ["*"]
app.add_middleware(
Expand Down
42 changes: 32 additions & 10 deletions src/api/signup.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
from fastapi import APIRouter
from api.model import UserSignupRequest
from tools import db_collection
from tools import users_collection
from tools.mail import send_email
from expiringdict import ExpiringDict
from tools import SignupConfig
from expiring_dict import ExpiringDict
import random

# Create an ExpiringDict object to store temporary accounts (not email verified yet)
temp_accounts = ExpiringDict(ttl=SignupConfig.conf_code_expiry * 60, interval=10)

# Generate and shuffle 10000 unique IDs for confirmation email
all_ids = [f"{i:04d}" for i in range(10000)]
random.shuffle(all_ids)

router = APIRouter(
prefix="/signup",
Expand All @@ -14,12 +23,25 @@

@router.post("/", status_code=204)
async def signup(signup_form: UserSignupRequest):
print(signup_form.model_dump())
db_collection.insert_one(signup_form.model_dump())
pass

if SignupConfig.enable_conf_email:
# If all numbers have been used, raise an exception
if not all_ids:
raise Exception(
"All unique IDs have been used. More than 10000 signups in a short time."
)
# Get a unique ID for confirmation email
unique_id = all_ids.pop()
# Save the Account into the expiring dict (delete if user refuses to confirm email in time)
temp_accounts[unique_id] = signup_form

@router.get("/new")
async def new():
send_email("WelcomeEmail", "[email protected]", username="Jonas")
pass
# Generate and send confirmation email
send_email(
"ConfirmEmail",
signup_form.email,
code=unique_id,
time=SignupConfig.conf_code_expiry,
username=signup_form.username,
)
else:
# Save the Account into the database
users_collection.insert_one(signup_form.model_dump())
2 changes: 1 addition & 1 deletion src/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
fastapi==0.111.0
pymongo==4.7.3
expiringdict==1.2.2
expiring-dict==1.1.0
4 changes: 2 additions & 2 deletions src/tools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .db import col as db_collection
from .conf import config
from .db import users_collection
from .conf import SignupConfig, EmailConfig
Binary file removed src/tools/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file removed src/tools/__pycache__/db.cpython-312.pyc
Binary file not shown.
14 changes: 14 additions & 0 deletions src/tools/conf.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
import json

config = json.load(open("/src/app/config/config.json", "rb"))


class SignupConfig:
enable_conf_email: bool = config["signup"]["enable_conf_email"]
conf_code_expiry: int = config["signup"]["conf_code_expiry"]
enable_welcome_email: bool = config["signup"]["enable_welcome_email"]


class EmailConfig:
login_usr: str = config["email"]["login_usr"]
login_pwd: str = config["email"]["login_pwd"]
sender_email: str = config["email"]["sender_email"]
smtp_host: str = config["email"]["smtp_host"]
smtp_port: int = config["email"]["smtp_port"]
6 changes: 3 additions & 3 deletions src/tools/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

client = MongoClient(DATABASE_URL)
db = client.get_database("ezauth")
col = db.get_collection("users")
users_collection = db.get_collection("users")

col.create_index("email", unique=True)
col.create_index("username", unique=True)
users_collection.create_index("email", unique=True)
users_collection.create_index("username", unique=True)
17 changes: 6 additions & 11 deletions src/tools/mail.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from . import config

smtp_host = config["email"]["smtp_host"]
smtp_port = config["email"]["smtp_port"]
username = config["email"]["login_usr"]
password = config["email"]["login_pwd"]
sender_email = config["email"]["sender_email"]
from . import EmailConfig
import logging


def load_template(template_name: str, **kwargs) -> str:
Expand All @@ -21,16 +16,16 @@ def send_email(template_name: str, to: str, **kwargs):
html_content, subject = load_template(template_name, **kwargs)

msg = MIMEMultipart()
msg["From"] = sender_email
msg["From"] = EmailConfig.sender_email
msg["To"] = to
msg["Subject"] = subject

# Attach HTML content
msg.attach(MIMEText(html_content, "html"))

# Send email
with smtplib.SMTP_SSL(smtp_host, smtp_port) as server:
server.login(username, password)
with smtplib.SMTP_SSL(EmailConfig.smtp_host, EmailConfig.smtp_port) as server:
server.login(EmailConfig.login_usr, EmailConfig.login_pwd)
server.send_message(msg)

print("Email sent successfully!")
logging.info(f"Email sent to {to} with subject: {subject}")

0 comments on commit 471a024

Please sign in to comment.