示例#1
0
    def test_multiple_values(self, request_factory, request):
        request = request_factory('GET',
                                  '/',
                                  subdomain='www',
                                  query_string='a=b&a=c')

        openapi_request = FlaskOpenAPIRequest(request)

        path = {}
        query = ImmutableMultiDict([
            ('a', 'b'),
            ('a', 'c'),
        ])
        headers = EnvironHeaders(request.environ)
        cookies = {}
        assert openapi_request.parameters == {
            'path': path,
            'query': query,
            'header': headers,
            'cookie': cookies,
        }
        assert openapi_request.host_url == request.host_url
        assert openapi_request.path == request.path
        assert openapi_request.method == request.method.lower()
        assert openapi_request.path_pattern == request.path
        assert openapi_request.body == request.data
        assert openapi_request.mimetype == request.mimetype
示例#2
0
    def post(self):
        logger.debug("top of  POST /tokens")
        # try:
        validator = RequestValidator(utils.spec)
        validated = validator.validate(FlaskOpenAPIRequest(request))
        if validated.errors:
            raise errors.ResourceError(
                msg=f'Invalid POST data: {validated.errors}.')
        validated_body = validated.body
        # this raises an exception of the claims are invalid -
        if hasattr(validated_body, 'extra_claims'):
            check_extra_claims(validated_body.extra_claims)
        token_data = TapisAccessToken.get_derived_values(validated_body)
        access_token = TapisAccessToken(**token_data)
        access_token.sign_token()
        result = {}
        result['access_token'] = access_token.serialize

        # refresh token --
        if hasattr(validated_body, 'generate_refresh_token'
                   ) and validated_body.generate_refresh_token:
            refresh_token = TokensResource.get_refresh_from_access_token_data(
                token_data, access_token)
            result['refresh_token'] = refresh_token.serialize
        return utils.ok(result=result, msg="Token generation successful.")
示例#3
0
    def post(self):
        logger.debug("top of  POST /tokens")
        validator = RequestValidator(utils.spec)
        validated = validator.validate(FlaskOpenAPIRequest(request))
        if validated.errors:
            raise errors.ResourceError(msg=f'Invalid POST data: {validated.errors}.')
        validated_body = validated.body
        # this raises an exception if the claims are invalid -
        if hasattr(validated_body, 'claims'):
            check_extra_claims(request.json.get('claims'))
            # set it to the raw request's claims object which is an arbitrary python dictionary
            validated_body.claims = request.json.get('claims')
        try:
            token_data = TapisAccessToken.get_derived_values(validated_body)
        except Exception as e:
            logger.error(f"Got exception trying to compute get_derived_values() for validated body; e: {e}")
            raise errors.AuthenticationError("Unable to create token. Please contact system administrator.")
        access_token = TapisAccessToken(**token_data)
        try:
            access_token.sign_token()
        except Exception as e:
            logger.error(f"Got exception trying to sign token! Exception: {e}")
            raise errors.AuthenticationError("Unable to sign token. Please contact system administrator.")

        result = {'access_token': access_token.serialize}

        # refresh token --
        if hasattr(validated_body, 'generate_refresh_token') and validated_body.generate_refresh_token:
            if hasattr(validated_body, 'refresh_token_ttl'):
                token_data['refresh_token_ttl'] = validated_body.refresh_token_ttl
            refresh_token = TokensResource.get_refresh_from_access_token_data(token_data, access_token)
            result['refresh_token'] = refresh_token.serialize
        return utils.ok(result=result, msg="Token generation successful.")
示例#4
0
 def put(self):
     logger.debug("top of  PUT /tokens/keys")
     validator = RequestValidator(utils.spec)
     validated = validator.validate(FlaskOpenAPIRequest(request))
     if validated.errors:
         raise errors.ResourceError(msg=f'Invalid PUT data: {validated.errors}.')
     tenant_id = validated.body.tenant_id
     logger.debug(f"calling check_authz_private_keypair with tenant_id {tenant_id}")
     check_authz_private_keypair(tenant_id)
     logger.debug("returned from check_authz_private_keypair; updating keys...")
     private_key, public_key = generate_private_keypair_in_sk(tenant_id)
     # update the tenant definition with the new public key
     logger.debug(f"making request to update tenant {tenant_id} with new public key.")
     try:
         t.tenants.update_tenant(tenant_id=tenant_id, public_key=public_key)
     except Exception as e:
         logger.error(f"Got exception trying to update tenant with new public key. Tenants API"
                      f"and SK are now out of sync!! SHOULD BE LOOKED AT IMMEDIATELY. "
                      f"Exception: {e}")
         raise errors.ResourceError(msg=f'Unable to update tenant definition with new public key'
                                        f'Please contact system administrators.')
     logger.info(f"tenant {tenant_id} has been updated with the new public key.")
     # update token's tenant cache with this private key for signing:
     logger.debug("updating token cache...")
     for tenant in tenants.tenants:
         if tenant.tenant_id == tenant_id:
             tenant.private_key = private_key
     result = {'public_key': public_key}
     return utils.ok(result=result, msg="Tenant signing keys update successful.")
