Exemplo n.º 1
0
    class ResetOrderSerializer(Serializer):
        ordering_field = fields.CharField()
        ordering = fields.CharField(required=False, allow_null=True)
        value_ordering = fields.CharField(required=False, allow_null=True)

        def save(self):
            ordering_field = self.validated_data['ordering_field']
            ordering = self.validated_data.get('ordering')
            value_ordering = self.validated_data.get('value_ordering')

            qs = queryset
            order_by = []

            if value_ordering:
                field, values_str = value_ordering.split('-', 2)
                values = values_str.split(',')
                order_by.append(
                    case([(getattr(Model, field) == x, i)
                          for i, x in enumerate(values)],
                         else_=len(values)))

            if ordering:

                def map_field(name):
                    descending = False
                    if name.startswith('-'):
                        name = name[1:]
                        descending = True
                    field = getattr(Model, name)
                    if descending:
                        field = desc(field)
                    return field

                order_by.extend(
                    map(lambda x: map_field(x), ordering.split(',')))

            if order_by:
                qs = qs.order_by(*order_by)

            i = 1

            try:
                items = qs.options(load_only(ordering_field)).all()
            except SQLAlchemyError:
                queryset.session.rollback()
                raise

            for instance in items:
                setattr(instance, ordering_field, i)
                i += 1

            try:
                session.commit()
            except SQLAlchemyError:
                session.rollback()
                raise
Exemplo n.º 2
0
class SqlSerializer(Serializer):
    query = fields.CharField()
    timezone = fields.CharField(required=False)
    params = SqlParamsSerializers(required=False)

    def validate_query(self, value):
        forbidden = ['insert', 'update', 'delete', 'grant', 'show']
        for i in range(len(forbidden)):
            forbidden.append('({}'.format(forbidden[i]))
        if any(map(lambda x: ' {} '.format(value.lower()).find(' {} '.format(x)) != -1, forbidden)):
            raise ValidationError('forbidden query')

        i = 0
        while value.find('%s') != -1:
            value = value.replace('%s', ':param_{}'.format(i), 1)
            i += 1

        return value

    def execute(self, data):
        request = self.context.get('request')
        session = create_session(request)

        query = data['query']
        params = data.get('params', [])

        if 'timezone' in data:
            try:
                session.execute('SET TIME ZONE :tz', {'tz': data['timezone']})
            except SQLAlchemyError:
                session.rollback()
                pass

        try:
            result = session.execute(
                text(query),
                params
            )

            rows = list(map(lambda x: list(x.itervalues()), result))

            def map_column(x):
                if x == '?column?':
                    return
                return x

            return {'data': rows, 'columns': list(map(map_column, result.keys()))}
        except SQLAlchemyError as e:
            session.rollback()
            raise SqlError(e)
        except TypeError as e:
            raise SqlError(e)
        finally:
            session.close()
Exemplo n.º 3
0
class ModelDescriptionFieldSerializer(Serializer):
    name = fields_.CharField()
    db_column = fields_.CharField()
    field = fields_.CharField()
    filterable = fields_.BooleanField()
    null = fields_.BooleanField()
    editable = fields_.BooleanField()
    params = fields_.JSONField()
    verbose_name = fields_.CharField(required=False)
    required = fields_.BooleanField(required=False)
    default_type = fields_.CharField(required=False)
    default_value = fields_.AnyField(required=False)
Exemplo n.º 4
0
class MessageSerializer(Serializer):
    name = fields.CharField()
    params = fields.JSONField(required=False)

    def save(self):
        handler = get_handler(self.validated_data['name'])
        if not handler:
            return
        return handler(self.validated_data['name'], self.validated_data.get('params', {}))
