Beispiel #1
0
    def has_permission(self, view):
        token = view.request.headers.get('Authorization')
        session_create = not getattr(view, 'session')
        permission = getattr(view, 'required_project_permission', None)

        if not token:
            return False

        try:
            session = Session() if session_create else getattr(view, 'session')

            if token[:len(self.token_prefix)] == self.token_prefix:
                token = token[len(self.token_prefix):]

                result = project_auth(session, token, permission)

                if result.get('warning'):
                    view.headers['X-Application-Warning'] = result['warning']

                return result['result']
            elif token[:len(self.project_token_prefix
                            )] == self.project_token_prefix:
                token = token[len(self.project_token_prefix):]

                result = project_auth(session, token, permission)

                if result.get('warning'):
                    view.headers['X-Application-Warning'] = result['warning']

                return result['result']
            else:
                return False
        finally:
            if session_create:
                session.close()
Beispiel #2
0
def project_auth(token, permission=None):
    session = Session()
    project_token = session.query(Token).first()

    if not project_token:
        return {'result': False}

    url = api_method_url('project_auth/')
    data = {'project_token': project_token.token, 'token': token}
    headers = {'User-Agent': 'Jet Django'}

    if permission:
        data.update(permission)

    r = requests.request('POST', url, data=data, headers=headers)
    success = 200 <= r.status_code < 300

    if not success:
        logging.error('Project Auth request error', r.status_code, r.reason)
        return {'result': False}

    result = r.json()

    if result.get('access_disabled'):
        return {'result': False, 'warning': result.get('warning')}

    return {'result': True, 'warning': result.get('warning')}
Beispiel #3
0
    def get(self, *args, **kwargs):
        try:
            session = Session()
            token, created = register_token(session)

            if not token:
                return

            if is_token_activated(session):
                response = Response(
                    {'message': 'Project token is already activated'})
                self.write_response(response)
                return

            if settings.WEB_BASE_URL.startswith(
                    'https'
            ) and not self.request.full_url().startswith('https'):
                web_base_url = 'http{}'.format(settings.WEB_BASE_URL[5:])
            else:
                web_base_url = settings.WEB_BASE_URL

            url = '{}/projects/register/{}'.format(web_base_url, token.token)
            query_string = 'referrer={}'.format(
                quote(self.request.full_url().encode('utf8')))

            self.redirect('%s?%s' % (url, query_string))
        finally:
            session.close()
Beispiel #4
0
    def prepare(self):
        method_override = self.request.headers.get('X-Http-Method-Override')
        if method_override is not None:
            self.request.method = method_override

        if self.request.method != 'OPTIONS':
            self.check_permissions()

        self.session = Session()
Beispiel #5
0
def token_command():
    try:
        session = Session()
        token = get_token(session)

        if token:
            logging.info('Jet Admin Token:')
            logging.info(token)
        else:
            logging.info('Jet Admin Token is not set')
    finally:
        session.close()
Beispiel #6
0
def set_token_command(args):
    try:
        session = Session()
        token = uuid.UUID(args[1]) if len(args) >= 2 else None

        if not token:
            logging.info('No token was specified')
            return

        set_token(session, token)
    finally:
        session.close()
Beispiel #7
0
def register_token_command():
    try:
        session = Session()
        token, created = register_token(session)

        if not created and token:
            logging.info('Token already exists: {}'.format(token.token))
        elif not created and not token:
            logging.info('Token creation failed')
        elif created and token:
            logging.info('Token created: {}'.format(token.token))
    finally:
        session.close()