示例#5
0
 def put(self):
     try:
         validator = RequestValidator(utils.spec)
         validated = validator.validate(FlaskOpenAPIRequest(request))
         if validated.errors:
             raise errors.ResourceError(
                 msg=f'Invalid PUT data: {validated.errors}.')
         refresh_token = validated.body.refresh_token
         refresh_token_data = auth.validate_token(refresh_token)
         token_data = refresh_token_data['access_token']
         token_data.pop('token_type')
         token_data['exp'] = TapisAccessToken.compute_exp(token_data['ttl'])
         access_token = TapisAccessToken(**token_data)
         access_token.sign_token()
         refresh_token = TokensResource.get_refresh_from_access_token_data(
             token_data, access_token)
         result = {
             'access_token': access_token.serialize,
             'refres_token': refresh_token.serialize
         }
         return utils.ok(result=result, msg="Token generation successful.")
     except Exception as e:
         # return utils.ok(result="Got exception", msg=f"{refresh_token.serialize}")
         return utils.ok(result="Got exception",
                         msg=f"Exception: {traceback.format_exc()}")
示例#6
0
 def post(self):
     logger.debug("top of POST /ldaps")
     validator = RequestValidator(utils.spec)
     result = validator.validate(FlaskOpenAPIRequest(request))
     if result.errors:
         raise errors.ResourceError(msg=f'Invalid POST data: {result.errors}.')
     validated_params = result.parameters
     validated_body = result.body
     logger.debug(f"validated_body: {dir(validated_body)}")
     ldap = LDAPConnection(ldap_id=validated_body.ldap_id,
                           url=validated_body.url,
                           port=validated_body.port,
                           use_ssl=validated_body.use_ssl,
                           user_dn=validated_body.user_dn,
                           bind_dn=validated_body.bind_dn,
                           bind_credential=validated_body.bind_credential,
                           account_type=validated_body.account_type,
                           create_time=datetime.datetime.utcnow(),
                           last_update_time = datetime.datetime.utcnow())
     db.session.add(ldap)
     try:
         db.session.commit()
     except (sqlalchemy.exc.SQLAlchemyError, sqlalchemy.exc.DBAPIError) as e:
         msg = utils.get_message_from_sql_exc(e)
         raise errors.ResourceError(f"Invalid POST data; {msg}")
     return utils.ok(result=ldap.serialize,
                     msg="LDAP object created successfully.")