Exemplo n.º 5
0
    class ReorderSerializer(Serializer):
        ordering_field = fields.CharField()
        forward = fields.BooleanField()
        segment_from = fields.IntegerField()
        segment_to = fields.IntegerField()
        item = fields.IntegerField()
        segment_by_ordering_field = fields.BooleanField(default=False)

        def save(self):
            mapper = inspect(Model)

            primary_key_field = mapper.primary_key[0].name
            ordering_field = self.validated_data['ordering_field']
            primary_key = getattr(Model, primary_key_field)
            ordering = getattr(Model, ordering_field)

            if self.validated_data.get('segment_by_ordering_field'):
                segment_from = self.validated_data['segment_from']
                segment_to = self.validated_data['segment_to']
            else:
                segment_from_instance = queryset.filter(primary_key == self.validated_data['segment_from']).first()
                segment_to_instance = queryset.filter(primary_key == self.validated_data['segment_to']).first()

                segment_from = getattr(segment_from_instance, ordering_field)
                segment_to = getattr(segment_to_instance, ordering_field)

            if self.validated_data['forward']:
                queryset.filter(
                    ordering >= segment_from,
                    ordering <= segment_to
                ).update(
                    {ordering_field: ordering - 1}
                )
                queryset.filter(
                    primary_key == self.validated_data['item']
                ).update(
                    {ordering_field: segment_to}
                )
            else:
                queryset.filter(
                    ordering >= segment_from,
                    ordering <= segment_to
                ).update(
                    {ordering_field: ordering + 1}
                )
                queryset.filter(
                    primary_key == self.validated_data['item']
                ).update(
                    {ordering_field: segment_to}
                )

            try:
                session.commit()
            except SQLAlchemyError as e:
                session.rollback()
                raise e
Exemplo n.º 6
0
class ModelDescriptionSerializer(Serializer):
    model = fields_.CharField()
    db_table = fields_.CharField()
    hidden = fields_.BooleanField()
    primary_key_field = fields_.CharField()
    fields = ModelDescriptionFieldSerializer(many=True)
    # relations = ModelDescriptionRelationSerializer(many=True)
    verbose_name = fields_.CharField(required=False)
    verbose_name_plural = fields_.CharField(required=False)
    display_field = fields_.CharField(required=False)
    default_order_by = fields_.CharField(required=False)
Exemplo n.º 7
0
Arquivo: sql.py Projeto: preetgur/main
class SqlSerializer(Serializer):
    query = fields.CharField()
    params = SqlParamsSerializers(required=False)

    def validate_query(self, value):
        forbidden = ['insert', 'update', 'delete', 'grant', 'show']
        for i in range(len(forbidden)):
            forbidden.append('({}'.format(forbidden[i]))
        if any(
                map(
                    lambda x: ' {} '.format(value.lower()).find(' {} '.format(
                        x)) != -1, forbidden)):
            raise ValidationError('forbidden query')

        i = 0
        while value.find('%s') != -1:
            value = value.replace('%s', ':param_{}'.format(i), 1)
            i += 1

        return value

    def execute(self, data):
        session = Session()

        query = data['query']
        params = data.get('params', [])

        try:
            result = session.execute(text(query), params)

            rows = list(map(lambda x: x.itervalues(), result))

            def map_column(x):
                if x == '?column?':
                    return
                return x

            return {'data': rows, 'columns': map(map_column, result.keys())}
        except (SQLAlchemyError, TypeError) as e:
            raise SqlError(e)
        finally:
            session.close()
