"""Utility Functions for Handlers.""" import functools import re from flask import request from oto import response from oto.adaptors.flask import flaskify from owsrequest import error_response from owsrequest import flask_request from werkzeug.exceptions import BadRequest from lyrics.constants import error from lyrics.constants import header from lyrics.exceptions import RequestError from lyrics.exceptions import ValidationError def parse_request_json(schema=None, partial=False): """Parse and optionally validate request JSON. Args: schema (type): marshmallow schema to validate request partial (bool): parial validation flag Returns: dict: Validated request """ try: request_json = request.get_json(silent=True) except BadRequest: raise RequestError("Invalid JSON") from None # Verify request data is enveloped in dict (Marshmallow doesn't catch this) if not isinstance(request_json, dict): raise RequestError("Request envelope must be an object.") if not schema: return request_json result = schema().load(request_json, partial=partial) if result.errors: raise ValidationError(result.errors) return result.data def no_grass_access(function): """Decorate function to check that request is not made from GRASS.""" @functools.wraps(function) def wrapper(*args, **kwargs): account_type, account_id = flask_request.get_grass_headers(request) user_id = request.headers.get(header.ORCHARD_USER_ID) if any((account_type, account_id, user_id)): return flaskify( response.create_error_response( code=error.ERROR_CODE_BAD_GRASS_REQUEST, message=error.ERROR_GRASS_FORBIDDEN, ) ) return function(*args, **kwargs) return wrapper def verify_profile(request_context, profile_type): """Verify that the request context matches the profile_type. Args: request_context (obj): request context. profile_type(str): check the request context to verify it is from this profile_type. """ if ( request_context.context_type == header.ERROR_CONTEXT_TYPE or request_context.context_type is None ): return error_response.create_error_incomplete_profile_headers() if profile_type == header.PROFILE_TYPE_ORCH_ADMIN: if request_context.orchard_user_id is not None and re.match( r"oa:[0-9]+", request_context.orchard_user_id ): return response.Response() return error_response.create_error_forbidden_user() def verify_authorization(function): """Decorate function to check that request is authorized.""" @functools.wraps(function) def wrapper(*args, **kwargs): authorization = request.headers.get("Authorization") if not authorization: return flaskify(error_response.create_error_forbidden_user()) return function(*args, **kwargs) return wrapper