示例#7
0
    def post(self):
        logger.debug("top of POST /sites")
        validator = RequestValidator(utils.spec)
        result = validator.validate(FlaskOpenAPIRequest(request))
        logger.debug(f"just got result {result.parameters}")
        if result.errors:
            logger.debug(f"error in results!!!!!!!!")
            raise errors.ResourceError(msg=f'Invalid POST data: {result.errors}')
        validated_params = result.parameters
        logger.debug('got validated params')
        validated_body = result.body
        logger.debug(f'got validated body {dir(validated_body)}')
        try:
            # request is trying to create the primary site:
            if validated_body.primary:
                logger.debug('checks for primary site')
                primary_site = Site.query.filter_by(primary=True).first()
                if primary_site:
                    raise errors.ResourceError("Invalid site description: a primary site already exists.")
                if not validated_body.tenant_base_url_template:
                    raise errors.ResourceError("Invalid site description: tenant_base_url_template is required for primary site.")
                site = Site(site_id=validated_body.site_id,
                            primary=validated_body.primary,
                            base_url=validated_body.base_url,
                            tenant_base_url_template=validated_body.tenant_base_url_template,
                            site_admin_tenant_id=validated_body.site_admin_tenant_id,
                            services=validated_body.services,
                            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())

            # request if for an associate site:
            else:
                logger.debug(f'checks for associate site.')
                if hasattr(validated_body, 'tenant_base_url_template') and validated_body.tenant_base_url_template:
                    raise errors.ResourceError("Invalid site description; "
                                               "the tenant_base_url_template property only applies to primary sites.")
                site = Site(site_id=validated_body.site_id,
                            primary=False,
                            base_url=validated_body.base_url,
                            site_admin_tenant_id=validated_body.site_admin_tenant_id,
                            services=validated_body.services,
                            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())
            logger.info(f'creating site {validated_body.site_id}')
        except Exception as e:
            raise errors.ResourceError(f"Invalid POST data; {e}")
        db.session.add(site)
        try:
            db.session.commit()
        except (sqlalchemy.exc.SQLAlchemyError, sqlalchemy.exc.DBAPIError) as e:
            msg = utils.get_message_from_sql_exc(e)
            raise errors.ResourceError(f"Invalid POST data; {msg}")
        logger.info(f"site {validated_body.site_id} saved in db.")
        return utils.ok(result=site.serialize,
                        msg="Site object created successfully.")
示例#8
0
 def test_response_validator_path_pattern(self, flask_spec, request_factory,
                                          response_factory):
     validator = ResponseValidator(flask_spec)
     request = request_factory('GET', '/browse/12/', subdomain='kb')
     openapi_request = FlaskOpenAPIRequest(request)
     response = response_factory('Some item', status_code=200)
     openapi_response = FlaskOpenAPIResponse(response)
     result = validator.validate(openapi_request, openapi_response)
     assert not result.errors
示例#9
0
def after_request(response):
    wrapped_req = FlaskOpenAPIRequest(request)
    wrapped_resp = FlaskOpenAPIResponse(response)
    validation_result = response_validator.validate(wrapped_req, wrapped_resp)
    if validation_result.errors:
        logger.error("Error on response: {}, {}"
                     .format(response.response, validation_result.errors))
        raise err.DeveloperError("; ".join([str(err) for err in validation_result.errors]))
    return response
示例#10
0
 def post(self):
     validator = RequestValidator(utils.spec)
     result = validator.validate(FlaskOpenAPIRequest(request))
     if result.errors:
         raise errors.ResourceError(
             msg=f'Invalid POST data: {result.errors}.')
     validated_body = result.body
     data = Client.get_derived_values(validated_body)
     client = Client(**data)
     db.session.add(client)
     db.session.commit()
     return utils.ok(result=client.serialize,
                     msg="Client created successfully.")
示例#11
0
def before_request():
    # Service alive check can skip validation
    if request.path == "/ping":
        return {"success": True}
    wrapped_req = FlaskOpenAPIRequest(request)
    validation_result = request_validator.validate(wrapped_req)
    if validation_result.errors:
        raise err.InvalidRequest("; ".join([str(err) for err in validation_result.errors]))
    token = request.headers.get("Authorization", "").replace("Bearer ", "")
    auth_state = TOKEN_CHECKER.check_token(token)
    if not auth_state.identities:
        # Return auth errors for debugging - may change in prod for security
        raise err.NoAuthentication("; ".join([str(err) for err in auth_state.errors]))
    request.auth = auth_state
