Ejemplo n.º 1
0
def get_job(job_id, user):
    job = model.Job.query.get(job_id)
    if not job:
        return problem(404, 'Not Found', f'Job {job_id} does not exist')

    if not user_is_admin(user) and job.launched_by != user:
        return problem(403, 'Forbidden',
                       f"You don't have permissions to view job {job_id}")

    try:
        tower_client = job.server.create_tower_client()

        if job.template.tower_template_is_workflow:
            tower_job_data = tower_client.workflow_job_get(job.tower_job_id)
        else:
            tower_job_data = tower_client.template_job_get(job.tower_job_id)

        return _tower_job(job, tower_job_data) | {'_href': _job_href(job)}

    except TowerError as e:
        logger.exception(f'Failed to get job data from Tower, {e}')
        return problem(e.response.status_code, 'Error',
                       f'Failed to get job {job_id} data from Tower')

    except Exception as e:
        logger.exception(e)
        return problem(500, 'Server Error', f'Unknown server error, {e}')
Ejemplo n.º 2
0
def get_credentials(account_id: str, role_name: str, user: str,
                    token_info: dict):
    current_span = extract_span_from_flask_request()

    uid = user
    realm = token_info['realm']

    if realm != '/employees':
        return connexion.problem(403, 'Forbidden',
                                 'You are not authorized to use this service')
    try:
        groups = get_groups(uid)
    except Exception as e:
        current_span.log_kv({'exception': str(e)})
        logger.exception('Failed to get groups for {}'.format(uid))
        return connexion.problem(500, 'Server Error',
                                 'Failed to get groups: {}'.format(e))

    allowed = False
    for account_role in map(map_group_to_account_role, groups):
        if role_name == account_role[
                'role_name'] and account_id == account_role['account_id']:
            allowed = True
            break
    if not allowed:
        current_span.set_tag('allowed', False)
        return connexion.problem(
            403, 'Forbidden',
            'Access to requested AWS account/role was denied')

    sts = boto3.client('sts')
    arn = ROLE_ARN.format(account_id=account_id, role_name=role_name)
    role_session_name = ROLE_SESSION_NAME_INVALID_CHARS.sub('', uid)

    try:
        role = sts.assume_role(RoleArn=arn, RoleSessionName=role_session_name)
    except Exception as e:
        error_message = 'Failed to assume role: {}'.format(e)
        current_span.log_kv({'exception': str(e), 'role_arn': arn})
        if 'AccessDenied' in error_message:
            # role might not exist in target account
            logger.error(error_message)
            return connexion.problem(403, 'AWS Error', error_message)
        else:
            # something else happened
            current_span.set_tag('error', True)
            logger.exception('Failed to assume role {}'.format(arn))
            return connexion.problem(500, 'AWS Error', error_message)

    credentials = role['Credentials']
    logger.info(
        'Handing out credentials for {account_id}/{role_name} to {uid}'.format(
            account_id=account_id, role_name=role_name, uid=uid))

    return {
        'access_key_id': credentials['AccessKeyId'],
        'secret_access_key': credentials['SecretAccessKey'],
        'session_token': credentials['SessionToken'],
        'expiration': credentials['Expiration']
    }
Ejemplo n.º 3
0
def post_items(body: dict):

    # connexion cannot validate this kind of entries
    try:
        bson.encode(body)
    except bson.InvalidDocument as e:
        return problem(status=422,
                       title="Unprocessable Entity",
                       detail=e.args[0])
    except OverflowError as e:
        return problem(status=422,
                       title="Unprocessable Entity",
                       detail=e.args[0])

    uuid = str(uuid4())
    ts = datetime.now().isoformat()
    current_app.config["store"].add(uuid, dict(id=uuid,
                                               timestamp=ts,
                                               item=body))
    return {
        "id": uuid,
        "timestamp": ts,
        "status": "success",
        "url": request.base_url + "/" + uuid,
        "debug": current_app.config["store"].list(),
    }
Ejemplo n.º 4
0
    def _validating_wrapper(param):
        req_errors = validate_request(param.get('body', {}))
        if req_errors:
            return problem(status=400,
                           title="The request could not be validated.",
                           detail="There is an error in your submitted data.",
                           ext={'errors': req_errors})

        response = func(param)
        if not hasattr(response, 'original_data'):
            return response

        # FIXME
        # We need to get the "original data" somewhere and are currently "piggy-backing"
        # it on the response instance. This is somewhat problematic because it's not
        # expected behaviour and not a valid interface of Response. Needs refactoring.
        errors = validate_response(response.original_data)
        if errors:
            # Hope we never get here in production.
            return problem(
                status=500,
                title="Server was about to send an invalid response.",
                detail="This is an error of the implementation.",
                ext={'errors': errors},
            )
        return response
Ejemplo n.º 5
0
def get_template(template_id):
    template = model.Template.query.get(template_id)
    if not template:
        return problem(404, 'Not Found',
                       f'Template {template_id} does not exist')

    try:
        tower_client = template.server.create_tower_client()

        if template.tower_template_is_workflow:
            tower_survey_data = tower_client.workflow_get_survey(
                template.tower_template_id)
        else:
            tower_survey_data = tower_client.template_get_survey(
                template.tower_template_id)

        return template.to_dict() | {
            'tower_survey': tower_survey_data,
            '_href': _template_href(template),
        }

    except TowerError as e:
        logger.exception(f'Failed to get template data from Tower, {e}')
        return problem(
            e.response.status_code, 'Error',
            f'Failed to get template {template_id} data from Tower')

    except Exception as e:
        logger.exception(e)
        return problem(500, 'Server Error', f'Unknown server error, {e}')
Ejemplo n.º 6
0
def add(product):
    with dbconn() as conn:
        cur = conn.cursor()

        cur.execute(
            '''SELECT * FROM zsm_data.product_group WHERE pg_slug = %s''',
            (product['product_group'], ))
        row = cur.fetchone()
        if not row:
            return connexion.problem(
                status=404,
                title='Product group not found',
                detail='Can not find product group: {}'.format(
                    product['product_group']))

        product_group = strip_column_prefix(row._asdict())

        try:
            cur.execute(
                '''INSERT INTO zsm_data.product (p_name, p_slug, p_product_group_id) VALUES (%s, %s, %s)''',
                (
                    product['name'],
                    slugger(product['name']),
                    product_group['id'],
                ))
            conn.commit()
        except IntegrityError:
            return connexion.problem(
                status=400,
                title='Product Already Exists',
                detail='Product with name: "{}" already exists!'.format(
                    product['name']))
        return NoContent, 201
