diff --git a/app/__init__.py b/app/__init__.py index 9bd918e..ba3f0d3 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,15 +1,22 @@ import os from flask import Flask, redirect, url_for, request, g, session, flash -from .blueprints.auth.routes import auth_bp -from .blueprints.main.routes import main_bp -from .blueprints.public.routes import public_bp + +# import blueprints +from app.blueprints.auth import auth_bp +from app.blueprints.main import main_bp +from app.blueprints.char import char_bp +from app.blueprints.public import public_bp +from app.blueprints.ajax import ajax_bp # load_dotenv() from .utils.settings import get_settings +from app.utils.logging import get_logger from .utils.session_user import SessionUser +logger = get_logger() settings = get_settings() + def create_app(): app = Flask(__name__, template_folder="templates") app.config.update( @@ -25,7 +32,9 @@ def create_app(): # Blueprints app.register_blueprint(auth_bp) app.register_blueprint(main_bp) + app.register_blueprint(char_bp) app.register_blueprint(public_bp) + app.register_blueprint(ajax_bp) @app.before_request def require_login(): @@ -68,7 +77,6 @@ def create_app(): @app.before_request def load_user(): user_data = session.get("user") - print(user_data) if user_data: g.current_user = SessionUser( diff --git a/app/blueprints/auth/routes.py b/app/blueprints/auth/routes.py deleted file mode 100644 index 131e0a2..0000000 --- a/app/blueprints/auth/routes.py +++ /dev/null @@ -1,113 +0,0 @@ -# app/auth/routes.py -from flask import Blueprint, render_template, request, redirect, url_for, flash, session,make_response -from flask_login import login_user, logout_user, login_required - -from app.services.appwrite_client import AppWriteClient - - -auth_bp = Blueprint("auth", __name__, url_prefix="/auth") - - -@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: - aw = AppWriteClient() - aw.create_new_user(email,password,name) - - login_valid, error = aw.log_user_in(email,password) - if login_valid: - flash("Account created and you are now logged in.", "success") - return redirect(url_for("main.dashboard")) - else: - flash(str(error), "error") - 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")) - - aw = AppWriteClient() - login_valid, error = aw.log_user_in(email,password) - try: - if login_valid: - username = session.get("user",{}).get("name","User") - flash(f"Welcome Back {username}", "success") - return redirect(url_for("main.dashboard")) - else: - flash(str(error), "error") - 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"]) -def logout(): - aw = AppWriteClient() - aw.log_user_out() - session.clear() - flash("Signed out.", "success") - return redirect(url_for("auth.login")) - -@auth_bp.route("/send", methods=["POST"]) -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 = AppWriteClient() - aw.send_email_verification() - 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. - """ - aw = AppWriteClient() - 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")) - - try: - # If we don't currently have an Appwrite session, ask them to log in, then resume. - if not aw.verify_email(user_id,secret): - 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 - 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")) \ No newline at end of file diff --git a/app/blueprints/main/routes.py b/app/blueprints/main/routes.py deleted file mode 100644 index 98809a1..0000000 --- a/app/blueprints/main/routes.py +++ /dev/null @@ -1,10 +0,0 @@ -from flask import Blueprint, redirect, url_for, render_template, session,flash -from app.services.appwrite_client import AppWriteClient - -aw = AppWriteClient() -main_bp = Blueprint("main", __name__, url_prefix="/main") - - -@main_bp.route("/dashboard") -def dashboard(): - return render_template("main/dashboard.html", profile="", jwt_info="") diff --git a/app/blueprints/public/routes.py b/app/blueprints/public/routes.py deleted file mode 100644 index 1cb9689..0000000 --- a/app/blueprints/public/routes.py +++ /dev/null @@ -1,10 +0,0 @@ -from flask import Blueprint, redirect, url_for, render_template, session,flash -from app.services.appwrite_client import AppWriteClient - - -public_bp = Blueprint("public", __name__, url_prefix="/") - - -@public_bp.route("/") -def home(): - return render_template("public/home.html") \ No newline at end of file diff --git a/app/services/appwrite_client.py b/app/services/appwrite_client.py index cf14fe5..18e30a0 100644 --- a/app/services/appwrite_client.py +++ b/app/services/appwrite_client.py @@ -3,7 +3,7 @@ from __future__ import annotations import os from typing import Optional, Dict, Any, Mapping, Union, List -from flask import session, redirect, url_for +from flask import session, redirect, url_for, request from appwrite.client import Client from appwrite.services.account import Account from appwrite.id import ID @@ -60,6 +60,7 @@ class AppWriteClient: client = (Client() .set_endpoint(ENDPOINT) .set_project(PROJECT_ID) + .set_forwarded_user_agent(request.headers.get('user-agent')) ) if session[self.session_key] is not None: @@ -82,6 +83,25 @@ class AppWriteClient: user = user_account.get() session['user']=user + def get_user_from_jwt_token(self, jwt_token:str): + try: + client = (Client() + .set_endpoint(ENDPOINT) + .set_project(PROJECT_ID) + .set_jwt(jwt_token) + ) + return Account(client).get() + except Exception as e: + return {} + + def mint_jwt(self): + try: + client = self._get_user_client() + account = Account(client) + return account.create_jwt() + except Exception as e: + return "" + def log_user_in(self, email:str,password:str): admin_client = self._get_admin_client() try: diff --git a/app/templates/bases/login_base.html b/app/templates/bases/login_base.html index 617642c..25ebc9a 100644 --- a/app/templates/bases/login_base.html +++ b/app/templates/bases/login_base.html @@ -29,11 +29,10 @@
v 0.1.0
- - + {% include "_flash_sticky.html" %} {% block scripts %}{% endblock %}