Beispiel #8
0
def run_command():
    logging.info(datetime.now().strftime('%B %d, %Y - %H:%M:%S %Z'))
    logging.info('Jet Bridge version {}'.format(VERSION))

    if missing_options == settings.required_options_without_default:
        create_config()
        return
    elif len(missing_options) and len(missing_options) < len(
            settings.required_options_without_default):
        logging.info('Required options are not specified: {}'.format(
            ', '.join(missing_options)))
        return

    from jet_bridge.app import make_app

    app = make_app()
    app.listen(settings.PORT, settings.ADDRESS)
    address = 'localhost' if settings.ADDRESS == '0.0.0.0' else settings.ADDRESS
    url = 'http://{}:{}/'.format(address, settings.PORT)

    logging.info('Starting server at {}'.format(url))

    if settings.DEBUG:
        logging.warning('Server is running in DEBUG mode')

    logging.info('Quit the server with CONTROL-C')

    try:
        session = Session()
        token, created = register_token(session)

        if not token:
            return

        if not is_token_activated(session):
            token = get_token(session)
            register_url = '{}api/register/?token={}'.format(url, token)
            logging.warning('[!] Your server token is not activated')
            logging.warning('[!] Token: {}'.format(token))

            if settings.AUTO_OPEN_REGISTER and webbrowser.open(register_url):
                logging.warning(
                    '[!] Activation page was opened in your browser - {}'.
                    format(register_url))
    except RequestException:
        logging.error('[!] Can\'t connect to Jet Admin API')
        logging.error('[!] Token verification failed')
    finally:
        session.close()

    tornado.ioloop.IOLoop.current().start()
Beispiel #9
0
def register_token():
    session = Session()
    token = session.query(Token).first()

    if token:
        return token, False

    url = api_method_url('project_tokens/')
    headers = {'User-Agent': 'Jet Django'}

    r = requests.request('POST', url, headers=headers)
    success = 200 <= r.status_code < 300

    if not success:
        logging.error('Register Token request error', r.status_code, r.reason)
        return None, False

    result = r.json()

    # TODO: add serializer
    token = result['token'].replace('-', '')
    date_add = datetime.strptime(result['date_add'][:-6],
                                 '%Y-%m-%dT%H:%M:%S.%f')

    token = Token(token=token, date_add=date_add)
    session.add(token)
    session.commit()

    return token, True
Beispiel #10
0
def is_token_activated():
    session = Session()
    token = session.query(Token).first()

    if not token:
        return False

    url = api_method_url('project_tokens/{}/'.format(token.token))
    headers = {'User-Agent': 'Jet Django'}

    r = requests.request('GET', url, headers=headers)
    success = 200 <= r.status_code < 300

    if not success:
        return False

    result = r.json()

    return bool(result.get('activated'))
Beispiel #11
0
    def execute(self):
        session = Session()

        query = self.validated_data['query']
        params = self.validated_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)
Beispiel #12
0
def run_command():
    from jet_bridge.app import make_app

    app = make_app()
    app.listen(settings.PORT, settings.ADDRESS)
    address = 'localhost' if settings.ADDRESS == '0.0.0.0' else settings.ADDRESS
    url = 'http://{}:{}/'.format(address, settings.PORT)

    logging.info('Starting server at {}'.format(url))

    if settings.DEBUG:
        logging.warning('Server is running in DEBUG mode')

    logging.info('Quit the server with CONTROL-C')

    try:
        session = Session()
        token, created = register_token(session)

        if not token:
            return

        if not is_token_activated(session):
            token = get_token(session)
            register_url = '{}api/register/?token={}'.format(url, token)
            logging.warning('[!] Your server token is not activated')
            logging.warning('[!] Token: {}'.format(token))

            if settings.AUTO_OPEN_REGISTER and webbrowser.open(register_url):
                logging.warning('[!] Activation page was opened in your browser - {}'.format(register_url))
    except RequestException:
        logging.error('[!] Can\'t connect to Jet Admin API')
        logging.error('[!] Token verification failed')
    finally:
        session.close()

    tornado.ioloop.IOLoop.current().start()
Beispiel #13
0
def reset_token():
    session = Session()
    session.query(Token).delete()
    session.commit()

    return register_token()
