98 lines
2.9 KiB
Python
98 lines
2.9 KiB
Python
# === FILE: app/auth.py ===
|
|
from functools import wraps
|
|
from flask import Blueprint, session, redirect, url_for, request, flash
|
|
from authlib.integrations.flask_client import OAuth
|
|
from app.config import Config
|
|
from app import db
|
|
|
|
|
|
auth_bp = Blueprint('auth', __name__, url_prefix='/auth')
|
|
|
|
# OAuth client will be initialized in __init__.py
|
|
oauth = None
|
|
|
|
|
|
def init_oauth(app):
|
|
"""Initialize OAuth with the Flask app."""
|
|
global oauth
|
|
oauth = OAuth(app)
|
|
oauth.register(
|
|
name='google',
|
|
client_id=Config.GOOGLE_CLIENT_ID,
|
|
client_secret=Config.GOOGLE_CLIENT_SECRET,
|
|
server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
|
|
client_kwargs={
|
|
'scope': 'openid email profile'
|
|
}
|
|
)
|
|
|
|
|
|
def login_required(f):
|
|
"""Decorator to protect routes that require authentication."""
|
|
@wraps(f)
|
|
def decorated_function(*args, **kwargs):
|
|
if 'user' not in session:
|
|
flash('Please log in to access this page.', 'error')
|
|
return redirect(url_for('auth.login'))
|
|
return f(*args, **kwargs)
|
|
return decorated_function
|
|
|
|
|
|
@auth_bp.route('/login')
|
|
def login():
|
|
"""Redirect to Google OAuth login page."""
|
|
redirect_uri = Config.GOOGLE_REDIRECT_URI
|
|
return oauth.google.authorize_redirect(redirect_uri)
|
|
|
|
|
|
@auth_bp.route('/callback')
|
|
def callback():
|
|
"""Handle Google OAuth callback."""
|
|
try:
|
|
# Exchange authorization code for access token
|
|
token = oauth.google.authorize_access_token()
|
|
|
|
# Get user info from Google
|
|
userinfo = token.get('userinfo')
|
|
|
|
if not userinfo:
|
|
flash('Failed to get user information from Google.', 'error')
|
|
return redirect(url_for('auth.login'))
|
|
|
|
# Extract user data
|
|
google_id = userinfo.get('sub')
|
|
email = userinfo.get('email')
|
|
name = userinfo.get('name')
|
|
profile_picture = userinfo.get('picture')
|
|
|
|
# Get or create user in database
|
|
user = db.get_or_create_user(google_id, email, name, profile_picture)
|
|
|
|
if not user:
|
|
flash('Failed to create user account.', 'error')
|
|
return redirect(url_for('auth.login'))
|
|
|
|
# Store user in session
|
|
session['user'] = {
|
|
'id': user['id'],
|
|
'email': user['email'],
|
|
'name': user['name'],
|
|
'profile_picture': user['profile_picture']
|
|
}
|
|
|
|
flash(f'Welcome back, {user["name"]}!', 'success')
|
|
return redirect(url_for('files.dashboard'))
|
|
|
|
except Exception as e:
|
|
print(f"Error during OAuth callback: {e}")
|
|
flash('An error occurred during login. Please try again.', 'error')
|
|
return redirect(url_for('auth.login'))
|
|
|
|
|
|
@auth_bp.route('/logout')
|
|
def logout():
|
|
"""Log out the current user."""
|
|
session.clear()
|
|
flash('You have been logged out successfully.', 'success')
|
|
return redirect(url_for('auth.login'))
|