def validate_request(req, path_pattern, path_params, spec, url): print('Validating URL: {}'.format(url)) counters['requests'] += 1 openapi_request = RequestsOpenAPIRequest(req, path_pattern, path_params) validator = RequestValidator(spec) result = validator.validate(openapi_request) request_errors = result.errors r = req.prepare() s = requests.Session() res = s.send(r) openapi_response = RequestsOpenAPIResponse(res) validator = ResponseValidator(spec) result = validator.validate(openapi_request, openapi_response) response_errors = result.errors print('Request errors: {}'.format(request_errors)) print('Response errors: {}'.format(response_errors)) if request_errors or response_errors: errors_count = len(request_errors) + len(response_errors) print(color(' [FAIL] {:d} errors found '.format(errors_count), fg='white', bg='red', style='bold')) print("Response body: {}".format(res.text)) else: errors_count = 0 print(color(' [PASS] No errors found ', fg='white', bg='green', style='bold')) print() return errors_count
def validate_request(req, path_pattern, path_params, spec, url): print('Validating URL: {}'.format(url)) counters['requests'] += 1 openapi_request = RequestsOpenAPIRequest(req, path_pattern, path_params) validator = RequestValidator(spec) result = validator.validate(openapi_request) request_errors = result.errors r = req.prepare() s = requests.Session() res = s.send(r) openapi_response = RequestsOpenAPIResponse(res) validator = ResponseValidator(spec) result = validator.validate(openapi_request, openapi_response) response_errors = result.errors print('Request errors: {}'.format(request_errors)) print('Response errors: {}'.format(response_errors)) if request_errors or response_errors: errors_count = len(request_errors) + len(response_errors) print( color(' [FAIL] {:d} errors found '.format(errors_count), fg='white', bg='red', style='bold')) print("Response body: {}".format(res.text)) else: errors_count = 0 print( color(' [PASS] No errors found ', fg='white', bg='green', style='bold')) print() return errors_count
class OpenApiSpecManager(SharedExtension): _loaded = Event() def setup(self): log.info(' ### OpenApiSpecManager.setup') super().setup() def load_spec(self, spec_file): log.debug('%s.load_spec: %s' % (self.__class__.__name__, spec_file)) # TODO: supporting loading from url instead of just file # TODO: How to handle/interpret/respect spec.servers[].url's? # TODO: Or should this be generated/injected into the spec_dict on startup? #spec_file = '/home/sar/vcs/nameko-openapi/petstore.yaml' spec_dict = yaml.safe_load(open(spec_file)) self.spec = openapi_core.create_spec(spec_dict) self.request_validator = RequestValidator(self.spec) self.response_validator = ResponseValidator(self.spec) self._loaded.send(self.spec) def wait_for_spec(self): """Allow other extensions to wait until the spec is loaded.""" return self._loaded.wait() def get_operation_by_id(self, operation_id): self.wait_for_spec() for path_name, path in six.iteritems(self.spec.paths): for http_method, operation in six.iteritems(path.operations): if operation.operation_id == operation_id: return operation def validate_request(self, request, raise_for_errors=True): result = self.request_validator.validate(request) if raise_for_errors: result.raise_for_errors() return result def validate_response(self, response, openapi_request, raise_for_errors=True): result = self.response_validator.validate(openapi_request, response) if raise_for_errors: result.raise_for_errors() return result
def register(): spec_dict = read_yaml_file(filepath) validate_spec(spec_dict) spec = create_spec(spec_dict) def spec_view(request): return FileResponse( filepath, request=request, content_type='text/yaml' ) config.add_view(route_name=route_name, view=spec_view) config.add_route(route_name, route) custom_formatters = config.registry.settings.get('pyramid_openapi3_formatters') config.registry.settings['pyramid_openapi3'] = { "filepath": filepath, "spec_route_name": route_name, "spec": spec, "request_validator": RequestValidator(spec, custom_formatters), "response_validator": ResponseValidator(spec, custom_formatters), }
def put(self, tenant_id): logger.debug(f"top of PUT /tenants/{tenant_id}") tenant = Tenant.query.filter_by(tenant_id=tenant_id).first() if not tenant: raise errors.ResourceError(msg=f'No tenant found with tenant_id {tenant_id}.') # additional authorization checks on update based on the tenant_id of the request: check_authz_tenant_update(tenant_id) validator = RequestValidator(utils.spec) result = validator.validate(FlaskOpenAPIRequest(request)) if result.errors: logger.debug(f"openapi_core validation failed. errors: {result.errors}") raise errors.ResourceError(msg=f'Invalid PUT data: {result.errors}.') validated_body = result.body logger.debug(f"initial openapi_core validation passed. validated_body: {dir(validated_body)}") # TODO -- # ------------------------- This DOES NOT WORK ------------------------------------ # the validated_body ONLY contains fields in the OAI spec; need to change this to look at the # request body itself if not getattr(validated_body, 'site_id', tenant.site_id) == tenant.site_id: raise errors.ResourceError(msg=f'Invalid PUT data: cannot change site_id.') if not getattr(validated_body, 'tenant_id', tenant.tenant_id) == tenant.tenant_id: raise errors.ResourceError(msg=f'Invalid PUT data: cannot change tenant_id.') if not getattr(validated_body, 'base_url', tenant.base_url) == tenant.base_url: raise errors.ResourceError(msg=f'Invalid PUT data: cannot change base_url.') # ------------------------------------------------------------------------------------ # validate the existence of the ldap and owner objects: if getattr(validated_body, 'owner', None): owner = TenantOwner.query.filter_by(email=validated_body.owner).first() if not owner: raise errors.ResourceError(msg=f'Invalid tenant description. Owner {validated_body.owner} not found.') logger.debug("owner was valid.") if getattr(validated_body, 'user_ldap_connection_id', None): ldap = LDAPConnection.query.filter_by(ldap_id=validated_body.user_ldap_connection_id).first() if not ldap: raise errors.ResourceError(msg=f'Invalid tenant description. ' f'LDAP {validated_body.user_ldap_connection_id} not found.') if getattr(validated_body, 'service_ldap_connection_id', None) and \ not validated_body.service_ldap_connection_id == getattr(validated_body, 'user_ldap_connection_id', None): ldap = LDAPConnection.query.filter_by(ldap_id=validated_body.service_ldap_connection_id).first() if not ldap: raise errors.ResourceError(msg=f'Invalid tenant description. ' f'LDAP {validated_body.service_ldap_connection_id} not found.') # overlay the tenant_current with the updates specified in the request body. changes_dict = {} # security_kernel new_security_kernel = getattr(validated_body, 'security_kernel', None) if new_security_kernel and not new_security_kernel == tenant.security_kernel: changes_dict['security_kernel'] = {'prev': tenant.security_kernel, 'new': new_security_kernel} tenant.security_kernel = new_security_kernel # token_service new_tokens_service = getattr(validated_body, 'token_service', None) if new_tokens_service and not new_tokens_service == tenant.token_service: changes_dict['tokens_service'] = {'prev': tenant.token_service, 'new': new_tokens_service} tenant.token_service = new_tokens_service # authenticator new_authenticator = getattr(validated_body, 'authenticator', None) if new_authenticator and not new_authenticator == tenant.authenticator: changes_dict['authenticator'] = {'prev': tenant.authenticator, 'new': new_authenticator} tenant.authenticator = new_authenticator # admin_user new_admin_user = getattr(validated_body, 'admin_user', None) if new_admin_user and not new_admin_user == tenant.admin_user: changes_dict['admin_user'] = {'prev': tenant.admin_user, 'new': new_admin_user} tenant.admin_user = new_admin_user # token_gen_services new_token_gen_services = getattr(validated_body, 'token_gen_services', None) if new_token_gen_services and not new_token_gen_services == tenant.token_gen_services: changes_dict['token_gen_services'] = {'prev': tenant.token_gen_services, 'new': new_token_gen_services} tenant.token_gen_services = new_token_gen_services # service_ldap_connection_id new_service_ldap_connection_id = getattr(validated_body, 'service_ldap_connection_id', None) if new_service_ldap_connection_id and not new_service_ldap_connection_id == tenant.service_ldap_connection_id: changes_dict['service_ldap_connection_id'] = {'prev': tenant.service_ldap_connection_id, 'new': new_service_ldap_connection_id} tenant.service_ldap_connection_id = new_service_ldap_connection_id # user_ldap_connection_id new_user_ldap_connection_id = getattr(validated_body, 'user_ldap_connection_id', None) if new_user_ldap_connection_id and not new_user_ldap_connection_id == tenant.user_ldap_connection_id: changes_dict['user_ldap_connection_id'] = {'prev': tenant.user_ldap_connection_id, 'new': new_user_ldap_connection_id} tenant.user_ldap_connection_id = new_user_ldap_connection_id # public_key new_public_key = getattr(validated_body, 'public_key', None) if new_public_key and not new_public_key == tenant.public_key: changes_dict['public_key'] = {'prev': tenant.public_key, 'new': new_public_key} tenant.public_key = new_public_key # status new_status = getattr(validated_body, 'status', None) if new_status and not new_status == tenant.status: changes_dict['status'] = {'prev': tenant.status.serialize, 'new': new_status.upper()} tenant.status = new_status # description new_description = getattr(validated_body, 'description', None) if new_description and not new_description == tenant.description: changes_dict['description'] = {'prev': tenant.description, 'new': new_description} tenant.description = new_description # owner new_owner = getattr(validated_body, 'owner', None) if new_owner and not new_owner == tenant.owner: changes_dict['owner'] = {'prev': tenant.owner, 'new': new_owner} tenant.owner = new_owner # last_update_time and last_updated_by update_time = datetime.datetime.utcnow() updated_by = f'{g.username}@{g.tenant_id}' tenant.last_update_time = update_time tenant.last_updated_by = updated_by # create the history record tenant_history = TenantHistory( tenant_id=tenant.tenant_id, update_time=update_time, updated_by=updated_by, updates_as_json=json.dumps(changes_dict) ) db.session.add(tenant_history) try: db.session.commit() logger.info(f"update to tenant committed to db. tenant object: {tenant}") except (sqlalchemy.exc.SQLAlchemyError, sqlalchemy.exc.DBAPIError) as e: logger.debug(f"got exception trying to commit updated tenant object to db. Exception: {e}") msg = utils.get_message_from_sql_exc(e) logger.debug(f"returning msg: {msg}") raise errors.ResourceError(f"Invalid PUT data; {msg}") logger.debug("returning serialized tenant object.") return utils.ok(result=tenant.serialize, msg="Tenant updated successfully.")
def post(self): logger.debug(f"top of POST /tenants") validator = RequestValidator(utils.spec) result = validator.validate(FlaskOpenAPIRequest(request)) if result.errors: logger.debug(f"openapi_core validation failed. errors: {result.errors}") raise errors.ResourceError(msg=f'Invalid POST data: {result.errors}.') validated_body = result.body logger.debug(f"initial openapi_core validation passed. validated_body: {dir(validated_body)}") # check reserved words "owners" and "ldaps" -- these cannot be tenant id's: try: if validated_body.tenant_id.lower() == 'owners': raise errors.ResourceError("Invalid tenant_id; 'owners' is a reserved keyword.") if validated_body.tenant_id.lower() == 'ldaps': raise errors.ResourceError("Invalid tenant_id; 'ldaps' is a reserved keyword.") if validated_body.tenant_id.lower() == 'ready': raise errors.ResourceError("Invalid tenant_id; 'ready' is a reserved keyword.") if validated_body.tenant_id.lower() == 'hello': raise errors.ResourceError("Invalid tenant_id; 'hello' is a reserved keyword.") except Exception as e: msg = f"Could not check tenant description for reserved words; Errors: {e}" logger.error(msg) raise errors.ResourceError(msg) logger.debug("got past the reserved words check.") # validate the existence of the site object: try: site_id = validated_body.site_id site = Site.query.filter_by(site_id=site_id).first() except Exception as e: logger.error(f"Got exception trying to retrieve site; e: {e}") raise errors.ResourceError(msg='Invalid tenant description; could not verify site_id.') if not site: raise errors.ResourceError(msg=f'Invalid tenant description. site {validated_body.site_id} not found.') logger.debug(f"site_id {site_id} is ok.") # validate the existence of the ldap and owner objects: owner = TenantOwner.query.filter_by(email=validated_body.owner).first() if not owner: raise errors.ResourceError(msg=f'Invalid tenant description. Owner {validated_body.owner} not found.') logger.debug("owner was valid.") # ldap objects are optional: if getattr(validated_body, 'user_ldap_connection_id', None): ldap = LDAPConnection.query.filter_by(ldap_id=validated_body.user_ldap_connection_id).first() if not ldap: raise errors.ResourceError(msg=f'Invalid tenant description. ' f'LDAP {validated_body.user_ldap_connection_id} not found.') if getattr(validated_body, 'service_ldap_connection_id', None) and \ not validated_body.service_ldap_connection_id == getattr(validated_body, 'user_ldap_connection_id', None): ldap = LDAPConnection.query.filter_by(ldap_id=validated_body.service_ldap_connection_id).first() if not ldap: raise errors.ResourceError(msg=f'Invalid tenant description. ' f'LDAP {validated_body.service_ldap_connection_id} not found.') logger.debug("ldap was valid; creating tenant record..") # create the tenant record -- tenant = Tenant(tenant_id=validated_body.tenant_id, base_url=validated_body.base_url, site_id=validated_body.site_id, status=validated_body.status, public_key=getattr(validated_body, 'public_key', None), token_service=validated_body.token_service, security_kernel=validated_body.security_kernel, authenticator=validated_body.authenticator, owner=validated_body.owner, admin_user=validated_body.admin_user, token_gen_services=validated_body.token_gen_services, service_ldap_connection_id=getattr(validated_body, 'service_ldap_connection_id', None), user_ldap_connection_id=getattr(validated_body, 'user_ldap_connection_id', None), description=getattr(validated_body, 'description', None), create_time=datetime.datetime.utcnow(), created_by=f'{g.username}@{g.tenant_id}', last_updated_by=f'{g.username}@{g.tenant_id}', last_update_time=datetime.datetime.utcnow()) db.session.add(tenant) try: db.session.commit() logger.info(f"new tenant committed to db. tenant object: {tenant}") except (sqlalchemy.exc.SQLAlchemyError, sqlalchemy.exc.DBAPIError) as e: logger.debug(f"got exception trying to commit new tenant object to db. Exception: {e}") msg = utils.get_message_from_sql_exc(e) logger.debug(f"returning msg: {msg}") raise errors.ResourceError(f"Invalid POST data; {msg}") logger.debug("returning serialized tenant object.") return utils.ok(result=tenant.serialize, msg="Tenant created successfully.")
from sqlalchemy import func from sqlalchemy.exc import IntegrityError from penguin_judge.models import (transaction, scoped_session, Contest, Environment, JudgeResult, JudgeStatus, Problem, Submission, TestCase, Token, User, Worker) from penguin_judge.mq import get_mq_conn_params from penguin_judge.utils import json_dumps, pagination_header DEFAULT_MEMORY_LIMIT = 256 # MiB app = Flask(__name__) with open(os.path.join(os.path.dirname(__file__), 'schema.yaml'), 'r') as f: _spec = create_spec(yaml.safe_load(f)) _request_validator = RequestValidator(_spec) def response204() -> Response: resp = make_response((b'', 204)) resp.headers.pop(key='content-type') return resp def jsonify(resp: Union[dict, list], *, status: Optional[int] = None, headers: Optional[Dict[str, str]] = None) -> Response: return app.response_class(json_dumps(resp), mimetype=app.config["JSONIFY_MIMETYPE"], status=status,
from flask import Flask, request import json import os from openapi_core import create_spec from openapi_core.shortcuts import RequestValidator from openapi_core.wrappers.flask import FlaskOpenAPIRequest from pprint import pprint app = Flask(__name__) with open(f"{os.path.dirname(os.path.abspath(__file__))}/openapi.json") as f: openapi_file = json.load(f) spec = create_spec(openapi_file) validator = RequestValidator(spec) @app.before_request def validate(): openapi_request = FlaskOpenAPIRequest(request) result = validator.validate(openapi_request) if result.errors: pprint(result.errors) @app.route("/cars", methods=["POST"]) def new_car(): # creating new car: pprint(request.json) return "created"