Beispiel #14
0
class ModelDescriptionsHandler(APIView):
    serializer_class = ModelDescriptionSerializer
    permission_classes = (HasProjectPermissions, )
    session = Session()

    def get_queryset(self):
        non_editable = ['id']
        hidden = ['__jet__token']

        def map_column(column):
            params = {}
            data_type = map_data_type(column.type)

            if len(column.foreign_keys):
                foreign_key = next(iter(column.foreign_keys))
                data_type = data_types.FOREIGN_KEY
                params['related_model'] = {
                    'model': foreign_key.column.table.name
                }

            return {
                'name': column.name,
                'db_column': column.name,
                'field': data_type,
                'filterable': True,
                'editable': column.name not in non_editable,
                'params': params
            }

        def map_relation(relation):
            field = None

            if relation.direction == ONETOMANY:
                field = 'ManyToOneRel'

            return {
                'name': relation.key,
                'related_model': {
                    'model': relation.table.name
                },
                'field': field,
                'related_model_field': relation.primaryjoin.right.name,
                'through': None
            }

        def table_relations(mapper):
            return list(
                map(
                    map_relation,
                    filter(lambda x: x.direction == ONETOMANY,
                           mapper.relationships)))

        def table_m2m_relations(mapper):
            result = []
            name = mapper.selectable.name

            for relation in mapper.relationships:
                if relation.direction != ONETOMANY:
                    continue

                m2m_relationships = relation.mapper.relationships.values()

                if len(m2m_relationships) != 2:
                    continue

                if len(relation.table.columns) > 5:
                    continue

                self_relationship = m2m_relationships[1] if m2m_relationships[1].table.name == name else \
                m2m_relationships[0]
                other_relationship = m2m_relationships[0] if self_relationship == m2m_relationships[1] else \
                m2m_relationships[1]

                result.append({
                    'name':
                    'M2M {} {}'.format(self_relationship.table.name,
                                       other_relationship.table.name),
                    'related_model': {
                        'model': other_relationship.table.name
                    },
                    'field':
                    'ManyToManyField',
                    'related_model_field':
                    self_relationship.table.name,
                    'through': {
                        'model': relation.table.name
                    }
                })

            return result

        def map_table(cls):
            mapper = inspect(cls)
            name = mapper.selectable.name

            return {
                'model': name,
                'db_table': name,
                'fields': list(map(map_column, mapper.columns)),
                'hidden': name in hidden,
                'relations':
                table_relations(mapper) + table_m2m_relations(mapper),
                'primary_key_field': mapper.primary_key[0].name
            }

        return list(map(map_table, MappedBase.classes))

    def get(self, *args, **kwargs):
        queryset = self.get_queryset()
        serializer = self.serializer_class(instance=queryset, many=True)
        response = Response(serializer.representation_data)
        self.write_response(response)
Beispiel #15
0
class GenericAPIView(APIView):
    serializer_class = None
    filter_class = None
    pagination_class = PageNumberPagination
    _paginator = None
    lookup_field = 'id'
    lookup_url_kwarg = None
    session = Session()
    action = None

    def get_model(self):
        raise NotImplementedError

    def get_queryset(self):
        raise NotImplementedError

    def get_object(self):
        queryset = self.filter_queryset(self.get_queryset())
        lookup_url_kwarg = self.lookup_url_kwarg or 'pk'

        assert lookup_url_kwarg in self.path_kwargs

        model_field = getattr(self.get_model(), self.lookup_field)
        obj = queryset.filter(
            getattr(model_field,
                    '__eq__')(self.path_kwargs[lookup_url_kwarg])).first()

        self.check_object_permissions(obj)

        return obj

    def get_filter(self, *args, **kwargs):
        filter_class = self.get_filter_class()
        if not filter_class:
            return
        kwargs['context'] = self.filter_context()
        return filter_class(*args, **kwargs)

    def get_filter_class(self):
        return self.filter_class

    def filter_context(self):
        return {'request': self.request, 'handler': self}

    def filter_queryset(self, queryset):
        filter_instance = self.get_filter()
        if filter_instance:
            queryset = filter_instance.filter_queryset(queryset)
        return queryset

    @property
    def paginator(self):
        if not self._paginator:
            if self.pagination_class is None:
                self._paginator = None
            else:
                self._paginator = self.pagination_class()
        return self._paginator

    def paginate_queryset(self, queryset):
        if self.paginator is None:
            return None
        return self.paginator.paginate_queryset(queryset, self)

    def get_paginated_response(self, data):
        assert self.paginator is not None
        return self.paginator.get_paginated_response(data)

    def get_serializer(self, *args, **kwargs):
        serializer_class = self.get_serializer_class()
        kwargs['context'] = self.get_serializer_context()
        return serializer_class(*args, **kwargs)

    def get_serializer_class(self):
        return self.serializer_class

    def get_serializer_context(self):
        return {'request': self.request, 'view': self, 'session': self.session}

    def write_error(self, status_code, **kwargs):
        self.session.rollback()
        super(GenericAPIView, self).write_error(status_code, **kwargs)
