diff --git a/app/app.py b/app/app.py index e26419c..8ee39ff 100644 --- a/app/app.py +++ b/app/app.py @@ -10,6 +10,122 @@ from config import Config # All comments are in English. +app = Flask(__name__) +app.config.from_object(Config) +app.secret_key = app.config["SECRET_KEY"] + +oauth = OAuth(app) +google = oauth.register( + name="google", + client_id=app.config["GOOGLE_CLIENT_ID"], + client_secret=app.config["GOOGLE_CLIENT_SECRET"], + access_token_url="https://oauth2.googleapis.com/token", + authorize_url="https://accounts.google.com/o/oauth2/v2/auth", + authorize_params={"access_type": "offline", "prompt": "consent"}, + api_base_url="https://www.googleapis.com/oauth2/v2/", + client_kwargs={"scope": "openid email profile"}, +) + + +def login_required(f): + """Decorator to ensure the user is authenticated via Google OAuth.""" + @wraps(f) + def wrapper(*args, **kwargs): + if "user" not in session: + return redirect(url_for("login")) + return f(*args, **kwargs) + return wrapper + + +@app.route("/login") +def login(): + """Start Google OAuth login flow.""" + return google.authorize_redirect(app.config["Google_REDIRECT_URI"]) + + +@app.route("/oauth/callback") +def oauth_callback(): + """Handle Google OAuth callback and store user session.""" + token = google.authorize_access_token() + user_info = google.get("userinfo").json() + + session["user"] = { + "email": user_info.get("email"), + "name": user_info.get("name"), + } + + return redirect(url_for("home")) + + +@app.route("/") +def home(): + return jsonify({ + "message": "Ollama Gateway is running.", + "domain": "https://safira.renatorosa.com", + "auth": "Google OAuth required for /api/* endpoints.", + "endpoints": { + "health": "/health", + "generate": "/api/generate" + } + }) + + +@app.route("/health") +def health(): + return jsonify({"status": "ok"}) + + +@app.route("/api/generate", methods=["POST"]) +@login_required +def generate(): + data = request.get_json(silent=True) or {} + + model_name = data.get("model", "llama3.2") + prompt = data.get("prompt") + + if not prompt: + return jsonify({"error": "Missing 'prompt' field."}), 400 + + model_id = app.config["MODEL_MAP"].get(model_name) + if not model_id: + return jsonify({"error": f"Unsupported model '{model_name}'."}), 400 + + ollama_url = f"{app.config['OLLAMA_BASE_URL']}/api/generate" + payload = {"model": model_id, "prompt": prompt} + + try: + response = requests.post(ollama_url, json=payload, timeout=60) + response.raise_for_status() + except requests.RequestException as e: + return jsonify({"error": "Failed to call Ollama API.", "details": str(e)}), 502 + + try: + ollama_data = response.json() + except json.JSONDecodeError: + return jsonify({"error": "Invalid JSON response from Ollama."}), 502 + + output_text = ollama_data.get("response") or ollama_data.get("output") or "" + + return jsonify({"model": model_name, "output": output_text}) + + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=8000) + +# *** + +import os +import json +import requests +from functools import wraps + +from flask import Flask, request, jsonify, redirect, session, url_for +from authlib.integrations.flask_client import OAuth + +from config import Config + +# All comments are in English. + app = Flask(__name__) app.config.from_object(Config)