def delete_member(username):  # noqa: E501
    """Delete member 

    This can only be done by the logged in member. 

    Attention! 
    All information, events and pictures associated with this member will be deleted!  # noqa: E501

    :param username: The name that needs to be deleted
    :type username: str

    :rtype: Success 
    """

    deleteMember = db_session.query(
        dbModels.Member).filter(dbModels.Member.username == username).first()

    if deleteMember is None:
        return connexion.problem(404, "Not Found", "Username not found.",
                                 "Lookup")

    db_session.delete(deleteMember)

    try:
        db_session.commit()
    except:
        db_session.rollback()
        return connexion.problem(500, "Internal Server Error", "Database",
                                 "Database")

    return {"success": True, "Description": "Member has been deleted."}
Ejemplo n.º 8
0
def set_acknowledgement_on_host(params):
    """Acknowledge problems on a specific host."""
    host_name = params['host_name']

    host = Query([Hosts.name, Hosts.state],
                 Hosts.name.equals(host_name)).first(sites.live())
    if host is None:
        return problem(
            status=404,
            title=f'Host {host_name} does not exist.',
            detail='It is not currently monitored.',
        )

    if host.state == 0:
        return problem(status=400,
                       title=f"Host {host_name} does not have a problem.",
                       detail="The state is UP.")

    acknowledge_host_problem(
        sites.live(),
        host_name,
        sticky=bool(params.get('sticky')),
        notify=bool(params.get('notify')),
        persistent=bool(params.get('persistent')),
        user=_user_id(),
        comment=params.get('comment', 'Acknowledged'),
    )
    return http.Response(status=204)
Ejemplo n.º 9
0
def post_jobs(body, user):
    print(body)

    quota = get_user(user)['quota']
    if quota['remaining'] - len(body['jobs']) < 0:
        max_jobs = quota['max_jobs_per_month']
        message = f'Your monthly quota is {max_jobs} jobs. You have {quota["remaining"]} jobs remaining.'
        return problem(400, 'Bad Request', message)

    try:
        validate_jobs(body['jobs'])
    except requests.HTTPError as e:
        print(f'WARN: CMR search failed: {e}')
    except GranuleValidationError as e:
        return problem(400, 'Bad Request', str(e))

    request_time = format_time(datetime.now(timezone.utc))
    table = DYNAMODB_RESOURCE.Table(environ['JOBS_TABLE_NAME'])

    for job in body['jobs']:
        job['job_id'] = str(uuid4())
        job['user_id'] = user
        job['status_code'] = 'PENDING'
        job['request_time'] = request_time
        if not body.get('validate_only'):
            job = convert_floats_to_decimals(job)
            table.put_item(Item=job)

    return body
Ejemplo n.º 10
0
 def wrapper(*args, **kwargs):
     # validate size
     if kwargs["size"] > app.config["PAPI_MAX_SIZE"]:
         return problem( 400, "Bad Request",
             "Value of parameter size= must not be greater than %d"
             % app.config["PAPI_MAX_SIZE"]
         )
     # validate value of sortBy    
     sort_by, _ = split_sortby(kwargs['sortBy'])
     if sort_by.lower() not in [v.lower() for v in ALLOWED_SORT_BY_VALUES]:
         return problem( 400, "Bad Request",
             "Value '{}' of parameter sortBy= is not allowed. Use one of these values: {}".format(
                 kwargs['sortBy'], ", ".join(ALLOWED_SORT_BY_VALUES)))
     # validate filter names (depending on compliance level)
     non_filters = ('size', 'page', 'sortBy', 'body')
     if app.config['PAPI_COMPLIANCE_LEVEL'] == 0:
         for kw in kwargs:
             if kw not in non_filters and not kw.lower() in ALLOWED_FILTERS_CL0:
                 return problem(400, "Bad Request", "'{}' is not a valid filter for compliance level 0".format(kw))
     else: # compliance level > 0
         allowed_filters = ALLOWED_FILTERS_CL0 + ALLOWED_EXTRA_FILTERS
         for kw in kwargs:
             if kw not in non_filters and not kw.lower() in allowed_filters:
                 return problem(400, "Bad Request", 
                     "'{}' is not a valid filter for compliance level {}".format(kw, app.config['PAPI_COMPLIANCE_LEVEL']))
     return func(*args, **kwargs)
Ejemplo n.º 11
0
def delete_region(keycloak: KeycloakClient, region_id, user):
    region = model.Region.query.get(region_id)
    if not region:
        return problem(404, 'Not Found', f'Region {region_id} does not exist')

    if not keycloak.user_check_role(user, ADMIN_ROLE):
        if not keycloak.user_check_group(user, region.owner_group):
            raise Forbidden("You don't have write access to this region.")

    q = model.RegionProduct.query.filter(
        model.RegionProduct.region_id == region.id, )
    if q.count() > 0:
        for relation in q.all():
            db.session.delete(relation)
        db.session.flush()

    db.session.delete(region)

    try:
        owner_group = keycloak.group_get(region.owner_group)
        keycloak.group_delete(owner_group['id'])
        logger.info(f'Deleted owners group {owner_group["id"]}')

    except KeycloakGetError as e:
        logger.exception(e)
        return problem_from_keycloak_error(e)
    except Exception as e:
        logger.exception(e)
        return problem(500, 'Unknown Error',
                       f'Failed to delete owner group in Keycloak, {e}')

    db.session.commit()
    logger.info(
        f'Region {region.name} (id {region.id}) deleted by user {user}')
Ejemplo n.º 12
0
def bouncer(endpoint, *args, **kwargs):
    """
    Checks if the user making request is in the predefined list of
    allowed users or match the defined username parttern.
    """
    config = Configuration()

    if not hasattr(connexion.request, "user"):
        logger.debug("User not found in the request", extra={"allowed_users": config.allowed_users})
        return connexion.problem(403, "Forbidden", "Anonymous access is not allowed " "in this endpoint")

    if config.allowed_users is not None:
        logger.debug(
            "Checking if user is allowed", extra={"user": connexion.request.user, "allowed_users": config.allowed_users}
        )
        if connexion.request.user not in config.allowed_users:
            return connexion.problem(403, "Forbidden", "User is not allowed to access " "this endpoint")

    if config.allowed_user_pattern is not None:
        logger.debug(
            "Checking if user pattern is allowed",
            extra={"user": connexion.request.user, "allowed_user_pattern": config.allowed_user_pattern},
        )
        if re.match(config.allowed_user_pattern, connexion.request.user) is None:
            return connexion.problem(403, "Forbidden", "User is not allowed to access " "this endpoint")

    return endpoint(*args, **kwargs)