Beispiel #16
0
class APIView(tornado.web.RequestHandler):
    permission_classes = []
    session = None

    @property
    def data(self):
        content_type = self.request.headers.get('Content-Type', '')
        if content_type.startswith('application/json'):
            return json_decode(self.request.body)
        else:
            return self.request.body_arguments

    def prepare(self):
        method_override = self.request.headers.get('X-Http-Method-Override')
        if method_override is not None:
            self.request.method = method_override

        if self.request.method != 'OPTIONS':
            self.check_permissions()

        self.session = Session()

    def on_finish(self):
        if self.session:
            self.session.close()
            self.session = None

    def set_default_headers(self):
        ACCESS_CONTROL_ALLOW_ORIGIN = 'Access-Control-Allow-Origin'
        ACCESS_CONTROL_EXPOSE_HEADERS = 'Access-Control-Expose-Headers'
        ACCESS_CONTROL_ALLOW_CREDENTIALS = 'Access-Control-Allow-Credentials'
        ACCESS_CONTROL_ALLOW_HEADERS = 'Access-Control-Allow-Headers'
        ACCESS_CONTROL_ALLOW_METHODS = 'Access-Control-Allow-Methods'

        self.set_header(ACCESS_CONTROL_ALLOW_ORIGIN, '*')
        self.set_header(ACCESS_CONTROL_ALLOW_METHODS,
                        'GET, POST, PUT, PATCH, DELETE, OPTIONS')
        self.set_header(
            ACCESS_CONTROL_ALLOW_HEADERS,
            'Authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,X-Application-Warning,X-HTTP-Method-Override'
        )
        self.set_header(ACCESS_CONTROL_EXPOSE_HEADERS,
                        'Content-Length,Content-Range,X-Application-Warning')
        self.set_header(ACCESS_CONTROL_ALLOW_CREDENTIALS, 'true')

    def get_permissions(self):
        return [permission() for permission in self.permission_classes]

    def check_permissions(self):
        for permission in self.get_permissions():
            if not permission.has_permission(self):
                raise PermissionDenied(
                    getattr(permission, 'message', 'forbidden'))

    def check_object_permissions(self, obj):
        for permission in self.get_permissions():
            if not permission.has_object_permission(self, obj):
                raise PermissionDenied(
                    getattr(permission, 'message', 'forbidden'))

    def options(self, *args, **kwargs):
        self.set_status(204)
        self.finish()

    def build_absolute_uri(self, url):
        return self.request.protocol + "://" + self.request.host + url

    def write_response(self, response):
        for name, value in response.header_items():
            self.set_header(name, value)
        self.write(response.render())

    def write_error(self, status_code, **kwargs):
        exc_type = exc = traceback = None

        if kwargs.get('exc_info'):
            exc_type, exc, traceback = kwargs['exc_info']

            if isinstance(exc, APIException):
                status_code = exc.status_code

        if status_code == status.HTTP_403_FORBIDDEN:
            self.render('403.html', **{
                'path': self.request.path,
            })
        else:
            if settings.DEBUG:
                ctx = {
                    'path':
                    self.request.path,
                    'full_path':
                    self.request.protocol + "://" + self.request.host +
                    self.request.path,
                    'method':
                    self.request.method,
                    'version':
                    VERSION,
                    'current_datetime':
                    datetime.now().strftime('%c'),
                    'python_version':
                    platform.python_version(),
                    'python_executable':
                    sys.executable,
                    'python_path':
                    sys.path
                }

                if exc:
                    last_traceback = traceback

                    while last_traceback.tb_next:
                        last_traceback = last_traceback.tb_next

                    ctx.update({
                        'exception_type':
                        exc_type.__name__,
                        'exception_value':
                        str(exc),
                        'exception_last_traceback_line':
                        last_traceback.tb_lineno,
                        'exception_last_traceback_name':
                        last_traceback.tb_frame
                    })

                self.render('500.debug.html', **ctx)
            else:
                self.render('500.html')