Ejemplo n.º 1
0
    def get_instance(cls, item=None, failsafe=False):
        """
        :param item: instance id or dict { "id" : .. "type" : ..}
        :param failsafe: indicates whether we want an exception to be raised in case the id is not found
        :return: Instance or None. An error is raised if an invalid id is used
        """
        instance = None
        # pylint: disable=invalid-name,redefined-builtin
        if isinstance(item, dict):
            id = item.get("id", None)
            if id is None:
                raise ValidationError("Invalid id")
            if item.get("type") != cls._s_type:
                raise ValidationError("Invalid item type")
        else:
            id = item
        try:
            primary_keys = cls.id_type.get_pks(id)
        except AttributeError:  # pragma: no cover
            # This happens when we request a sample from a class that is not yet loaded
            # when we're creating the swagger models
            safrs.log.debug('AttributeError for class "{}"'.format(
                cls.__name__))
            return instance  # instance is None!

        if id is not None or not failsafe:
            try:
                instance = cls._s_query.filter_by(**primary_keys).first()
            except Exception as exc:  # pragma: no cover
                raise GenericError("get_instance : {}".format(exc))

            if not instance and not failsafe:
                raise NotFoundError('Invalid "{}" ID "{}"'.format(
                    cls.__name__, id))
        return instance
Ejemplo n.º 2
0
 def __init__(self, **kwargs):
     for key, value in kwargs.items():
         # here, the properties variable is the one passed to the
         # ClassFactory call
         if key not in properties:
             raise ValidationError("Argument {} not valid for {}".format(key, self.__class__.__name__))
         setattr(self, key, value)
Ejemplo n.º 3
0
    def _s_parse_attr_value(self, attr_name, attr_val):
        """
        Parse the given jsonapi attribute value so it can be stored in the db
        :param attr_name: attribute name
        :param attr_val: attribute value
        :return: parsed value
        """
        # Don't allow attributes from web requests that are not specified in _s_jsonapi_attrs
        if not has_request_context():
            # we only care about parsing when working in the request context
            return attr_val

        if attr_name == "id":
            return attr_val

        attr = self.__class__._s_jsonapi_attrs.get(attr_name, None)

        if is_jsonapi_attr(attr):
            return attr_val

        # attr is a sqlalchemy.sql.schema.Column now
        if not isinstance(attr, Column):  # pragma: no cover
            raise ValidationError("Not a column: {}".format(attr))

        return parse_attr(attr, attr_val)
Ejemplo n.º 4
0
    def process_bind_param(self, value, dialect):

        try:
            uuid.UUID(value, version=4)
        except:
            raise ValidationError('UUID Validation Error {}'.format(value))

        return value
Ejemplo n.º 5
0
    def _s_filter(cls, *filter_args, **filter_kwargs):
        """
        Apply a filter to this model
        :param filter_args: A list of filters information to apply, passed as a request URL parameter.
        Each filter object has the following fields:
          - name: The name of the field you want to filter on.
          - op: The operation you want to use (all sqlalchemy operations are available). The valid values are:
              - eq: check if field is equal to something
              - ge: check if field is greater than or equal to something
              - gt: check if field is greater than to something
              - ne: check if field is not equal to something
              - is_: check if field is a value
              - is_not: check if field is not a value
              - le: check if field is less than or equal to something
              - lt: check if field is less than to something
          - val: The value that you want to compare.
        :return: sqla query object
        """
        try:
            filters = json.loads(filter_args[0])
        except json.decoder.JSONDecodeError:
            raise ValidationError(
                "Invalid filter format (see https://github.com/thomaxxl/safrs/wiki)"
            )

        if not isinstance(filters, list):
            filters = [filters]
        expressions = []
        for filt in filters:
            attr_name = filt.get("name")
            if attr_name not in cls._s_jsonapi_attrs:
                raise ValidationError(
                    'Invalid filter "{}", unknown attribute "{}"'.format(
                        filt, attr_name))

            op_name = filt.get("op", "").strip("_")
            if not hasattr(operator, op_name):
                raise ValidationError(
                    'Invalid filter "{}", unknown operator "{}"'.format(
                        filt, op_name))

            attr = cls._s_jsonapi_attrs[attr_name]
            op = getattr(operator, op_name)
            expressions.append(op(attr, filt.get("val")))
        return cls._s_query.filter(*expressions)