Ejemplo n.º 13
0
def create_source(body):
    # TODO: metadata enrichment if not set?
    if app.config["PAPI_COMPLIANCE_LEVEL"] < 2:
        return problem(
            501,
            "Not implemented",
            "Compliance level {} does not allow PUT requests.".format(
                app.config["PAPI_COMPLIANCE_LEVEL"]
            ),
        )
    connector = get_connector()
    # it seems that connexion converts '@id' to 'id'??
    # to make thing consistent for further processing, we revert this
    body = fix_ids(body)
    #if not '@id' in body and 'id' in body:
    #    body['@id'] = body['id']

    # This should be handled by spec!
    #if '@id' in body and not is_valid_id(body['@id']):
    #    return problem(400, "Bad Request", 'Illegal character in id')

    try:
        data = connector.create(body)
        return data
    except CreationException as err:
        return problem( 409, "Conflict", str(err))
Ejemplo n.º 14
0
        def wrapped(*args, **kwargs):
            api_key = request.headers.get("X-Phabricator-API-Key")

            if api_key is None and not self.optional:
                return problem(
                    401,
                    "X-Phabricator-API-Key Required",
                    ("Phabricator api key not provided in "
                     "X-Phabricator-API-Key header"),
                    type=
                    "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401",
                )

            g.phabricator = PhabricatorClient(
                current_app.config["PHABRICATOR_URL"],
                api_key
                or current_app.config["PHABRICATOR_UNPRIVILEGED_API_KEY"],
            )
            if api_key is not None and not g.phabricator.verify_api_token():
                return problem(
                    403,
                    "X-Phabricator-API-Key Invalid",
                    "Phabricator api key is not valid",
                    type=
                    "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403",
                )

            return f(*args, **kwargs)
Ejemplo n.º 15
0
def _SubscriptionConfirmation(  snsMessage):
	#logger.debug( snsMessage)

	if not 'SubscribeURL' in snsMessage:
			return connexion.problem( 400, "Subscription error", "No subscription URL was provided")
	
	subUrl = snsMessage[ 'SubscribeURL']

	'''
	Check subUrl is an URL
	^http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+
	Long live regex101!!! :)
	'''
	if not re.match( '^http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', subUrl):
		logger.error ( 'SubscribeURL is not an URL')
		return connexion.problem( 400, "Subscription error", "'%s' is not a valid SubscribeURL" % subUrl)

	try:
		r = requests.get( subUrl)
	except:
		logger.error( 'Unable to fetch: ' + subUrl)
		return connexion.problem( 404, "Subscription error", "Unable to fetch: '%s'" % subUrl)

	logger.debug( 'And got... %s' % r)
	return connexion.problem( 200, "Subscription success", "Subscription done.")
Ejemplo n.º 16
0
def get_consent(taxCode, callback_url, consent, accept=False):
    user_data = _get_user_data(taxCode)
    if not user_data:
        return problem(title="User Not Found",
                       status=404,
                       detail="Missing user")

    if not accept:
        token = validate_token(consent,
                               valid=False,
                               audience=app.config["entityId"])
        return problem(
            title="OK",
            status=200,
            detail="Do you want to give access to %r for the following jwt" %
            token["iss"],
            ext={
                "_link": [{
                    "url": request.url + "&accept=yes"
                }],
                "callback_url": callback_url,
                "token": token,
            },
        )

    user_data["consent"] = time()

    return problem(
        title="Redirecting to consent",
        status=302,
        detail="Redirecto to POST",
        headers={"Location": callback_url},
    )
    raise NotImplementedError
Ejemplo n.º 17
0
def post(h5p_data: dict):
    """ The POST method for the H5P REST API. It offers client-side H5P exercises for download as ZIP archives. """
    h5p_form: H5PForm = H5PForm.from_dict(h5p_data)
    language: Language = determine_language(h5p_form.lang)
    exercise: Exercise = DatabaseService.query(
        Exercise, filter_by=dict(eid=h5p_form.eid), first=True)
    if not exercise:
        return connexion.problem(404, Config.ERROR_TITLE_NOT_FOUND,
                                 Config.ERROR_MESSAGE_EXERCISE_NOT_FOUND)
    text_field_content: str = get_text_field_content(exercise,
                                                     h5p_form.solution_indices)
    if not text_field_content:
        return connexion.problem(422, Config.ERROR_TITLE_UNPROCESSABLE_ENTITY,
                                 Config.ERROR_MESSAGE_UNPROCESSABLE_ENTITY)
    response_dict: dict = TextService.json_template_mark_words
    response_dict = get_response(response_dict, language,
                                 TextService.json_template_drag_text, exercise,
                                 text_field_content,
                                 TextService.feedback_template)
    file_name_no_ext: str = str(h5p_form.exercise_type_path)
    file_name: str = f"{file_name_no_ext}.{FileType.ZIP}"
    target_dir: str = Config.TMP_DIRECTORY
    make_h5p_archive(file_name_no_ext, response_dict, target_dir, file_name)
    return send_from_directory(target_dir,
                               file_name,
                               mimetype=MimeType.zip.value,
                               as_attachment=True)
Ejemplo n.º 18
0
def land(data, api_key=None):
    """ API endpoint at /revisions/{id}/transplants to land revision. """
    # get revision_id from body
    revision_id = data['revision_id']
    try:
        landing = Landing.create(revision_id, api_key)
    except RevisionNotFoundException:
        # We could not find a matching revision.
        return problem(
            404,
            'Revision not found',
            'The requested revision does not exist',
            type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404'
        )
    except LandingNotCreatedException:
        # We could not find a matching revision.
        return problem(
            502,
            'Landing not created',
            'The requested revision does exist, but landing failed.'
            'Please retry your request at a later time.',
            type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502'
        )

    return {'id': landing.id}, 202