Exemplo n.º 8
0
class ProxyRequestSerializer(Serializer):
    method = fields.CharField(required=False, default='GET')
    url = fields.CharField(trim_whitespace=False)
    query_params = fields.JSONField(required=False, default=dict)
    headers = fields.JSONField(required=False, default=dict)
    body = fields.RawField(required=False)

    project = fields.CharField(required=False)
    resource = fields.CharField(required=False)
    secret_tokens = fields.CharField(required=False)
    context = fields.JSONField(required=False)

    def get_access_token(self, app, config, extra_data):
        handler = self.context.get('handler')
        request = self.context.get('request')
        strategy = load_strategy(handler, request, config)

        backend_path = config.get('backend_path')
        Backend = module_member(backend_path)

        if not issubclass(Backend, BaseAuth):
            return extra_data.get('access_token')

        backend = Backend(strategy, None)

        refresh_token = extra_data.get('refresh_token') or extra_data.get(
            'access_token')

        expires_on = None
        params_expires_on = extra_data.get('expires_on')
        params_token_updated = extra_data.get('token_updated')
        params_expires_in = extra_data.get('expires') or extra_data.get(
            'expires_in')

        try:
            if params_expires_on:
                expires_on = int(params_expires_on)
            elif params_expires_in and params_token_updated:
                expires_on = int(params_token_updated) + int(params_expires_in)
        except (ValueError, TypeError):
            pass

        try:
            if refresh_token and (not expires_on
                                  or expires_on <= int(time.time())):
                response = backend.refresh_token(token=refresh_token)
                if not backend.EXTRA_DATA or len(backend.EXTRA_DATA) == 0:
                    backend.GET_ALL_EXTRA_DATA = True
                new_extra_data = backend.extra_data(user=None,
                                                    uid=None,
                                                    response=response,
                                                    details={})
                access_token = new_extra_data.get('access_token')

                new_extra_data = {
                    'expires_on': new_extra_data.get('expires_on'),
                    'access_token': new_extra_data.get('access_token'),
                    'expires': new_extra_data.get('expires'),
                    'auth_time': new_extra_data.get('auth_time'),
                    'refresh_token': new_extra_data.get('refresh_token'),
                    'token_updated': int(time.time())
                }

                request = self.context.get('request')
                extra_data_key = '_'.join(['extra_data', app])
                configuration.session_set(request, extra_data_key,
                                          json.dumps(new_extra_data))

                return access_token
        except Exception:
            pass

        return extra_data.get('access_token')

    def resolve_secret_tokens(self, names, project, resource):
        request = self.context.get('request')
        instances = {}
        unresolved = names[:]

        for name in unresolved:
            regex = re.search('sso\.(?P<sso>\w+)\.(?P<token>\w+)', name)

            if not regex:
                continue

            matches = regex.groupdict()

            if matches['token'] != 'access_token':
                continue

            app = configuration.clean_sso_application_name(matches['sso'])
            config = settings.SSO_APPLICATIONS.get(app)

            if not config:
                continue

            extra_data_key = '_'.join(['extra_data', app])

            try:
                if settings.COOKIE_COMPRESS:
                    extra_data_str = configuration.session_get(request,
                                                               extra_data_key,
                                                               decode=False,
                                                               secure=False)
                    extra_data_str = decompress_data(extra_data_str)
                else:
                    extra_data_str = configuration.session_get(
                        request, extra_data_key)

                extra_data = json.loads(extra_data_str)

                if matches['token'] not in extra_data:
                    continue

                if matches['token'] == 'access_token':
                    instances[name] = self.get_access_token(
                        app, config, extra_data)
                else:
                    instances[name] = extra_data.get(matches['token'])
            except Exception:
                pass

        unresolved = list(
            filter(lambda x: x not in instances.keys(), unresolved))

        if len(unresolved):
            token_prefix = 'Token '
            authorization = request.headers.get('AUTHORIZATION', '')
            user_token = authorization[len(token_prefix
                                           ):] if authorization.startswith(
                                               token_prefix) else None

            for item in get_secret_tokens(project, resource, settings.TOKEN,
                                          user_token):
                if item['name'] not in unresolved:
                    continue
                instances[item['name']] = item['value']

        for name in unresolved:
            if name not in instances:
                instances[name] = ''

        return instances

    def validate(self, attrs):
        if 'resource' in attrs:
            if 'project' not in attrs:
                raise ValidationError(
                    '"project" is required when specifying "resource"')

        if 'secret_tokens' in attrs and len(attrs['secret_tokens']):
            if 'resource' not in attrs:
                raise ValidationError(
                    '"resource" is required when specifying "secret_tokens"')
            names = attrs['secret_tokens'].split(',')

            attrs['secret_tokens'] = self.resolve_secret_tokens(
                names, attrs['project'], attrs['resource'])

        if isinstance(attrs['headers'], dict):
            attrs['headers'] = dict(
                [[key, str(value)] for key, value in attrs['headers'].items()])

        return attrs

    def params_dict_to_list(self, items):
        return list(map(lambda x: {
            'name': x[0],
            'value': x[1]
        }, items.items()))

    def interpolate(self, url, headers, query_params, body, pattern, replaces):
        def replace(str, replaces):
            for name, value in replaces.items():
                str = str.replace(pattern % name, value)
            return str

        url = replace(url, replaces)

        for header in headers:
            header['value'] = replace(header['value'], replaces)

        for query_param in query_params:
            query_param['value'] = replace(query_param['value'], replaces)

        if body:
            body = replace(body, replaces)

        return url, headers, query_params, body

    def submit(self):
        method = self.validated_data['method']
        url = self.validated_data['url']
        headers = self.validated_data['headers'] or []
        query_params = self.validated_data['query_params'] or []
        body = self.validated_data.get('body')

        if isinstance(headers, dict):
            headers = self.params_dict_to_list(headers)

        if isinstance(query_params, dict):
            query_params = self.params_dict_to_list(query_params)

        if 'secret_tokens' in self.validated_data:
            url, headers, query_params, body = self.interpolate(
                url, headers, query_params, body, '{-%s-}',
                self.validated_data['secret_tokens'])

        if 'context' in self.validated_data:
            url, headers, query_params, body = self.interpolate(
                url, headers, query_params, body, '{{%s}}',
                self.validated_data['context'])

        if body:
            body = body.encode('utf-8')

        headers = dict(map(lambda x: (x['name'], x['value']), headers))
        query_params = list(
            map(lambda x: (x['name'], x['value']), query_params))

        try:
            r = requests.request(method,
                                 url,
                                 headers=headers,
                                 params=query_params,
                                 data=body)
            response_headers = r.headers

            remove_headers = [
                'Access-Control-Allow-Origin', 'Access-Control-Allow-Methods',
                'Access-Control-Allow-Headers',
                'Access-Control-Expose-Headers',
                'Access-Control-Allow-Credentials', 'Connection',
                'Content-Encoding', 'Content-Length', 'Keep-Alive',
                'Proxy-Authenticate', 'Proxy-Authorization', 'TE', 'Trailers',
                'Transfer-Encoding', 'Upgrade'
            ]

            for header in remove_headers:
                if header in response_headers:
                    del response_headers[header]

            response = Response(data=r.content,
                                status=r.status_code,
                                headers=response_headers)

            return response
        except Exception as e:
            raise ValidationError(e)