Ejemplo n.º 6
0
 def validate_id(cls, id):
     return
     for pk in id.split(cls.delimiter):
         try:
             cls.column.type(pk)
             uuid.UUID(pk, version=4)
             #return pk
         except:
             raise ValidationError('Invalid ID')
Ejemplo n.º 7
0
 def validate_id(cls, id):
     '''
         Validate a given id (eg. check if it's a valid uuid, email etc.)
     '''
     return
     for pk in id.split(cls.delimiter):
         try:
             cls.column.type(pk)
             uuid.UUID(pk, version=4)
             #return pk
         except:
             raise ValidationError('Invalid ID')
Ejemplo n.º 8
0
def schema_from_object(name, object):
    def replace_None(object):
        # None aka "null" is invalid in swagger schema definition => recursively replace all "None" by ""
        if object is None:
            return ''
        if isinstance(object, dict):
            result = {}
            for k, v in object.items():
                v = replace_None(v)
                result[k] = v
            return result
        if isinstance(object, list):
            result = []
            for i in object:
                result.append(replace_None(i))
            return result
        return object

    properties = {}

    if isinstance(object, str):
        properties = {'example': k, 'type': 'string'}

    elif isinstance(object, int):
        properties = {'example': k, 'type': 'integer'}

    elif isinstance(object, dict):
        for k, v in object.items():
            if isinstance(v, str):
                properties[k] = {'example': v, 'type': 'string'}
            if isinstance(v, int):
                properties[k] = {'example': v, 'type': 'integer'}
            if isinstance(v, (dict, list)):
                if isinstance(v, dict):
                    v = replace_None(v)
                properties[k] = {'example': v, 'type': 'string'}
            if v is None:
                properties[k] = {'example': "", 'type': 'string'}
    else:
        raise ValidationError('Invalid schema object type {}'.format(
            type(object)))

    # generate a unique name to be used as a reference
    idx = _references.count(name)
    if idx:
        name = name + str(idx)
    #name = urllib.parse.quote(name)
    _references.append(name)
    return SchemaClassFactory(name, properties)
Ejemplo n.º 9
0
def schema_from_object(name, object):
    """
        :param name:
        :param object:
        :return: swagger schema object
    """

    properties = {}

    if isinstance(object, str):
        properties = {"example": "", "type": "string"}

    elif isinstance(object, int):
        properties = {"example": 0, "type": "integer"}

    elif isinstance(object, (datetime.datetime, datetime.date)):
        properties = {"example": str(k), "type": "string"}

    elif isinstance(object, dict):
        for k, v in object.items():
            if isinstance(v, str):
                properties[k] = {"example": v, "type": "string"}
            elif isinstance(v, int):
                properties[k] = {"example": v, "type": "integer"}
            elif isinstance(v, (dict, list)):
                if isinstance(v, dict):
                    v = encode_schema(v)
                properties[k] = {"example": v, "type": "string"}
            elif v is None:
                properties[k] = {"example": "", "type": "string"}
            else:  # isinstance(object, datetime.datetime):
                properties = {"example": str(k), "type": "string"}
                safrs.log.warning("Invalid schema object type %s",
                                  type(object))
    else:
        raise ValidationError("Invalid schema object type {}".format(
            type(object)))

    # generate a unique name to be used as a reference
    idx = _references.count(name)
    if idx:
        name = name + str(idx)
    # name = urllib.parse.quote(name)
    _references.append(name)
    return SchemaClassFactory(name, properties)
