Skip to content

Psycho-Poodle/sahienglish-backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

✨ What this project does

  • πŸ” Authentication & Sessions
    • Register β†’ email verification (secure token link)
    • Login with OAuth2 password flow
    • Short-lived access JWT + long-lived refresh with rotation & JTI persistence
    • Logout (revokes refresh), token versioning for global invalidation
  • πŸ”‘ Password Flows
    • Forgot password: email OTP (bcrypt-hashed) β†’ verify β†’ short-lived reset token β†’ set new password
    • Change password: requires old password
  • πŸ‘€ Profile
    • Update full name, update email (optional follow‑up re‑verification)
  • 🧠 AI Text Tools (Gemini 1.5 Flash via google-generative-ai)
    • Fix Grammar, Translate, Improve, Humanize
    • Protected endpoints β€” require Bearer access token
  • 🧩 Templates
    • Default templates (shared to all users, isDefault: true)
    • Custom templates (per-user, CRUD)
  • 🧱 MongoDB (Atlas/Local)
    • Async driver (Motor), strict indexes, TTL cleanup for OTP and refresh tokens

πŸ—οΈ Tech & Libraries

  • FastAPI / Uvicorn
  • Pydantic v2
  • MongoDB + Motor (async)
  • python-jose (JWT), passlib[bcrypt] (password/OTP hashing)
  • google-generative-ai (Gemini 1.5 Flash)
  • smtplib (Gmail SMTP w/ App Password) for email

πŸ“‚ Project structure (high‑level)

app/
β”œβ”€ main.py                       # App factory, CORS, routers, startup DB connect
β”œβ”€ config.py                     # Settings (reads .env)
β”œβ”€ database.py                   # Motor client, indexes, collection getters
β”œβ”€ routes/
β”‚  β”œβ”€ auth.py                    # Register, verify-email, login, refresh, logout,
β”‚  β”‚                              # forgot-password, verify-otp, reset-password,
β”‚  β”‚                              # change-password
β”‚  β”œβ”€ actions.py                 # AI tools: fix-grammar, translate, improve, humanize
β”‚  └─ templates.py               # Default + custom templates CRUD
β”œβ”€ auth_dependencies.py          # get_current_user() (Bearer token -> user)
β”œβ”€ security/
β”‚  β”œβ”€ crypto.py                  # hash/verify password + OTP with bcrypt
β”‚  └─ tokens.py                  # mint/validate access/refresh/reset tokens
β”œβ”€ security/session_store.py     # persist/rotate/revoke refresh tokens (JTI)
β”œβ”€ email_service.py              # Email utility (Gmail SMTP)
β”œβ”€ validation.py                 # Validation helpers & error codes
β”œβ”€ auth_models.py                # Pydantic models (requests/responses/DB)
β”œβ”€ exceptions.py                 # AuthException + typed error responses
└─ ...

πŸš€ Getting started

1) Clone & install

git clone https://github.com/Psycho-Poodle/sahienglish-backend.git
cd sahienglish-backend
python -m venv .venv && source .venv/Scripts/activate  # on Windows PowerShell: .venv\Scripts\Activate.ps1
pip install -r requirements.txt

2) Environment variables (.env)

Never commit real secrets. Use placeholders locally and real secrets in deployment.

# MongoDB
MONGODB_URL=mongodb+srv://<user>:<pass>@cluster0.xxx.mongodb.net/sahienglish_db?retryWrites=true&w=majority
DATABASE_NAME=sahienglish_db

# JWT
JWT_SECRET_KEY=change-me-min-32-chars
JWT_ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=15
REFRESH_TOKEN_EXPIRE_DAYS=30
RESET_TOKEN_EXPIRE_MINUTES=15

# Email (Gmail SMTP with App Password)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=[email protected]
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=[email protected]

# App
APP_NAME=SahiEnglish
APP_URL=http://localhost:8000   # use http locally
ENVIRONMENT=development

# Security / OTP
PASSWORD_MIN_LENGTH=8
MAX_LOGIN_ATTEMPTS=5
ACCOUNT_LOCKOUT_DURATION_MINUTES=30
OTP_EXPIRE_MINUTES=10           # you can set 1 for testing (60s)
OTP_MAX_ATTEMPTS=5

# Rate limits (soft logic level)
LOGIN_RATE_LIMIT_PER_MINUTE=5
LOGIN_RATE_LIMIT_PER_HOUR=20
FORGOT_PASSWORD_RATE_LIMIT_PER_15MIN=3
FORGOT_PASSWORD_RATE_LIMIT_PER_HOUR=10
REGISTER_RATE_LIMIT_PER_HOUR=3
VERIFY_OTP_RATE_LIMIT_PER_HOUR=10

# Gemini (text tools)
GEMINI_API_KEY=your-gemini-api-key

3) Run API

uvicorn app.main:app --reload
# visit http://127.0.0.1:8000/docs