Exemplo n.º 9
0
class SqlSerializer(Serializer):
    query = fields.CharField()
    timezone = fields.CharField(required=False)
    params = SqlParamsSerializers(required=False)
    params_obj = fields.JSONField(required=False)
    v = fields.IntegerField(default=1)

    def validate(self, attrs):
        forbidden = ['insert', 'update', 'delete', 'grant', 'show']
        for i in range(len(forbidden)):
            forbidden.append('({}'.format(forbidden[i]))
        if any(map(lambda x: ' {} '.format(attrs['query'].lower()).find(' {} '.format(x)) != -1, forbidden)):
            raise ValidationError({'query': 'forbidden query'})

        if attrs['v'] < 2:
            i = 0
            while attrs['query'].find('%s') != -1:
                attrs['query'] = attrs['query'].replace('%s', ':param_{}'.format(i), 1)
                i += 1

        return attrs

    def execute(self, data):
        request = self.context.get('request')
        session = create_session(request)

        query = data['query']

        if data['v'] >= 2:
            params = data.get('params_obj', {})
        else:
            params = data.get('params', [])

        if 'timezone' in data:
            try:
                session.execute('SET TIME ZONE :tz', {'tz': data['timezone']})
            except SQLAlchemyError:
                session.rollback()
                pass

        try:
            result = session.execute(
                text(query),
                params
            )

            def map_column(x):
                if x == '?column?':
                    return
                return x

            def map_row_column(x):
                if isinstance(x, bytes):
                    try:
                        return x.decode('utf-8')
                    except UnicodeDecodeError:
                        return x.hex()
                else:
                    return x

            def map_row(row):
                return list(map(lambda x: map_row_column(row[x]), row.keys()))

            return {'data': list(map(map_row, result)), 'columns': list(map(map_column, result.keys()))}
        except SQLAlchemyError as e:
            session.rollback()
            raise SqlError(e)
        except TypeError as e:
            raise SqlError(e)
        except Exception as e:
            raise SqlError(e)
        finally:
            session.close()