Ejemplo n.º 10
0
def schema_from_object(name, object):
    def replace_None(object):
        # None aka "null" is invalid in swagger schema definition => recursively replace all "None" by ""
        if object is None:
            return ''
        if type(object) is dict:
            result = {}
            for k, v in object.items():
                v = replace_None(v)
                result[k] = v
            return result
        if type(object) is list:
            result = []
            for i in object:
                result.append(replace_None(i))
            return result
        return object

    properties = {}

    if type(object) == str:
        properties = {'example': k, 'type': 'string'}

    elif type(object) == int:
        properties = {'example': k, 'type': 'integer'}

    elif type(object) == dict:
        for k, v in object.items():
            if type(v) == str:
                properties[k] = {'example': v, 'type': 'string'}
            if type(v) == int:
                properties[k] = {'example': v, 'type': 'integer'}
            if type(v) == dict or type(v) == list:
                if type(v) == dict:
                    v = replace_None(v)
                properties[k] = {'example': v, 'type': 'string'}
            if v is None:
                properties[k] = {'example': "", 'type': 'string'}
    else:
        raise ValidationError('Invalid schema object type {}'.format(
            type(object)))

    # generate random name
    return SchemaClassFactory(name + str(uuid.uuid4()), properties)
Ejemplo n.º 11
0
    def _s_check_perm(cls, property_name, permission="r"):
        """
        Check the (class-level) column permission
        :param column_name: column name
        :param permission: permission string (read/write)
        :return: Boolean indicating whether access is allowed
        """
        if property_name.startswith("_"):
            return False

        if property_name in cls.exclude_attrs:
            return False

        for rel in cls.__mapper__.relationships:
            if not cls.supports_includes:
                continue
            if rel.key != property_name:
                continue
            if rel.key in cls.exclude_rels:
                # relationship name has been set in exclude_rels
                return False
            if not getattr(rel.mapper.class_, "_s_expose", False):
                # only SAFRSBase instances can be exposed
                return False
            if not getattr(rel, "expose", True):
                # relationship `expose` attribute has explicitly been set to False
                return False
            return True

        for column in cls.__mapper__.columns:
            # don't expose attributes starting with an underscore
            if cls.colname_to_attrname(column.name) != property_name:
                continue
            if getattr(column, "expose", True) and permission in getattr(
                    column, "permissions", "rw"):
                return True
            return False

        if is_jsonapi_attr(cls.__dict__.get(property_name,
                                            None)):  # avoid getattr here
            return True

        raise ValidationError("Invalid property {}".format(property_name))
Ejemplo n.º 12
0
def schema_from_object(name, object):
    """
        :param name:
        :param object:
        :return: swagger schema object
    """

    properties = {}

    if isinstance(object, str):
        properties = {"example": "", "type": "string"}

    elif isinstance(object, int):
        properties = {"example": 0, "type": "integer"}

    elif isinstance(object, (datetime.datetime, datetime.date, datetime.time)):
        properties = {"example": str(object), "type": "string"}

    elif isinstance(object, dict):
        for k, v in object.items():
            if isinstance(v, str):
                properties[k] = {"example": v, "type": "string"}
            elif isinstance(v, int):
                properties[k] = {"example": v, "type": "integer"}
            elif isinstance(v, (dict, list)):
                if isinstance(v, dict):
                    v = encode_schema(v)
                properties[k] = {"example": v, "type": "string"}
            elif v is None:
                # swagger doesn't allow null values
                properties[k] = {"example": "", "type": "string"}
            else:  # isinstance(object, datetime.datetime):
                properties = {"example": str(k), "type": "string"}
                safrs.log.warning("Invalid schema object type %s",
                                  type(object))
    else:
        raise ValidationError("Invalid schema object type {}".format(
            type(object)))

    properties = encode_schema(properties)
    schema = SchemaClassFactory(name, properties)
    return schema