Ejemplo n.º 19
0
def add_region_product(keycloak: KeycloakClient, region_id, body, user):
    region = model.Region.query.get(region_id)
    if not region:
        return problem(404, 'Not Found', f'Region {region_id} does not exist')

    if not keycloak.user_check_role(user, ADMIN_ROLE):
        if not keycloak.user_check_group(user, region.owner_group):
            raise Forbidden("You don't have write access to this region.")

    product = model.Product.query.get(body['id'])
    if not product:
        return problem(404, 'Not Found',
                       f'Product {body["id"]} does not exist')

    q = model.RegionProduct.query.filter(
        sqlalchemy.and_(
            model.RegionProduct.region_id == region.id,
            model.RegionProduct.product_id == product.id,
        ))
    if q.count() == 0:
        relation = model.RegionProduct(
            region_id=region.id,
            product_id=product.id,
            enabled=body.get('enabled', True),
        )
        db.session.add(relation)
        db.session.commit()
        logger.info(
            f'Added Product {product.name} (id {product.id}) to Region {region.name} '
            f'(id {region.id}) by user {user}')
    elif 'enabled' in body:
        for relation in q.all():
            relation.enabled = body['enabled']
        db.session.commit()
Ejemplo n.º 20
0
def get_status():
    """Ritorna lo stato dell'applicazione.

    Ritorna lo stato dell'applicazione.  # noqa: E501


    :rtype: Problem
    """
    @after_this_request
    def cache_no_store(response):
        """Add the 'no-store' cache value to avoid clients and
        intermediaries to store this response.
        """
        response.headers["Cache-Control"] = "no-store"
        return response

    if current_app.config["store"].ping():
        return problem(
            status=200,
            title="Success",
            detail="Il servizio funziona correttamente",
            ext={"result": "ok"},
        )

    return problem(
        status=503,
        title="Service Unavailable",
        detail="Questo errore viene ritornato randomicamente.",
        headers={"Retry-After": "1"},
    )
Ejemplo n.º 21
0
def common_error_handler(exception: BaseException) -> flask.Response:
    """Used to capture connexion exceptions and add link to the type field."""
    if isinstance(exception, ProblemException):

        link = EXCEPTIONS_LINK_MAP.get(exception.status)
        if link:
            response = problem(
                status=exception.status,
                title=exception.title,
                detail=exception.detail,
                type=link,
                instance=exception.instance,
                headers=exception.headers,
                ext=exception.ext,
            )
        else:
            response = problem(
                status=exception.status,
                title=exception.title,
                detail=exception.detail,
                type=exception.type,
                instance=exception.instance,
                headers=exception.headers,
                ext=exception.ext,
            )
    else:
        if not isinstance(exception, werkzeug.exceptions.HTTPException):
            exception = werkzeug.exceptions.InternalServerError()

        response = problem(title=exception.name,
                           detail=exception.description,
                           status=exception.code)

    return FlaskApi.get_response(response)
Ejemplo n.º 22
0
def update_region(keycloak: KeycloakClient, vault: Vault, region_id, body,
                  user):
    region = model.Region.query.get(region_id)
    if not region:
        return problem(404, 'Not Found', f'Region {region_id} does not exist')

    if not keycloak.user_check_role(user, ADMIN_ROLE):
        if not keycloak.user_check_group(user, region.owner_group):
            raise Forbidden("You don't have write access to this region.")

    try:
        if body.get('users_group'):
            keycloak.group_get(body['users_group'])
    except KeycloakGetError as e:
        logger.exception(e)
        return problem(
            400, 'Users group does not exist',
            f'Users group {body["users_group"]} does not exist in Keycloak, '
            'you have to create group first or use existing group.')

    if 'quota' in body:
        if body['quota']:
            if region.quota is None:
                region.quota = model.Quota(**body['quota'])
            else:
                for k, v in body['quota'].items():
                    setattr(region.quota, k, v)
        else:
            region.quota = None
        del body['quota']

    openstack_credentials = dpath.get(body,
                                      'openstack/credentials',
                                      default=region.openstack_credentials)
    if not isinstance(openstack_credentials, str):
        vault.write(region.openstack_credentials, openstack_credentials)
        dpath.delete(body, 'openstack/credentials')

    satellite_credentials = dpath.get(body,
                                      'satellite/credentials',
                                      default=region.satellite_credentials)
    if not isinstance(satellite_credentials, str):
        vault.write(region.satellite_credentials, satellite_credentials)
        dpath.delete(body, 'satellite/credentials')

    dns_server_key = dpath.get(body,
                               'dns_server/key',
                               default=region.dns_server_key)
    if not isinstance(dns_server_key, str):
        vault.write(region.dns_server_key, dns_server_key)
        dpath.delete(body, 'dns_server/key')

    region.update_from_dict(body)

    db.session.commit()
    logger.info(
        f'Region {region.name} (id {region.id}) updated by user {user}')

    return region.to_dict() | {'_href': _region_href(region)}
Ejemplo n.º 23
0
def images(taxon=None, service=None, limit=None, offset=None):
    """Specimen link retrieval."""
    from ..elc import subreq

    desc_obj = dict()
    t0 = time()
    sub_query = 'Specimen images for {0:s} retrieved through {1:s}'.format(
        taxon.capitalize(), 'iDigBio' if service == 'idigbio' else 'ePANDDA')

    try:
        options = params.set_options(req_args=connexion.request.args,
                                     endpoint='images')

    except ValueError as err:
        return connexion.problem(status=err.args[0],
                                 title=Status(err.args[0]).name,
                                 detail=err.args[1],
                                 type='about:blank')

    # Call parse function to check for parameter errors

    try:
        payload = params.parse(req_args=connexion.request.args,
                               options=options,
                               db='pbdb',
                               endpoint='images')

    except ValueError as err:
        return connexion.problem(status=err.args[0],
                                 title=Status(err.args[0]).name,
                                 detail=err.args[1],
                                 type='about:blank')

    # Query media aggregators

    try:
        media = subreq.images_req(payload=payload,
                                  options=options)

    except ValueError as err:
        return connexion.problem(status=err.args[0],
                                 title=Status(err.args[0]).name,
                                 detail=err.args[1],
                                 type='about:blank')

    # Build returned metadata object

    desc_obj.update(aux.build_meta(options))

    desc_obj.update(aux.build_meta_sub(source=sub_query,
                                       t0=t0,
                                       sub_tag='media_links',
                                       options=options,
                                       data=media))

    # Return data structure to client

    return jsonify(metadata=desc_obj, records=media)
Ejemplo n.º 24
0
def mobile(taxon=None, bbox=None):
    """Lightweight custom response."""
    from ..elc import config, subreq

    return_obj = list()

    # Set runtime options

    try:
        options = params.set_options(req_args=connexion.request.args,
                                     endpoint='occ')

    except ValueError as err:
        return connexion.problem(status=err.args[0],
                                 title=Status(err.args[0]).name,
                                 detail=err.args[1],
                                 type='about:blank')

    # This query only applies to Neotoma and PBDB

    for db in ['neotoma', 'pbdb']:

        # Configure parameter payload for api subquery

        try:
            payload = params.parse(req_args=connexion.request.args,
                                   options=options,
                                   db=db,
                                   endpoint='occ')

        except ValueError as err:
            return connexion.problem(status=err.args[0],
                                     title=Status(err.args[0]).name,
                                     detail=err.args[1],
                                     type='about:blank')

        # Database API call

        url_path = ''.join([config.get('resource_api', db),
                            config.get('db_occ_endpt', db)])

        try:
            return_obj = subreq.mobile_req(return_obj=return_obj,
                                           url_path=url_path,
                                           payload=payload,
                                           db=db)

        except ValueError as err:
            return connexion.problem(status=err.args[0],
                                     title=Status(err.args[0]).name,
                                     detail=err.args[1],
                                     type='about:blank')

    # Return composite data structure to client

    return jsonify(return_obj)
Ejemplo n.º 25
0
def land(data, api_key=None):
    """API endpoint at POST /landings to land revision."""
    # get revision_id from body
    revision_id = data['revision_id']
    diff_id = data['diff_id']
    logger.info(
        {
            'path': request.path,
            'method': request.method,
            'data': data,
            'msg': 'landing requested by user'
        }, 'landing.invoke')
    try:
        landing = Landing.create(revision_id, diff_id, api_key)
    except RevisionNotFoundException:
        # We could not find a matching revision.
        logger.info({
            'revision': revision_id,
            'msg': 'revision not found'
        }, 'landing.failure')
        return problem(
            404,
            'Revision not found',
            'The requested revision does not exist',
            type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404'
        )
    except DiffNotFoundException:
        # We could not find a matching diff
        logger.info({
            'diff': diff_id,
            'msg': 'diff not found'
        }, 'landing.failure')
        return problem(
            404,
            'Diff not found',
            'The requested diff does not exist',
            type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404'
        )
    except LandingNotCreatedException as exc:
        # We could not find a matching revision.
        logger.info(
            {
                'revision': revision_id,
                'exc': exc,
                'msg': 'error creating landing',
            }, 'landing.error')
        return problem(
            502,
            'Landing not created',
            'The requested revision does exist, but landing failed.'
            'Please retry your request at a later time.',
            type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502'
        )

    return {'id': landing.id}, 202
Ejemplo n.º 26
0
def convert(amount, input_currency, output_currency=""):
    try:
        converter = Converter(amount, input_currency, output_currency)
        if converter.check_parameters():
            return converter.convert()
        else:
            return problem(400, "Bad Request", "Wrong parameters",
                           "about:blank")
    except FileNotFoundError:
        return problem(400, "Error", "Cannot find file with currency symbols.",
                       "about:blank")
Ejemplo n.º 27
0
def bulk_set_acknowledgement_on_host_service(params):
    """Bulk Acknowledge specific services on specific host"""
    live = sites.live()
    body = params['body']
    host_name = body['host_name']
    entries = body.get('entries', [])

    query = Query([Services.description, Services.state],
                  And(
                      Services.host_name.equals(host_name),
                      Or(*[
                          Services.description.equals(service_description)
                          for service_description in entries
                      ])))

    services = query.to_dict(live)

    not_found = []
    for service_description in entries:
        if service_description not in services:
            not_found.append(service_description)

    if not_found:
        return problem(
            status=400,
            title=
            f"Services {', '.join(not_found)} not found on host {host_name}",
            detail='Currently not monitored')

    up_services = []
    for service_description in entries:
        if services[service_description] == 0:
            up_services.append(service_description)

    if up_services:
        return problem(
            status=400,
            title=f"Services {', '.join(up_services)} do not have a problem",
            detail="The states of these services are OK")

    for service_description in entries:
        acknowledge_service_problem(
            sites.live(),
            host_name,
            service_description,
            sticky=body.get('sticky', False),
            notify=body.get('notify', False),
            persistent=body.get('persistent', False),
            user=str(config.user.id),
            comment=body.get('comment', 'Acknowledged'),
        )
    return http.Response(status=204)
Ejemplo n.º 28
0
def get(urn: str) -> Union[Response, ConnexionResponse]:
    """The GET method for the valid references REST API. It provides references for the desired text."""
    try:
        reff: List[str] = CustomCorpusService.get_custom_corpus_reff(
            urn) if CustomCorpusService.is_custom_corpus_urn(
                urn) else CorpusService.get_standard_corpus_reff(urn)
    except ValueError:
        return connexion.problem(400, Config.ERROR_TITLE_BAD_REQUEST,
                                 Config.ERROR_MESSAGE_BAD_REQUEST)
    if not reff:
        return connexion.problem(404, Config.ERROR_TITLE_NOT_FOUND,
                                 Config.ERROR_MESSAGE_CORPUS_NOT_FOUND)
    return NetworkService.make_json_response(reff)
Ejemplo n.º 29
0
 def _execute(name=None):
     try:
         return func(name), httplib.OK
     except error.NotFoundError:
         return connexion.problem(
             httplib.NOT_FOUND, '{} not found'.format(resource),
             'Requested {} `{}` not found.'.format(
                 resource.lower(), name))
     except error.ToBeDoneError:
         return connexion.problem(
             httplib.NOT_IMPLEMENTED,
             '{} handler not implemented'.format(operation),
             'Requested operation `{}` on {} not implemented.'.format(
                 operation.lower(), resource.lower()))
Ejemplo n.º 30
0
def relaunch_job(job_id, user):
    job = model.Job.query.get(job_id)
    if not job:
        return problem(404, 'Not Found', f'Job {job_id} does not exist')

    if not user_is_admin(user) and job.launched_by != user:
        return problem(403, 'Forbidden',
                       f"You don't have permissions to relaunch job {job_id}")

    try:
        tower_client = job.server.create_tower_client()

        if job.template.tower_template_is_workflow:
            tower_job_data = tower_client.workflow_job_relaunch(
                job.tower_job_id)
        else:
            tower_job_data = tower_client.template_job_relaunch(
                job.tower_job_id)

        relaunched_job = model.Job(
            template_id=job.template_id,
            tower_job_id=tower_job_data['id'],
            launched_by=user,
        )
        db.session.add(relaunched_job)
        db.session.commit()

        return _tower_job(relaunched_job, tower_job_data) | {
            '_href': _job_href(job)
        }

    except TowerError as e:
        logger.exception(f'Failed to relaunch job, {e}')

        problem_ext = None
        try:
            problem_ext = e.response.json()
            if 'detail' in problem_ext:
                del problem_ext['detail']
        except Exception:
            pass  # simply ignore

        return problem(e.response.status_code,
                       'Error',
                       f'Failed to relaunch job {job_id}',
                       ext=problem_ext)

    except Exception as e:
        logger.exception(e)
        return problem(500, 'Server Error', f'Unknown server error, {e}')
Ejemplo n.º 31
0
def call_eureka():
    if not EUREKA_URL:
        return connexion.problem(500, "Internal Server error",
                                 "Eureka url not set", "errors.eureka")
    if not ExternalServices.eureka_on:
        ExternalServices.init_eureka()
        if not ExternalServices.eureka_on:
            return connexion.problem(
                500, "Internal Server error",
                "Unable to connect to eureka, the server might not be running",
                "errors.eureka")
        return "Connected to eureka", 200

    return "Already connected to eureka", 200
Ejemplo n.º 32
0
def get_attribute_consent(taxCode):
    """Receives a token and asks for permission if
       required.
    Return
    :param taxCode:
    :return:
    """
    content_type = request.headers.get("Content-Type", "")
    assert content_type.lower() == "application/jose"

    user_data = _get_user_data(taxCode)
    if not user_data:
        return problem(title="User Not Found",
                       status=404,
                       detail="Missing user")

    try:
        claims = validate_token(request.data, audience=app.config["entityId"])
    except jwt.exceptions.InvalidTokenError as e:
        return invalid_token_handler(e)
    except Exception as e:
        raise ValueError(e, request.data)

    assert claims["v"] == "0.0.1", claims
    assert claims["attributes"], claims

    if user_data["consent"] + 30 < time():
        return problem(
            status=403,
            title="ConsentRequired",
            detail="User consent is required for this attribute. Last given: %r"
            % datetime.fromtimestamp(user_data["consent"]),
            type="https://spid.gov.it/aa/problem/consent-required",
            ext={"consent_url": "https://aa/v1/consents/{taxCode}/"},
        )

    aa = [{
        "attribute": a,
        "value": user_data[a]
    } for a in claims["attributes"] if a in user_data]

    token = create_token({"v": "0.0.1", "attributes": aa})
    token["iss"] = app.config["entityId"]
    token["aud"] = claims["iss"]

    signed_token = sign_request(token, app_config=app.config)

    return Response(response=signed_token,
                    status=200,
                    mimetype="application/jose")
Ejemplo n.º 33
0
def with_problem():
    return problem(type='http://www.example.com/error',
                   title='Some Error',
                   detail='Something went wrong somewhere',
                   status=418,
                   instance='instance1',
                   headers={'x-Test-Header': 'In Test'})
Ejemplo n.º 34
0
def get_fragment_svg(fragment_id, width, height):
    """2D drawing of fragment in SVG format

    Args:
        fragment_id (str): Fragment identifier
        width (int): Width of SVG in pixels
        height (int): Height of SVG in pixels

    Returns:
        flask.Response|connexion.lifecycle.ConnexionResponse: SVG document|problem
    """
    fragments_db_filename = current_app.config['fragments']
    with FragmentsDb(fragments_db_filename) as fragmentsdb:
        try:
            fragment = fragmentsdb[fragment_id]
            if not fragment['mol']:
                title = 'Not Found'
                description = 'Fragment with identifier \'{0}\' has no molblock'.format(fragment_id)
                ext = {'identifier': fragment_id}
                return connexion.problem(404, title, description, ext=ext)
            mol = fragment['mol']
            svg = mol2svg(mol, width, height)
            return flask.Response(svg, mimetype='image/svg+xml')
        except LookupError:
            return fragment_not_found(fragment_id)
Ejemplo n.º 35
0
def post(emergency_shutoff, changed_by, transaction):
    if shutoff_exists(emergency_shutoff["product"], emergency_shutoff["channel"]):
        return problem(400, "Bad Request", "Invalid Emergency shutoff data", ext={"data": "Emergency shutoff for product/channel already exists."})
    inserted_shutoff = dbo.emergencyShutoffs.insert(
        changed_by=changed_by, transaction=transaction, product=emergency_shutoff["product"], channel=emergency_shutoff["channel"]
    )
    return Response(status=201, content_type="application/json", response=json.dumps(inserted_shutoff))
Ejemplo n.º 36
0
def with_problem():
    return problem(
        type="http://www.example.com/error",
        title="Some Error",
        detail="Something went wrong somewhere",
        status=418,
        instance="instance1",
    )
Ejemplo n.º 37
0
def get_by_id(product, channel):
    shutoffs = dbo.emergencyShutoffs.select(where=dict(product=product, channel=channel))
    if not shutoffs:
        return problem(status=404, title="Not Found", detail="Requested emergency shutoff wasn't found", ext={"exception": "Requested shutoff does not exist"})

    headers = {"X-Data-Version": shutoffs[0]["data_version"]}

    return Response(response=json.dumps(shutoffs[0]), headers=headers, mimetype="application/json")
Ejemplo n.º 38
0
def schedule_deletion(sc_emergency_shutoff, changed_by, transaction):
    if "csrf_token" in sc_emergency_shutoff:
        del sc_emergency_shutoff["csrf_token"]
    change_type = sc_emergency_shutoff.get("change_type")
    if change_type != "delete":
        return problem(400, "Bad Request", "Invalid or missing change_type")

    view = ScheduledChangesView("emergency_shutoff", dbo.emergencyShutoffs)
    return view._post(sc_emergency_shutoff, transaction, changed_by, change_type)
Ejemplo n.º 39
0
def schedule_deletion(sc_emergency_shutoff, changed_by, transaction):
    if 'csrf_token' in sc_emergency_shutoff:
        del sc_emergency_shutoff['csrf_token']
    change_type = sc_emergency_shutoff.get('change_type')
    if change_type != 'delete':
        return problem(400, "Bad Request", "Invalid or missing change_type")

    view = ScheduledChangesView('emergency_shutoff', dbo.emergencyShutoffs)
    return view._post(sc_emergency_shutoff, transaction, changed_by, change_type)
Ejemplo n.º 40
0
def get_rule(id_or_alias, with_csrf_headers=False):
    rule = dbo.rules.getRule(id_or_alias)
    if not rule:
        return problem(status=404, title="Not Found", detail="Requested rule wasn't found", ext={"exception": "Requested rule does not exist"})

    headers = {"X-Data-Version": rule["data_version"]}
    if with_csrf_headers:
        headers.update(get_csrf_headers())
    return Response(response=json.dumps(rule), mimetype="application/json", headers=headers)
Ejemplo n.º 41
0
def post(emergency_shutoff, changed_by, transaction):
    if shutoff_exists(emergency_shutoff['product'], emergency_shutoff['channel']):
        return problem(
            400, 'Bad Request', 'Invalid Emergency shutoff data',
            ext={'data': 'Emergency shutoff for product/channel already exists.'})
    inserted_shutoff = dbo.emergencyShutoffs.insert(
        changed_by=changed_by, transaction=transaction, product=emergency_shutoff['product'], channel=emergency_shutoff['channel'])
    return Response(status=201,
                    content_type="application/json",
                    response=json.dumps(inserted_shutoff))
Ejemplo n.º 42
0
Archivo: api.py Proyecto: zalando/lizzy
def exception_to_connexion_problem(func, *args, **kwargs):
    try:
        return func(*args, **kwargs)
    except ObjectNotFound as exception:
        problem = connexion.problem(404, 'Not Found',
                                    "Stack not found: {}".format(exception.uid),
                                    headers=_make_headers())
        metrics.count('generic.{}.stack_not_found'.format(func.__name__))
        return problem
    except ExecutionError as error:
        sentry_client.captureException()
        metrics.count('generic.{}.senza_cmd_error'.format(func.__name__))
        return connexion.problem(500,
                                 title='Execution Error',
                                 detail=error.output,
                                 headers=_make_headers())
    except Exception:
        sentry_client.captureException()
        raise
Ejemplo n.º 43
0
def get_release_single_locale(release, platform, locale, with_csrf_header=False):
    try:
        locale = dbo.releases.getLocale(release, platform, locale)
    except KeyError as e:
        return problem(404, "Not Found", json.dumps(e.args))
    data_version = dbo.releases.getReleases(name=release)[0]["data_version"]
    headers = {"X-Data-Version": data_version}
    if with_csrf_header:
        headers.update(get_csrf_headers())
    return Response(response=json.dumps(locale), mimetype="application/json", headers=headers)
Ejemplo n.º 44
0
def delete(product, channel, data_version, changed_by, transaction, **kwargs):
    if not shutoff_exists(product, channel):
        return problem(status=404,
                       title="Not Found",
                       detail="Shutoff wasn't found",
                       ext={"exception": "Shutoff does not exist"})
    where = dict(product=product, channel=channel)
    dbo.emergencyShutoffs.delete(where=where, changed_by=changed_by,
                                 old_data_version=data_version,
                                 transaction=transaction)
    return Response(status=200)
Ejemplo n.º 45
0
def get(animal_id):
    gc = global_cell.GlobalCell()
    q = {'animal_id': animal_id}
    res = [i['id'] for i in gc.find(q)]
    if not res:
        return connexion.problem(
            404,
            'not found',
            'no global cells found for {}'.format(animal_id),
            __name__.split('.')[-1]
        )
    return res
Ejemplo n.º 46
0
def get_release_history(release):
    history_table = dbo.releases.history
    order_by = [history_table.timestamp.desc()]
    history_helper = HistoryHelper(hist_table=history_table,
                                   order_by=order_by,
                                   get_object_callback=lambda: _get_release(release),
                                   history_filters_callback=_get_filters,
                                   process_revisions_callback=process_release_revisions)
    try:
        return history_helper.get_history()
    except (ValueError, AssertionError) as e:
        log.warning("Bad input: %s", json.dumps(e.args))
        return problem(400, "Bad Request", "Invalid input", ext={"data": e.args})
Ejemplo n.º 47
0
def get(cell_id):
    c = cell.Cell()
    q = {'id': cell_id}
    res = c.find_one(q)
    if not res:
        return connexion.problem(
            404,
            'not found',
            'id {} does not exist'.format(cell_id),
            __name__.split('.')[-1]
        )
    del res['_id']
    return res
Ejemplo n.º 48
0
def get(run_id):
    r = run.Run()
    q = {'id': run_id}
    res = r.find_one(q)
    if not res:
        return connexion.problem(
            404,
            'not found',
            'id {} does not exist'.format(run_id),
            __name__.split('.')[-1]
        )
    del res['_id']
    return res
def get(cell_metric_id):
    pcmi = per_cell_metric.PerCellMetricInfo()
    q = {'id': cell_metric_id}
    res = pcmi.find_one(q)
    if not res:
        return connexion.problem(
            404,
            'not found',
            'id {} does not exist'.format(cell_metric_id),
            __name__.split('.')[-1]
        )
    del res['_id']
    return res
Ejemplo n.º 50
0
def get(trial_id):
    t = trial.Trial()
    q = {'id': trial_id}
    res = t.find_one(q)
    if not res:
        return connexion.problem(
            404,
            'not found',
            'id {} does not exist'.format(trial_id),
            __name__.split('.')[-1]
        )
    del res['_id']
    return res
Ejemplo n.º 51
0
def get(trial_id):
    ret = raw_eye_tracking.RawEyeTracking()
    q = {'trial_id': trial_id}
    res = ret.find_one(q)
    if not res:
        return connexion.problem(
            404,
            'not found',
            'raw eye tracking data for trial {} not found'.format(trial_id),
            __name__.split('.')[-1]
        )
    if res:
        del res['_id']
    return res