Exemplo n.º 10
0
class ProxyRequestSerializer(Serializer):
    method = fields.CharField(required=False, default='GET')
    url = fields.CharField(trim_whitespace=False)
    query_params = fields.JSONField(required=False, default=dict)
    headers = fields.JSONField(required=False, default=dict)
    body = fields.RawField(required=False)

    project = fields.CharField(required=False)
    resource = fields.CharField(required=False)
    secret_tokens = fields.CharField(required=False)
    context = fields.JSONField(required=False)

    def validate(self, attrs):
        if 'resource' in attrs:
            if 'project' not in attrs:
                raise ValidationError(
                    '"project" is required when specifying "resource"')

        if 'secret_tokens' in attrs and len(attrs['secret_tokens']):
            if 'resource' not in attrs:
                raise ValidationError(
                    '"resource" is required when specifying "secret_tokens"')
            names = attrs['secret_tokens'].split(',')
            instances = {}

            request = self.context.get('request')
            token_prefix = 'Token '
            authorization = request.headers.get('AUTHORIZATION', '')
            user_token = authorization[len(token_prefix
                                           ):] if authorization.startswith(
                                               token_prefix) else None

            for item in get_secret_tokens(attrs['project'], attrs['resource'],
                                          settings.TOKEN, user_token):
                instances[item['name']] = item['value']

            for name in names:
                if name not in instances:
                    instances[name] = ''

            attrs['secret_tokens'] = instances

        if isinstance(attrs['headers'], dict):
            attrs['headers'] = dict(
                [[key, str(value)] for key, value in attrs['headers'].items()])

        return attrs

    def params_dict_to_list(self, items):
        return list(map(lambda x: {
            'name': x[0],
            'value': x[1]
        }, items.items()))

    def interpolate(self, url, headers, query_params, body, pattern, replaces):
        def replace(str, replaces):
            for name, value in replaces.items():
                str = str.replace(pattern % name, value)
            return str

        url = replace(url, replaces)

        for header in headers:
            header['value'] = replace(header['value'], replaces)

        for query_param in query_params:
            query_param['value'] = replace(query_param['value'], replaces)

        if body:
            body = replace(body, replaces)

        return url, headers, query_params, body

    def submit(self):
        method = self.validated_data['method']
        url = self.validated_data['url']
        headers = self.validated_data['headers'] or []
        query_params = self.validated_data['query_params'] or []
        body = self.validated_data.get('body')

        if isinstance(headers, dict):
            headers = self.params_dict_to_list(headers)

        if isinstance(query_params, dict):
            query_params = self.params_dict_to_list(query_params)

        if 'secret_tokens' in self.validated_data:
            url, headers, query_params, body = self.interpolate(
                url, headers, query_params, body, '{-%s-}',
                self.validated_data['secret_tokens'])

        if 'context' in self.validated_data:
            url, headers, query_params, body = self.interpolate(
                url, headers, query_params, body, '{{%s}}',
                self.validated_data['context'])

        if body:
            body = body.encode('utf-8')

        headers = dict(map(lambda x: (x['name'], x['value']), headers))
        query_params = list(
            map(lambda x: (x['name'], x['value']), query_params))

        try:
            r = requests.request(method,
                                 url,
                                 headers=headers,
                                 params=query_params,
                                 data=body)
            response_headers = r.headers

            remove_headers = [
                'Access-Control-Allow-Origin', 'Access-Control-Allow-Methods',
                'Access-Control-Allow-Headers',
                'Access-Control-Expose-Headers', 'Connection',
                'Content-Encoding', 'Content-Length', 'Keep-Alive',
                'Proxy-Authenticate', 'Proxy-Authorization', 'TE', 'Trailers',
                'Transfer-Encoding', 'Upgrade'
            ]

            for header in remove_headers:
                if header in response_headers:
                    del response_headers[header]

            response = Response(data=r.content,
                                status=r.status_code,
                                headers=response_headers)

            return response
        except Exception as e:
            raise ValidationError(e)
Exemplo n.º 11
0
class ModelDescriptionRelationSerializer(Serializer):
    name = fields_.CharField()
    related_model = fields_.JSONField()
    field = fields_.CharField()
    related_model_field = fields_.CharField()
    through = fields_.JSONField()