示例#12
0
    def put(self):
        logger.debug("top of  PUT /tokens")
        validator = RequestValidator(utils.spec)
        validated = validator.validate(FlaskOpenAPIRequest(request))
        if validated.errors:
            raise errors.ResourceError(msg=f'Invalid PUT data: {validated.errors}.')
        refresh_token = validated.body.refresh_token
        logger.debug(f"type(refresh_token) = {type(refresh_token)}")
        try:
            refresh_token_data = auth.validate_token(refresh_token)
        except errors.AuthenticationError:
            raise errors.ResourceError(msg=f'Invalid PUT data: {request}.')

        # get the original access_token data from within the decoded refresh_token
        token_data = refresh_token_data['tapis/access_token']
        token_data.pop('tapis/token_type')
        token_data['exp'] = TapisAccessToken.compute_exp(token_data['ttl'])
        token_data['jti'] = str(uuid.uuid4())
        # create a dictionary of data that can be used to instantiate access and refresh tokens; the constructors
        # require variable names that do not include the Tapis prefix, so we need to remove that -
        new_token_data = { 'jti': token_data.pop('jti'),
                           'iss': token_data.pop('iss'),
                           'sub': token_data.pop('sub'),
                           'tenant_id': token_data.pop('tapis/tenant_id'),
                           'username': token_data.pop('tapis/username'),
                           'account_type': token_data.pop('tapis/account_type'),
                           'ttl': token_data.pop('ttl'),
                           'exp': token_data.pop('exp'),
                           'delegation': token_data.pop('tapis/delegation'),
                           'delegation_sub': token_data.pop('tapis/delegation_sub', None),
                           'extra_claims': token_data
                           }
        access_token = TapisAccessToken(**new_token_data)
        access_token.sign_token()

        # add the original refresh token's initial_ttl claim as the ttl for the new refresh token
        new_token_data['refresh_token_ttl'] = refresh_token_data['tapis/initial_ttl']
        refresh_token = TokensResource.get_refresh_from_access_token_data(new_token_data, access_token)
        result = {'access_token': access_token.serialize,
                  'refresh_token': refresh_token.serialize
                  }
        return utils.ok(result=result, msg="Token generation successful.")
示例#13
0
def test_healthz(client):
    """Test the /healthz endpoint."""

    path = '/v1/healthz'
    rv = client.get(path)

    # Validate request and response against OpenAPI spec
    with app.test_request_context(path):
        with open(app.config['OPENAPI_SPEC']) as stream:
            spec = create_spec(safe_load(stream))

        openapi_response = FlaskOpenAPIResponse(rv)
        openapi_request = FlaskOpenAPIRequest(request)
        validator = ResponseValidator(spec)
        result = validator.validate(openapi_request, openapi_response)
        result.raise_for_errors()

    assert rv.content_type == "text/plain"
    assert rv.status_code == 200
    assert b'OK' in rv.data
示例#14
0
    def test_url_rule(self, request_factory, request):
        request = request_factory('GET', '/browse/12/', subdomain='kb')

        openapi_request = FlaskOpenAPIRequest(request)

        path = {'id': 12}
        query = ImmutableMultiDict([])
        headers = EnvironHeaders(request.environ)
        cookies = {}
        assert openapi_request.parameters == {
            'path': path,
            'query': query,
            'header': headers,
            'cookie': cookies,
        }
        assert openapi_request.host_url == request.host_url
        assert openapi_request.path == request.path
        assert openapi_request.method == request.method.lower()
        assert openapi_request.path_pattern == request.url_rule.rule
        assert openapi_request.body == request.data
        assert openapi_request.mimetype == request.mimetype
示例#15
0
 def post(self):
     logger.debug(f"top of POST /owners")
     validator = RequestValidator(utils.spec)
     result = validator.validate(FlaskOpenAPIRequest(request))
     if result.errors:
         raise errors.ResourceError(msg=f'Invalid POST data: {result.errors}.')
     validated_params = result.parameters
     validated_body = result.body
     owner = TenantOwner(name=validated_body.name,
                         email=validated_body.email,
                         institution=validated_body.institution,
                         create_time=datetime.datetime.utcnow(),
                         last_update_time=datetime.datetime.utcnow()
                         )
     db.session.add(owner)
     try:
         db.session.commit()
     except (sqlalchemy.exc.SQLAlchemyError, sqlalchemy.exc.DBAPIError) as e:
         msg = utils.get_message_from_sql_exc(e)
         raise errors.ResourceError(f"Invalid POST data; {msg}")
     return utils.ok(result=owner.serialize,
                     msg="Owner object created successfully.")
示例#16
0
 def openapi_request(self, request):
     return FlaskOpenAPIRequest(request)
示例#17
0
    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.")
示例#18
0
    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.")
示例#19
0
def validate():
    openapi_request = FlaskOpenAPIRequest(request)
    result = validator.validate(openapi_request)

    if result.errors:
        pprint(result.errors)
示例#20
0
 def test_request_validator_path_pattern(self, flask_spec, request_factory):
     validator = RequestValidator(flask_spec)
     request = request_factory('GET', '/browse/12/', subdomain='kb')
     openapi_request = FlaskOpenAPIRequest(request)
     result = validator.validate(openapi_request)
     assert not result.errors