πŸ” Authentication flow (summary)

  • Register POST /auth/register β†’ creates user (inactive by default for email verification)
  • Verify Email GET /auth/verify-email?token=...
    Token is a short-lived signed JWT (type=verify_email). On success β†’ is_email_verified=true.
  • Login POST /auth/login (OAuth2 password form: grant_type=password):
    Returns { access_token, refresh_token, token_type="bearer", expires_in }.
  • Use API with Authorization: Bearer <access_token>.
  • Refresh POST /auth/refresh with refresh_token. Server rotates & revokes old, returns new pair.
  • Logout POST /auth/logout to revoke current refresh (server-side).
  • Forgot password POST /auth/forgot-password β†’ email OTP (6 digits, bcrypt‑hashed in DB)
  • Verify OTP POST /auth/verify-otp β†’ returns short‑lived reset_token
  • Reset password POST /auth/reset-password with reset_token + new password
  • Change password POST /auth/change-password (requires valid access token & old password)
  • Profile updates PATCH /auth/profile (e.g., change name/email)

Access tokens are short‑lived (default 15 min). Refresh tokens are long‑lived (default 30 days) and stored with JTI in MongoDB for revocation/rotation. Passwords & OTPs use bcrypt via passlib.


🧠 AI Text Tools (protected routes)

All require Authorization: Bearer <access_token> and call Gemini 1.5 Flash through google-generative-ai.

  • POST /actions/fix-grammar
  • POST /actions/translate (fields: text, target_language)
  • POST /actions/improve
  • POST /actions/humanize

Request example

POST /actions/fix-grammar
Authorization: Bearer <access_token>
Content-Type: application/json

{ "text": "i has a apple, it was red" }

Response

{ "result": "I have an apple; it was red." }

πŸ“‘ Templates

Two kinds of templates live in the single templates collection:

  • Default (system) templates: { isDefault: true } β€” visible to all users
  • Custom templates: { isDefault: false, userId: <ObjectId> } β€” only visible to the owner

Endpoints (require auth):

  • GET /templates/ β€” lists (default βˆͺ user’s custom) templates
  • POST /templates/ β€” create custom template
  • PUT /templates/{id} β€” update your custom template
  • DELETE /templates/{id} β€” delete your custom template

Seed default templates (once)

You can insert a few defaults directly or via a small script. Example docs:

[
  {
    "title": "Professional Email (General)",
    "category": "email",
    "content": "Dear Hiring Manager,\n\nI’m writing to express my interest in the [Position] role at [Company Name]. ...\n\nBest regards,\n[Your Name]",
    "isDefault": true
  },
  {
    "title": "Job Application β€” Short",
    "category": "job-application",
    "content": "Dear [Hiring Manager],\n\nPlease find my application for [Role] attached. ...\n\nSincerely,\n[Your Name]",
    "isDefault": true
  },
  {
    "title": "Meeting Request",
    "category": "email",
    "content": "Hi [Name],\n\nCould we schedule a quick call to discuss [topic]? ...\n\nThanks,\n[Your Name]",
    "isDefault": true
  },
  {
    "title": "Wedding Invitation",
    "category": "invitation",
    "content": "Dear [Guest],\n\nYou’re cordially invited to celebrate our wedding on [Date] at [Venue]. ...\n\nWith love,\n[Names]",
    "isDefault": true
  },
  {
    "title": "Thank‑You Email",
    "category": "email",
    "content": "Hello [Name],\n\nThank you for your time today. I appreciated learning more about [topic]. ...\n\nBest,\n[Your Name]",
    "isDefault": true
  }
]

If you want a helper script, create app/scripts/seed_templates.py that inserts the JSON above with isDefault: true and run:

python -m app.scripts.seed_templates

πŸ§ͺ Local utilities

  • Mongo connectivity check: python -m app.test_connection
  • Session store smoke test: python -m app.scratch_session_check
  • Email test (Gmail SMTP): python -m app.scratch_send_email

πŸ”§ Swagger & auth in docs

Open http://127.0.0.1:8000/docs β†’ click Authorize β†’ use OAuth2PasswordBearer:

  • username: your account email
  • password: your account password
  • No client id/secret is used (password grant), just β€œAuthorize”, then try protected routes.

πŸ”’ Security notes

  • Never log raw passwords/OTPs or tokens.
  • bcrypt for password & OTP hashing.
  • Refresh tokens stored server‑side with JTI & TTL, rotated on each refresh.
  • token_version increments can invalidate all previous tokens for a user.
  • CORS is open by default for local testing β€” restrict in production.

πŸ“¦ Deployment notes (short)

  • Use a real domain + HTTPS for APP_URL in production (affects email links).
  • Store secrets in a secure vault (not in .env committed to git).
  • Set strong JWT_SECRET_KEY (β‰₯ 32 chars) and rotate periodically.
  • Use a dedicated email sender account with Gmail App Password or a transactional provider.

About

FastAPI + MongoDB backend for SahiEnglish. Features authentication, email verification, password reset, AI-powered grammar tools, and template

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages