|
from flask import Blueprint, request, jsonify, current_app |
|
from flask_jwt_extended import jwt_required, get_jwt_identity |
|
from backend.services.linkedin_service import LinkedInService |
|
import secrets |
|
|
|
accounts_bp = Blueprint('accounts', __name__) |
|
|
|
@accounts_bp.route('/', methods=['OPTIONS']) |
|
@accounts_bp.route('', methods=['OPTIONS']) |
|
def handle_options(): |
|
"""Handle OPTIONS requests for preflight CORS checks.""" |
|
return '', 200 |
|
|
|
@accounts_bp.route('/', methods=['GET']) |
|
@accounts_bp.route('', methods=['GET']) |
|
@jwt_required() |
|
def get_accounts(): |
|
""" |
|
Get all social media accounts for the current user. |
|
|
|
Returns: |
|
JSON: List of social media accounts |
|
""" |
|
try: |
|
user_id = get_jwt_identity() |
|
|
|
|
|
if not hasattr(current_app, 'supabase') or current_app.supabase is None: |
|
|
|
response_data = jsonify({ |
|
'success': False, |
|
'message': 'Database connection not initialized' |
|
}) |
|
response_data.headers.add('Access-Control-Allow-Origin', 'http://localhost:3000') |
|
response_data.headers.add('Access-Control-Allow-Credentials', 'true') |
|
return response_data, 500 |
|
|
|
|
|
response = ( |
|
current_app.supabase |
|
.table("Social_network") |
|
.select("*") |
|
.eq("id_utilisateur", user_id) |
|
.execute() |
|
) |
|
|
|
accounts = response.data if response.data else [] |
|
|
|
|
|
response_data = jsonify({ |
|
'success': True, |
|
'accounts': accounts |
|
}) |
|
response_data.headers.add('Access-Control-Allow-Origin', 'http://localhost:3000') |
|
response_data.headers.add('Access-Control-Allow-Credentials', 'true') |
|
return response_data, 200 |
|
|
|
except Exception as e: |
|
current_app.logger.error(f"Get accounts error: {str(e)}") |
|
|
|
response_data = jsonify({ |
|
'success': False, |
|
'message': 'An error occurred while fetching accounts' |
|
}) |
|
response_data.headers.add('Access-Control-Allow-Origin', 'http://localhost:3000') |
|
response_data.headers.add('Access-Control-Allow-Credentials', 'true') |
|
return response_data, 500 |
|
|
|
@accounts_bp.route('/', methods=['POST']) |
|
@accounts_bp.route('', methods=['POST']) |
|
@jwt_required() |
|
def add_account(): |
|
""" |
|
Add a new social media account for the current user. |
|
|
|
Request Body: |
|
account_name (str): Account name |
|
social_network (str): Social network name |
|
|
|
Returns: |
|
JSON: Add account result |
|
""" |
|
try: |
|
user_id = get_jwt_identity() |
|
data = request.get_json() |
|
|
|
|
|
if not data or not all(k in data for k in ('account_name', 'social_network')): |
|
return jsonify({ |
|
'success': False, |
|
'message': 'Account name and social network are required' |
|
}), 400 |
|
|
|
account_name = data['account_name'] |
|
social_network = data['social_network'] |
|
|
|
|
|
if social_network.lower() == 'linkedin': |
|
linkedin_service = LinkedInService() |
|
|
|
state = secrets.token_urlsafe(32) |
|
|
|
|
|
|
|
authorization_url = linkedin_service.get_authorization_url(state) |
|
|
|
return jsonify({ |
|
'success': True, |
|
'message': 'Please authenticate with LinkedIn', |
|
'authorization_url': authorization_url, |
|
'state': state |
|
}), 200 |
|
else: |
|
return jsonify({ |
|
'success': False, |
|
'message': 'Unsupported social network' |
|
}), 400 |
|
|
|
except Exception as e: |
|
current_app.logger.error(f"Add account error: {str(e)}") |
|
return jsonify({ |
|
'success': False, |
|
'message': f'An error occurred while adding account: {str(e)}' |
|
}), 500 |
|
|
|
@accounts_bp.route('/callback', methods=['POST']) |
|
@jwt_required() |
|
def handle_oauth_callback(): |
|
""" |
|
Handle OAuth callback from social network. |
|
|
|
Request Body: |
|
code (str): Authorization code |
|
state (str): State parameter |
|
social_network (str): Social network name |
|
|
|
Returns: |
|
JSON: OAuth callback result |
|
""" |
|
try: |
|
user_id = get_jwt_identity() |
|
data = request.get_json() |
|
|
|
|
|
if not data or not all(k in data for k in ('code', 'state', 'social_network')): |
|
return jsonify({ |
|
'success': False, |
|
'message': 'Code, state, and social network are required' |
|
}), 400 |
|
|
|
code = data['code'] |
|
state = data['state'] |
|
social_network = data['social_network'] |
|
|
|
|
|
|
|
|
|
if social_network.lower() == 'linkedin': |
|
linkedin_service = LinkedInService() |
|
|
|
|
|
token_response = linkedin_service.get_access_token(code) |
|
access_token = token_response['access_token'] |
|
|
|
|
|
user_info = linkedin_service.get_user_info(access_token) |
|
|
|
|
|
response = ( |
|
current_app.supabase |
|
.table("Social_network") |
|
.insert({ |
|
"social_network": social_network, |
|
"account_name": user_info.get('name', 'LinkedIn Account'), |
|
"id_utilisateur": user_id, |
|
"token": access_token, |
|
"sub": user_info.get('sub'), |
|
"given_name": user_info.get('given_name'), |
|
"family_name": user_info.get('family_name'), |
|
"picture": user_info.get('picture') |
|
}) |
|
.execute() |
|
) |
|
|
|
if response.data: |
|
return jsonify({ |
|
'success': True, |
|
'message': 'Account linked successfully', |
|
'account': response.data[0] |
|
}), 200 |
|
else: |
|
return jsonify({ |
|
'success': False, |
|
'message': 'Failed to link account' |
|
}), 500 |
|
else: |
|
return jsonify({ |
|
'success': False, |
|
'message': 'Unsupported social network' |
|
}), 400 |
|
|
|
except Exception as e: |
|
current_app.logger.error(f"OAuth callback error: {str(e)}") |
|
return jsonify({ |
|
'success': False, |
|
'message': f'An error occurred during OAuth callback: {str(e)}' |
|
}), 500 |
|
|
|
@accounts_bp.route('/<account_id>', methods=['OPTIONS']) |
|
def handle_account_options(account_id): |
|
"""Handle OPTIONS requests for preflight CORS checks for specific account.""" |
|
return '', 200 |
|
|
|
@accounts_bp.route('/<account_id>', methods=['DELETE']) |
|
@jwt_required() |
|
def delete_account(account_id): |
|
""" |
|
Delete a social media account. |
|
|
|
Path Parameters: |
|
account_id (str): Account ID |
|
|
|
Returns: |
|
JSON: Delete account result |
|
""" |
|
try: |
|
user_id = get_jwt_identity() |
|
|
|
|
|
response = ( |
|
current_app.supabase |
|
.table("Social_network") |
|
.delete() |
|
.eq("id", account_id) |
|
.eq("id_utilisateur", user_id) |
|
.execute() |
|
) |
|
|
|
if response.data: |
|
return jsonify({ |
|
'success': True, |
|
'message': 'Account deleted successfully' |
|
}), 200 |
|
else: |
|
return jsonify({ |
|
'success': False, |
|
'message': 'Account not found or unauthorized' |
|
}), 404 |
|
|
|
except Exception as e: |
|
current_app.logger.error(f"Delete account error: {str(e)}") |
|
return jsonify({ |
|
'success': False, |
|
'message': 'An error occurred while deleting account' |
|
}), 500 |
|
|
|
@accounts_bp.route('/<account_id>/primary', methods=['OPTIONS']) |
|
def handle_primary_options(account_id): |
|
"""Handle OPTIONS requests for preflight CORS checks for primary account.""" |
|
return '', 200 |
|
|
|
@accounts_bp.route('/<account_id>/primary', methods=['PUT']) |
|
@jwt_required() |
|
def set_primary_account(account_id): |
|
""" |
|
Set an account as primary for the user. |
|
|
|
Path Parameters: |
|
account_id (str): Account ID |
|
|
|
Returns: |
|
JSON: Update result |
|
""" |
|
try: |
|
user_id = get_jwt_identity() |
|
|
|
|
|
response = ( |
|
current_app.supabase |
|
.table("Social_network") |
|
.select("*") |
|
.eq("id_utilisateur", user_id) |
|
.execute() |
|
) |
|
|
|
accounts = response.data if response.data else [] |
|
|
|
|
|
account_exists = any(account['id'] == account_id and account['id_utilisateur'] == user_id for account in accounts) |
|
|
|
if not account_exists: |
|
return jsonify({ |
|
'success': False, |
|
'message': 'Account not found or unauthorized' |
|
}), 404 |
|
|
|
|
|
|
|
|
|
|
|
return jsonify({ |
|
'success': True, |
|
'message': 'Account set as primary successfully' |
|
}), 200 |
|
|
|
except Exception as e: |
|
current_app.logger.error(f"Set primary account error: {str(e)}") |
|
return jsonify({ |
|
'success': False, |
|
'message': 'An error occurred while setting primary account' |
|
}), 500 |