Exemple #1
0
def _filter_fields(documents: [Document], filed_types=None):
    result = []

    def expected_field(inc, f_ids):
        attr_type = path(inc, 'attributes.field_type')
        if filed_types is not None and attr_type not in filed_types:
            return False
        return inc['type'] == 'dictionary' and inc['id'] in f_ids

    for doc in documents:
        ids = [d['id'] for d in path(doc.relationships, 'fields.data', [])]
        fields = [i for i in doc.included if expected_field(i, ids)]

        for field in fields:
            f_type = path(field, 'attributes.field_type')
            f_text = f_type.capitalize()
            f_name = path(field, 'attributes.name')
            response = {
                'id': f_name,
                'name': f'{f_text} Field: {f_name}',
                'icon_type': f_type,
                'group': {
                    'id': doc['id'],  # TODO: doc.id
                    'name': doc['name'],
                }
            }
            result.append(response)

    return result
Exemple #2
0
def handle_connection():
    """Handle bot connections.

    Gets notifications when the bot is added to a flow in an
    organization for the firs time.
    """
    contents = request.get_json()

    if not isinstance(contents, dict):
        raise BadRequest('No input data provided')

    data = contents.get('data')
    if not data or not isinstance(data, dict):
        raise BadRequest('Invalid payload, missed "data"')

    should_disconnect = path(contents, 'meta.disconnected') or False

    org_uid = path(data, 'relationships.organization.data.id')
    if not org_uid:
        raise ValidationError('Organization id is missed')

    logger.info(
        'Received %s webhook for organization %s' %
        (('disconnect' if should_disconnect else 'connect'), org_uid)
    )

    if should_disconnect:
        disconnect(org_uid)
        message = 'Organization disconnected.'
    else:
        connect(Organization.from_id(org_uid))
        message = 'Organization connected.'

    response = {'message': f'{message}'}
    return response, HTTPStatus.OK
Exemple #3
0
def create_request(data: dict):
    transformer = SettingsTransformer()

    return Request(
        path(data, 'meta.organization.data.id'),
        path(data, 'data.relationships.organization_addon.data.id'),
        path(data, 'data.relationships.slate.data.id'),
        path(data, 'data.attributes.setting_name'),
        transformer.transform(path(data, 'data.attributes.settings')),
    )
Exemple #4
0
    def _transform_setting(self, setting: dict):
        setting_type = str(setting.get('type', ''))

        # TODO: radio_group_manual, multiple_choice, sequence
        # TODO: fields_mapping, match, mapping, group
        if setting_type in [self.CHOICE, self.RADIO_GROUP_MANUAL]:
            return path(setting, 'data.value')
        else:
            # Otherwise return the data or None
            return path(setting, 'data')
Exemple #5
0
def documents_to_resource_fields(documents):
    result = []

    for document in documents:
        field = models.Field(
            rf_id=path(document, 'id'),
            name=path(document, 'name'),
        )
        result.append(field)

    return result
Exemple #6
0
def field_to_resource_fields(fields):
    result = []

    for field in fields:
        rf = models.Document(
            resource_id=path(field, 'id'),
            name=path(field, 'name'),
            resource_type=path(field, 'icon_type'),
            document_id=path(field, 'group.id'),
            document_name=path(field, 'group.name'),
        )
        result.append(rf)

    return result
Exemple #7
0
    def from_collection(cls, obj):
        """
        Create a list of instances of the current class from the provided data.
        """
        if 'data' not in obj:
            raise MissingData()

        data = obj['data']
        if len(data) == 0:
            return []

        entities = []
        for item in data:
            entity = cls(entity_id=None)

            if path(item, 'type', '') != entity.type:
                raise TypeMismatch()

            entity.__setstate__({
                'data': {
                    'id': path(item, 'id'),
                    'attributes': path(item, 'attributes', {}),
                    'relationships': path(item, 'relationships', {}),
                },
                'included': filter_included(
                    path(item, 'relationships', {}),
                    path(obj, 'included', [])
                ),
                'meta': path(item, 'meta', {}),
            })

            entities.append(entity)

        return entities
Exemple #8
0
 def fields(self, root):
     """Get all keys pointing to lists using `the_path` as a start point."""
     result = []
     first_object = path(self.contents, root)
     if isinstance(first_object, list) and len(first_object):
         first_object = first_object[0]
     if isinstance(first_object, dict):
         result = first_object.keys()
     return result
Exemple #9
0
def create_storage(settings, org_id):
    if 'json_url' in settings:
        return JsonUrlStorage(
            url=settings['json_url'],
            user_agent=os.environ.get('CRAWLER_USER_AGENT'),
            timeout=int(os.environ.get('CRAWLER_TIMEOUT', 5)),
        )

    if 'attachment' in settings:
        return JsonFileStorage(path(settings, 'attachment.file_id'), org_id)

    raise ValidationError('Invalid storage settings')