Ejemplo n.º 13
0
def schema_from_object(name, object):
    '''
    schema_from_object
    '''

    properties = {}

    if isinstance(object, str):
        properties = {'example': k, 'type': 'string'}

    elif isinstance(object, int):
        properties = {'example': k, 'type': 'integer'}

    elif isinstance(object, (datetime.datetime, datetime.date)):
        properties = {'example': str(k), 'type': 'string'}
    elif isinstance(object, dict):
        for k, v in object.items():
            if isinstance(v, str):
                properties[k] = {'example': v, 'type': 'string'}
            elif isinstance(v, int):
                properties[k] = {'example': v, 'type': 'integer'}
            elif isinstance(v, (dict, list)):
                if isinstance(v, dict):
                    v = encode_schema(v)
                properties[k] = {'example': v, 'type': 'string'}
            elif v is None:
                properties[k] = {'example': "", 'type': 'string'}
            else:  #isinstance(object, datetime.datetime):
                properties = {'example': str(k), 'type': 'string'}
                LOGGER.warning('Invalid schema object type %s', type(object))
    else:
        raise ValidationError('Invalid schema object type {}'.format(
            type(object)))

    # generate a unique name to be used as a reference
    idx = _references.count(name)
    if idx:
        name = name + str(idx)
    #name = urllib.parse.quote(name)
    _references.append(name)
    return SchemaClassFactory(name, properties)
Ejemplo n.º 14
0
def parse_object_doc(object):
    '''
        Parse the yaml description from the "documented_api_method"-decorated methods
    '''

    api_doc = {}
    obj_doc = str(inspect.getdoc(object))
    yaml_doc = None
    raw_doc = obj_doc.split(DOC_DELIMITER)[0]
    try:
        yaml_doc = yaml.load(raw_doc)
    except SyntaxError:
        pass

    except Exception as e:
        raise ValidationError('Failed to parse api doc')

    if isinstance(yaml_doc, dict):
        api_doc.update(yaml_doc)

    return api_doc
Ejemplo n.º 15
0
def parse_object_doc(object):
    '''
        Parse the yaml description from the documented methods
    '''
    api_doc = {}
    obj_doc = str(inspect.getdoc(object))
    raw_doc = obj_doc.split(DOC_DELIMITER)[0]
    yaml_doc = None

    try:
        yaml_doc = yaml.load(raw_doc)
    except (SyntaxError, yaml.scanner.ScannerError) as exc:
        LOGGER.error('Failed to parse documentation %s', raw_doc)
        yaml_doc = {'description': raw_doc}

    except Exception as e:
        raise ValidationError('Failed to parse api doc')

    if isinstance(yaml_doc, dict):
        api_doc.update(yaml_doc)

    return api_doc
Ejemplo n.º 16
0
def parse_object_doc(object):
    """
        Parse the yaml description from the documented methods
    """
    api_doc = {}
    obj_doc = str(inspect.getdoc(object))
    raw_doc = obj_doc.split(DOC_DELIMITER)[0]
    yaml_doc = None

    try:
        yaml_doc = yaml.safe_load(raw_doc)
    except (SyntaxError, yaml.scanner.ScannerError) as exc:
        safrs.log.error("Failed to parse documentation {} ({})".format(raw_doc, exc))
        yaml_doc = {"description": raw_doc}

    except Exception as exc:
        raise ValidationError("Failed to parse api doc")

    if isinstance(yaml_doc, dict):
        api_doc.update(yaml_doc)

    return api_doc
Ejemplo n.º 17
0
def schema_from_object(name, object):

    properties = {}

    if type(object) == str:
        properties = { 'example' : k, 'type' : 'string' }
    
    elif type(object) == int:
        properties = { 'example' : k, 'type' : 'integer' }

    elif type(object) == dict:
        for k, v in object.items():
            if type(v) == str:
                properties[k] = { 'example' : v, 'type' : 'string' }
            if type(v) == int:
                properties[k] = { 'example' : v, 'type' : 'integer' }
            if type(v) == dict or type(v) == list:
                properties[k] = { 'example' : v, 'type' : 'string' }
    else:
        raise ValidationError('Invalid schema object type {}'.format(type(object)))

    # generate random name 
    return SchemaClassFactory(name + str(uuid.uuid4()), properties)
Ejemplo n.º 18
0
 def validate_id(cls, id):
     try:
         uuid.UUID(id, version=4)
         return id
     except:
         raise ValidationError('Invalid ID')
Ejemplo n.º 19
0
    def process_bind_param(self, value, dialect):
        if value and not validate_email(value):
            raise ValidationError('Email Validation Error {}'.format(value))

        return value