- Added comprehensive README files for all three sync modules - Implemented advanced logging system with multiple log levels (DEBUG, INFO, WARNING, ERROR) - Added automatic sensitive data masking for security in log payloads - Implemented log retention policy (90 days local, 7 years in AWS S3 Glacier) - Added AWS S3 integration for long-term log archiving - Fixed validation error with bemade_instance_id in sync model creation - Refactored model inheritance structure from _inherit to _inherits for proper delegation - Fixed duplicate sync model prevention logic - Restored Test Connection button in instance view - Fixed connection test logging to properly record success/failure - Fixed queue creation for connection test logs - Removed unnecessary Synchronized Module tab from odoo_to_odoo_bemade - Added database indexing on create_date for performance optimization - Fixed foreign key constraint violations in field mappings creation - Enhanced error handling throughout the synchronization process
170 lines
6 KiB
Python
170 lines
6 KiB
Python
# Copyright 2025 Bemade
|
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html)
|
|
|
|
"""Client Validation Controller.
|
|
|
|
This controller handles XML-RPC requests from client instances for
|
|
validating API tokens and establishing connections.
|
|
"""
|
|
|
|
import logging
|
|
|
|
from odoo import http
|
|
from odoo.http import request
|
|
from odoo.exceptions import AccessDenied
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ClientValidationController(http.Controller):
|
|
"""Controller for handling client validation requests."""
|
|
|
|
def _validate_client(self, client_key):
|
|
"""Validate a client connection using the client key.
|
|
|
|
Args:
|
|
client_key (str): The client key to validate
|
|
|
|
Returns:
|
|
bool: True if the client is valid, False otherwise
|
|
"""
|
|
# Find the project with this client key
|
|
project = request.env['project.project'].sudo().search([
|
|
('client_key', '=', client_key)
|
|
], limit=1)
|
|
|
|
if not project:
|
|
_logger.warning(f"Client validation failed: No project found with client key {client_key}")
|
|
return False
|
|
|
|
if not project.is_client_project:
|
|
_logger.warning(f"Client validation failed: Project {project.id} is not marked as client project")
|
|
return False
|
|
|
|
# Create or update the client instance
|
|
instance_vals = {
|
|
'name': f"Client {client_key}",
|
|
'url': request.httprequest.remote_addr,
|
|
'connection_type': 'xmlrpc',
|
|
}
|
|
|
|
if project.client_instance_id:
|
|
project.client_instance_id.sudo().write(instance_vals)
|
|
else:
|
|
instance = request.env['odoo.to.bemade.instance'].sudo().create(instance_vals)
|
|
project.sudo().write({'client_instance_id': instance.id})
|
|
|
|
_logger.info(f"Client validation successful for project {project.id}")
|
|
return True
|
|
|
|
def _authenticate_client(self, client_key, api_token):
|
|
"""Authenticate a client using client key and API token.
|
|
|
|
Args:
|
|
client_key (str): The client key
|
|
api_token (str): The API token
|
|
|
|
Returns:
|
|
dict: Authentication result with company info and models
|
|
"""
|
|
# Find the project with this client key
|
|
project = request.env['project.project'].sudo().search([
|
|
('client_key', '=', client_key),
|
|
('client_api_token', '=', api_token)
|
|
], limit=1)
|
|
|
|
if not project:
|
|
_logger.warning(f"Client authentication failed: Invalid credentials for client key {client_key}")
|
|
return {
|
|
'success': False,
|
|
'error': 'Invalid client key or API token'
|
|
}
|
|
|
|
if not project.is_client_project:
|
|
_logger.warning(f"Client authentication failed: Project {project.id} is not marked as client project")
|
|
return {
|
|
'success': False,
|
|
'error': 'Project is not configured as client project'
|
|
}
|
|
|
|
# Get company information
|
|
company = request.env.user.company_id
|
|
|
|
# Get available sync models for this project
|
|
models = []
|
|
for model in project.sync_model_ids:
|
|
models.append({
|
|
'model': model.model_id.model,
|
|
'target_model': model.target_model,
|
|
'field_mapping': model.field_mapping,
|
|
'domain': model.sync_domain,
|
|
})
|
|
|
|
result = {
|
|
'success': True,
|
|
'company_name': company.name,
|
|
'models': models
|
|
}
|
|
|
|
_logger.info(f"Client authentication successful for project {project.id}")
|
|
return result
|
|
try:
|
|
# Find the project with the matching API token
|
|
project = request.env['project.project'].sudo().search([
|
|
('client_api_token', '=', api_key),
|
|
('is_client_project', '=', True)
|
|
], limit=1)
|
|
|
|
if not project:
|
|
return {
|
|
'success': False,
|
|
'message': 'Clé API invalide'
|
|
}
|
|
|
|
|
|
return {
|
|
'success': True,
|
|
'company_name': project.company_id.name if project.company_id else project.name,
|
|
'models': model_data
|
|
}
|
|
|
|
except Exception as e:
|
|
_logger.error("Erreur de validation client: %s", str(e))
|
|
return {
|
|
'success': False,
|
|
'message': 'Erreur de validation'
|
|
}
|
|
|
|
def _authenticate_client(self, client_key, api_key, instance_id):
|
|
"""Authenticate client and return user ID.
|
|
|
|
Args:
|
|
client_key (str): The client key provided by the user
|
|
api_key (str): The API key provided by the user
|
|
instance_id (str): The unique instance ID of the client
|
|
|
|
Returns:
|
|
int or False: User ID if authentication successful, False otherwise
|
|
"""
|
|
try:
|
|
# Find the project with the matching API token
|
|
project = request.env['project.project'].sudo().search([
|
|
('client_api_token', '=', api_key),
|
|
('is_client_project', '=', True)
|
|
], limit=1)
|
|
|
|
if not project:
|
|
return False
|
|
|
|
# Check if the client key matches
|
|
# For now, we'll use the project ID as the client key
|
|
if str(project.id) != client_key:
|
|
return False
|
|
|
|
# Return a valid user ID for synchronization
|
|
# In a real implementation, this would be a specific sync user
|
|
return request.env.ref('base.user_admin').id
|
|
|
|
except Exception as e:
|
|
_logger.error("Erreur d'authentification client: %s", str(e))
|
|
return False
|