Exemple #10
0
    def to_dict(self):
        """Convert this model to a dictionary."""
        tags = []

        for name in path(self.data, 'names', []):
            tags.append({
                'type': 'flow_tags',
                'attributes': {
                    'name': name,
                },
            })

        return {'data': tags}
Exemple #11
0
    def has_one(self, cls, relation_name):
        """Create an instance of the related entity.

        :param cls: The class of the related entity
        :param relation_name: The name of the relation defined in the
            ``relationships`` dictionary
        :return: An instance of the related entity if any or None
        """
        if relation_name not in self.relationships:
            raise RelationNotExist()

        data = path(self.relationships, f'{relation_name}.data')
        if data is None:
            return None

        ids = (path(data, 'id'), path(data, 'type'))
        relations = [e for e in self.included if (e['id'], e['type']) == ids]

        if len(relations) == 0:
            return cls(path(data, 'id'))

        return cls.from_one({'data': relations})
Exemple #12
0
def authenticate(org_uid: str, client_id: str,
                 client_secret: str) -> AddonIdentity:
    client = Client(base_url=current_app.config.get('API_BASE_URI'))

    logger.info('Trying to authenticate bot %s for organization %s' %
                (client_id, org_uid))

    # We're expect a response in the following format:
    #    {
    #        'meta': {
    #            'token_type': 'Bearer',
    #            'expires': 1209000,
    #            'access_token': '...',
    #            'refresh_token': '...',
    #            'domain': '',
    #        }
    #    }
    #
    identity = client.addons.access_token(org_uid, client_id, client_secret)

    logger.info('Received identity response for organization %s: %s' %
                (org_uid, identity))

    if 'meta' not in identity:
        raise BadRequest(message='The `meta` field is required.')

    token = path(identity, 'meta.access_token')
    domain = path(identity, 'meta.domain')
    expires = path(identity, 'meta.expires')

    if expires and token and domain:
        expires = datetime.utcnow() + timedelta(seconds=int(expires))
        return AddonIdentity(token, domain, expires)

    fields = {'expires': expires, 'access_token': token, 'domain': domain}
    missed = [k for k in fields.keys() if not fields[k]]
    message = map(lambda f: f'The `meta.{f}` field is required.', missed)

    raise BadRequest(message=list(message))
Exemple #13
0
 def __setstate__(self, obj):
     """Play nice with pickle."""
     self.attributes = path(obj, 'data.attributes', {})
     self.attributes['id'] = path(obj, 'data.id')
     self.relationships = path(obj, 'data.relationships', {})
     self.included = path(obj, 'included', [])
     self.meta = path(obj, 'meta', {})
     self.object_meta = path(obj, 'data.meta', {})
Exemple #14
0
    def from_one(cls, obj):
        """Create an instance of the current class from the provided data."""
        if 'data' not in obj:
            raise MissingData()

        entity = cls(entity_id=None)
        if path(obj, 'data.type') != entity.type:
            raise TypeMismatch()

        entity.__setstate__({
            'data': {
                'id': path(obj, 'data.id'),
                'attributes': path(obj, 'data.attributes', {}),
                'relationships': path(obj, 'data.relationships', {}),
                'meta': path(obj, 'data.meta', {}),
            },
            'included': filter_included(
                path(obj, 'data.relationships', {}),
                path(obj, 'included', [])
            ),
            'meta': path(obj, 'meta', {}),
        })

        return entity
Exemple #15
0
    def has_many(self, cls, relation_name):
        """Create a list of instances of the related entities.

        :param cls: The class of the related entity
        :param relation_name: The name of the relation defined in the
            ``relationships`` dictionary
        :return: A list of instances of the related entities
        """
        if relation_name not in self.relationships:
            raise RelationNotExist()

        data = path(self.relationships, f'{relation_name}.data')
        if data is None:
            return []

        ids = set((r['id'], r['type']) for r in data)
        relations = [e for e in self.included if (e['id'], e['type']) in ids]

        if len(relations) == 0:
            result = map(lambda x: cls(entity_id=x[0]), ids)
            return list(result)

        return cls.from_collection({'data': relations})
Exemple #16
0
 def expected_field(inc, f_ids):
     attr_type = path(inc, 'attributes.field_type')
     if filed_types is not None and attr_type not in filed_types:
         return False
     return inc['type'] == 'dictionary' and inc['id'] in f_ids
Exemple #17
0
 def simplify(relation):
     return ((d['type'], d['id'])
             for i in relation
             for d in normalize(path(relation, f'{i}.data'))
             if 'type' in d)