import traceback from flask import request from flask.app import Flask import ldap3 from werkzeug.exceptions import HTTPException from ceo_common.errors import UserNotFoundError, GroupNotFoundError, \ UserAlreadyExistsError, GroupAlreadyExistsError, BadRequest, \ UserAlreadySubscribedError, InvalidMembershipError, \ CloudStackAPIError, InvalidDomainError, InvalidIPError from ceo_common.logger_factory import logger_factory __all__ = ['register_error_handlers'] logger = logger_factory(__name__) def register_error_handlers(app: Flask): """Register error handlers for the application.""" app.register_error_handler(Exception, generic_error_handler) def generic_error_handler(err: Exception): """Return JSON for all errors.""" if isinstance(err, HTTPException): status_code = err.code elif any(isinstance(err, cls) for cls in [ BadRequest, InvalidDomainError, InvalidIPError ]): status_code = 400 elif isinstance(err, ldap3.core.exceptions.LDAPStrongerAuthRequiredResult) \ or isinstance(err, InvalidMembershipError): status_code = 403 elif isinstance(err, UserNotFoundError) or isinstance(err, GroupNotFoundError): status_code = 404 elif any(isinstance(err, cls) for cls in [ UserAlreadyExistsError, GroupAlreadyExistsError, UserAlreadySubscribedError ]): status_code = 409 elif isinstance(err, CloudStackAPIError): status_code = 500 else: status_code = 500 logger.error(traceback.format_exc()) if request.path.startswith('/api/cloud'): # I've noticed that the requests library spits out the # full URL when an Exception is raised, which will cause # our CloudStack API key to be leaked. So we're going to mask # it here instead. err = Exception('Please contact the Systems Committee') return {'error': type(err).__name__ + ': ' + str(err)}, status_code