Ejemplo n.º 52
0
def get_rule_history(rule_id):
    history_table = dbo.rules.history
    order_by = [history_table.timestamp.desc()]
    history_helper = HistoryHelper(hist_table=history_table,
                                   order_by=order_by,
                                   get_object_callback=lambda: dbo.rules.getRule(rule_id),
                                   history_filters_callback=_get_filters,
                                   obj_not_found_msg='Requested rule does not exist')
    try:
        return history_helper.get_history(response_key='rules')
    except (ValueError, AssertionError) as msg:
        log.warning("Bad input: %s", msg)
        return problem(400, "Bad Request", "Error occurred when trying to fetch"
                                           " Rule's revisions having rule_id {0}".format(rule_id),
                       ext={"exception": str(msg)})
Ejemplo n.º 53
0
def get(session_id):
    s = session.Session()
    q = {'id': session_id}
    res = s.find_one(q)
    if not res:
        return connexion.problem(
            404,
            'not found',
            'session id {} not found'.format(session_id),
            __name__.split('.')[-1]
        )
    res['animal'] = res['animal']['id']
    del res['_id']
    del res['runs']
    return res
Ejemplo n.º 54
0
def get_release(release, with_csrf_header=False):
    release = _get_release(release)
    if not release:
        return problem(404, "Not Found", "Release name: %s not found" % release)
    headers = {"X-Data-Version": release["data_version"]}
    if with_csrf_header:
        headers.update(get_csrf_headers())
    if request.args.get("pretty"):
        indent = 4
        separators = (",", ": ")
    else:
        indent = None
        separators = None
    # separators set manually due to https://bugs.python.org/issue16333 affecting Python 2
    return Response(response=json.dumps(release["data"], indent=indent, separators=separators, sort_keys=True), mimetype="application/json", headers=headers)
Ejemplo n.º 55
0
def _get_histories(table, obj, process_revisions_callback=None):
    history_table = table
    order_by = [history_table.timestamp.desc()]
    history_helper = HistoryHelper(hist_table=history_table,
                                   order_by=order_by,
                                   get_object_callback=lambda: obj,
                                   history_filters_callback=_get_filters,
                                   obj_not_found_msg='No history found',
                                   process_revisions_callback=process_revisions_callback)
    try:
        return history_helper.get_history()
    except (ValueError, AssertionError) as msg:
        log.warning("Bad input: %s", msg)
        return problem(400, "Bad Request", "Error occurred when trying to fetch histories",
                       ext={"exception": str(msg)})
def get(run_id, cell_id, channel_id=None, trial_id=None):
    ftc = functional_time_course.FunctionalTimeCourse()
    q = {'run_id': run_id, 'cell_id': cell_id}
    if trial_id:
        q['trial_id'] = trial_id
    res = ftc.find_one(q)
    if not res:
        return connexion.problem(
            404,
            'not found',
            'time course data not found',
            __name__.split('.')[-1]
        )
    if res:
        del res['_id']
    return res
Ejemplo n.º 57
0
def get_fragments(fragment_ids=None, pdb_codes=None):
    """Retrieve fragments based on their identifier or PDB code.

    Args:
        fragment_ids (List[str]): List of fragment identifiers
        pdb_codes (List[str]): List of PDB codes

    Returns:
        list[dict]: List of fragment information

    Raises:
        werkzeug.exceptions.NotFound: When one of the fragments_ids or pdb_code could not be found
    """
    fragments_db_filename = current_app.config['fragments']
    with FragmentsDb(fragments_db_filename) as fragmentsdb:
        fragments = []
        missing_ids = []
        if fragment_ids:
            for frag_id in fragment_ids:
                try:
                    fragments.append(fragmentsdb[frag_id])
                except LookupError:
                    missing_ids.append(frag_id)

        if pdb_codes:
            for pdb_code in pdb_codes:
                try:
                    for fragment in fragmentsdb.by_pdb_code(pdb_code):
                        fragments.append(fragment)
                except LookupError:
                    missing_ids.append(pdb_code)
        # TODO if fragment_ids and pdb_codes are both None then return paged list of all fragments
        if missing_ids:
            title = 'Not found'
            label = 'identifiers'
            if pdb_codes:
                label = 'PDB codes'
            description = 'Fragments with {1} \'{0}\' not found'.format(','.join(missing_ids), label)
            # connexion.problem is using json.dumps instead of flask custom json encoder, so performing convert myself
            # TODO remove mol2string conversion when https://github.com/zalando/connexion/issues/266 is fixed
            for fragment in fragments:
                if fragment['mol']:
                    fragment['mol'] = MolToMolBlock(fragment['mol'])
            ext = {'absent_identifiers': missing_ids, 'fragments': fragments}
            return connexion.problem(404, title, description, ext=ext)
        return fragments
Ejemplo n.º 58
0
def common_error_handler(exception):
    '''TODO: add description

    :param extension:  TODO
    :type exception: Exception

    :rtype: TODO:
    '''

    if not isinstance(exception, werkzeug.exceptions.HTTPException):
        exception = werkzeug.exceptions.InternalServerError()

    return connexion.problem(
        title=exception.name,
        detail=exception.description,
        status=exception.code,
    )
Ejemplo n.º 59
0
    def validate_schema(self, data, url):
        # type: (dict, AnyStr) -> Union[ConnexionResponse, None]
        if self.is_null_value_valid and is_null(data):
            return None
        try:
            self.validator.validate(data)
        except JsonSchemaValidationError as exception:
            # Add field name to the error response
            exception_field = ''
            for i in exception.path:
                exception_field = i + ': '
            if exception.__cause__ is not None:
                exception_message = str(exception.__cause__.message) + ' ' + exception_field + str(exception.message)
            else:
                exception_message = exception_field + str(exception.message)
            logger.error("{url} validation error: {error}".
                         format(url=url, error=exception_message))
            return problem(400, 'Bad Request', exception_message)

        return None
Ejemplo n.º 60
0
    def validate_schema(self, data, url):
        # type: (dict, AnyStr) -> Union[ConnexionResponse, None]
        if self.is_null_value_valid and is_null(data):
            return None
        try:
            self.validator.validate(data)
        except jsonschema.ValidationError as exception:
            # Add field name to the error response
            exception_field = ""
            for i in exception.path:
                exception_field = i + ": "
            if exception.__cause__ is not None:
                exception_message = exception.__cause__.message + " " + exception_field + exception.message
            else:
                exception_message = exception_field + exception.message
            # Some exceptions could contain unicode characters - if we don't replace them
            # we could end up with a UnicodeEncodeError.
            logger.error("{url} validation error: {error}".format(url=url, error=exception_message.encode("utf-8", "replace")))
            return problem(400, "Bad Request", exception_message)

        return None