init commit
This commit is contained in:
158
app/blueprints/auth/routes.py
Normal file
158
app/blueprints/auth/routes.py
Normal file
@@ -0,0 +1,158 @@
|
||||
# app/auth/routes.py
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, flash, session
|
||||
from flask_login import login_user, logout_user, login_required
|
||||
|
||||
from app.utils.extensions import User, get_client_from_session
|
||||
from app.services.appwrite_client import AppwriteAccountClient
|
||||
|
||||
auth_bp = Blueprint("auth", __name__, url_prefix="")
|
||||
|
||||
@auth_bp.route("/register", methods=["GET", "POST"])
|
||||
def register():
|
||||
if request.method == "POST":
|
||||
email = request.form.get("email", "").strip()
|
||||
password = request.form.get("password", "")
|
||||
name = (request.form.get("name") or "").strip() or None
|
||||
|
||||
if not email or not password:
|
||||
flash("Email and password are required.", "error")
|
||||
return redirect(url_for("auth.register"))
|
||||
|
||||
try:
|
||||
# Create user (no bound session needed)
|
||||
aw = AppwriteAccountClient(use_admin=True)
|
||||
aw.create_user(email=email, password=password, name=name)
|
||||
|
||||
# Create a session and STORE THE SECRET in Flask session
|
||||
sess_obj = aw.create_email_password_session(email=email, password=password)
|
||||
secret = sess_obj.get("secret")
|
||||
|
||||
session["appwrite_cookies"] = secret
|
||||
|
||||
# Bind and fetch profile (either reuse aw with binding or make a new instance)
|
||||
aw = AppwriteAccountClient(cookies=secret)
|
||||
profile = aw.get_account()
|
||||
session["user_profile"] = profile
|
||||
|
||||
# (Optional) Create a JWT for short-lived API calls
|
||||
jwt = aw.create_jwt()
|
||||
session["appwrite_jwt"] = jwt
|
||||
|
||||
login_user(User(id=profile["$id"], email=profile["email"], name=profile.get("name")))
|
||||
flash("Account created and you are now logged in.", "success")
|
||||
return redirect(url_for("main.dashboard"))
|
||||
|
||||
except Exception as e:
|
||||
flash(str(e), "error")
|
||||
return redirect(url_for("auth.register"))
|
||||
|
||||
return render_template("auth/register.html")
|
||||
|
||||
|
||||
@auth_bp.route("/login", methods=["GET", "POST"])
|
||||
def login():
|
||||
if request.method == "POST":
|
||||
email = request.form.get("email", "").strip()
|
||||
password = request.form.get("password", "")
|
||||
if not email or not password:
|
||||
flash("Email and password are required.", "error")
|
||||
return redirect(url_for("auth.login"))
|
||||
|
||||
try:
|
||||
# 1) Create session once
|
||||
aw = AppwriteAccountClient(use_admin=True)
|
||||
sess_obj = aw.create_email_password_session(email=email, password=password)
|
||||
secret = sess_obj.get("secret")
|
||||
|
||||
# 2) Save the secret for SSR calls
|
||||
session["appwrite_cookies"] = secret
|
||||
|
||||
# 3) Bind and load profile
|
||||
aw = AppwriteAccountClient(cookies=secret)
|
||||
profile = aw.get_account()
|
||||
session["user_profile"] = profile
|
||||
|
||||
# optional: create a JWT now if your dashboard expects it
|
||||
try:
|
||||
session["appwrite_jwt"] = aw.create_jwt()
|
||||
except Exception:
|
||||
session["appwrite_jwt"] = {}
|
||||
|
||||
usersname = profile.get("name")
|
||||
|
||||
login_user(User(id=profile["$id"], email=profile["email"], name=profile.get("name")))
|
||||
flash(f"Welcome back {usersname}!", "success")
|
||||
return redirect(url_for("main.dashboard"))
|
||||
except Exception as e:
|
||||
flash(str(e), "error")
|
||||
return redirect(url_for("auth.login"))
|
||||
|
||||
# Get method
|
||||
return render_template("auth/login.html")
|
||||
|
||||
|
||||
@auth_bp.route("/logout", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def logout():
|
||||
secret = session.get("appwrite_cookies")
|
||||
if secret:
|
||||
try:
|
||||
aw = AppwriteAccountClient(cookies=secret)
|
||||
aw.logout_current() # best effort
|
||||
except Exception:
|
||||
pass
|
||||
session.clear()
|
||||
logout_user()
|
||||
flash("Signed out.", "success")
|
||||
return redirect(url_for("auth.login"))
|
||||
|
||||
@auth_bp.route("/send", methods=["POST"])
|
||||
@login_required
|
||||
def send():
|
||||
"""
|
||||
Sends a verification email to the currently logged-in user.
|
||||
Appwrite will redirect the user back to /verify/callback with userId & secret.
|
||||
"""
|
||||
try:
|
||||
aw = get_client_from_session()
|
||||
callback = url_for("auth.callback", _external=True) # Must be allowed in Appwrite -> Platforms
|
||||
aw.send_verification(callback_url=callback)
|
||||
flash("Verification email sent. Please check your inbox.", "info")
|
||||
except Exception as e:
|
||||
flash(f"Could not send verification email: {e}", "error")
|
||||
# Go back to where the user came from, or your dashboard
|
||||
return redirect(request.referrer or url_for("main.dashboard"))
|
||||
|
||||
@auth_bp.route("/callback", methods=["GET"])
|
||||
def callback():
|
||||
"""
|
||||
Completes verification after user clicks the email link.
|
||||
Requires the user to be logged in (Appwrite Account endpoints need a session).
|
||||
If not logged in, we stash the link params and send them to log in first.
|
||||
"""
|
||||
user_id = request.args.get("userId")
|
||||
secret = request.args.get("secret")
|
||||
if not user_id or not secret:
|
||||
flash("Invalid verification link.", "error")
|
||||
return redirect(url_for("auth.login"))
|
||||
|
||||
# If we don't currently have an Appwrite session, ask them to log in, then resume.
|
||||
if not session.get("appwrite_cookies"):
|
||||
session["pending_verification"] = {"userId": user_id, "secret": secret}
|
||||
flash("Please log in to complete email verification.", "warning")
|
||||
return redirect(url_for("auth.login"))
|
||||
|
||||
# We have a session; complete verification
|
||||
try:
|
||||
aw = get_client_from_session()
|
||||
aw.complete_verification(user_id=user_id, secret=secret)
|
||||
# Refresh cached profile so templates reflect emailVerification=True
|
||||
profile = aw.get_account()
|
||||
session["user_profile"] = profile
|
||||
# Cleanup any pending state
|
||||
session.pop("pending_verification", None)
|
||||
flash("Email verified! You're all set.", "success")
|
||||
return redirect(url_for("main.dashboard"))
|
||||
except Exception as e:
|
||||
flash(f"Verification failed: {e}", "error")
|
||||
return redirect(url_for("auth.login"))
|
||||
Reference in New Issue
Block a user