Ejemplo n.º 1
0
def view_node(project_url, node_id):
    """Entry point to view a node in the context of a project"""
    # Some browsers mangle URLs and URL-encode /p/{p-url}/#node-id
    if node_id.startswith('#'):
        return redirect(url_for('projects.view_node',
                                project_url=project_url,
                                node_id=node_id[1:]),
                        code=301)  # permanent redirect

    theatre_mode = 't' in request.args
    api = system_util.pillar_api()
    # First we check if it's a simple string, in which case we are looking for
    # a static page. Maybe we could use bson.objectid.ObjectId.is_valid(node_id)
    if not utils.is_valid_id(node_id):
        # raise wz_exceptions.NotFound('No such node')
        project, node = render_node_page(project_url, node_id, api)
    else:
        # Fetch the node before the project. If this user has access to the
        # node, we should be able to get the project URL too.
        try:
            node = Node.find(node_id, api=api)
        except ForbiddenAccess:
            return render_template('errors/403.html'), 403
        except ResourceNotFound:
            raise wz_exceptions.NotFound('No such node')

        try:
            project = Project.find_one({'where': {"url": project_url, '_id': node.project}},
                                       api=api)
        except ResourceNotFound:
            # In theatre mode, we don't need access to the project at all.
            if theatre_mode:
                project = None
            else:
                raise wz_exceptions.NotFound('No such project')

    og_picture = node.picture = utils.get_file(node.picture, api=api)
    if project:
        if not node.picture:
            og_picture = utils.get_file(project.picture_header, api=api)
        project.picture_square = utils.get_file(project.picture_square, api=api)

    # Append _theatre to load the proper template
    theatre = '_theatre' if theatre_mode else ''

    extension_sidebar_links = current_app.extension_sidebar_links(project)

    return render_template('projects/view{}.html'.format(theatre),
                           api=api,
                           project=project,
                           node=node,
                           show_node=True,
                           show_project=False,
                           og_picture=og_picture,
                           extension_sidebar_links=extension_sidebar_links)
Ejemplo n.º 2
0
    def test_valid(self):
        # 24-byte hex strings
        self.assertTrue(utils.is_valid_id(24 * 'a'))
        self.assertTrue(utils.is_valid_id(24 * 'a'))
        self.assertTrue(utils.is_valid_id('deadbeefbeefcacedeadcace'))
        self.assertTrue(utils.is_valid_id('deadbeefbeefcacedeadcace'))

        # 12-byte arbitrary ASCII bytes
        self.assertTrue(utils.is_valid_id(b'DeadBeefCake'))
        self.assertTrue(utils.is_valid_id(b'DeadBeefCake'))

        # 12-byte object
        self.assertTrue(utils.is_valid_id('beef€67890'.encode()))
Ejemplo n.º 3
0
def view_task_log(project, task_id):
    """Shows a limited number of task log entries.

    Pass page=N (N≥1) to request further entries.
    """

    from pillarsdk import ResourceNotFound
    from pillar.web.utils import is_valid_id, last_page_index
    from flamenco.tasks.sdk import TaskLog

    if not is_valid_id(task_id):
        raise wz_exceptions.UnprocessableEntity()

    page_idx = int(request.args.get('page', 1))
    api = pillar_api()
    try:
        logs = TaskLog.all(
            {
                'where': {
                    'task': task_id
                },
                'page': page_idx,
                'max_results': TASK_LOG_PAGE_SIZE
            },
            api=api)
    except ResourceNotFound:
        logs = {
            '_items': [],
            '_meta': {
                'total': 0,
                'page': page_idx,
                'max_results': TASK_LOG_PAGE_SIZE
            }
        }

    last_page_idx = last_page_index(logs['_meta'])
    has_next_page = page_idx < last_page_idx
    has_prev_page = page_idx > 1

    return render_template('flamenco/tasks/view_task_log_embed.html',
                           page_idx=page_idx,
                           logs=logs,
                           has_prev_page=has_prev_page,
                           has_next_page=has_next_page,
                           last_page_idx=last_page_idx,
                           project=project,
                           task_id=task_id)
Ejemplo n.º 4
0
def download_task_log(project, task_id):
    """Shows the entire task log as text/plain"""

    from flask import Response, current_app

    from pillar.web.utils import is_valid_id, last_page_index
    from flamenco.tasks.sdk import TaskLog

    if not is_valid_id(task_id):
        raise wz_exceptions.UnprocessableEntity()

    # Required because the stream_log() generator will run outside the app context.
    app = current_app._get_current_object()
    api = pillar_api()

    def stream_log():
        page_idx = 1
        while True:
            with app.app_context():
                logs = TaskLog.all(
                    {
                        'where': {
                            'task': task_id
                        },
                        'page': page_idx,
                        'max_results': TASK_LOG_PAGE_SIZE
                    },
                    api=api)

            for tasklog in logs['_items']:
                yield tasklog.log + '\n'

            if page_idx >= last_page_index(logs['_meta']):
                break

            page_idx += 1

    return Response(stream_log(), mimetype='text/plain')
Ejemplo n.º 5
0
def download_task_log(project, task_id):
    """Show the entire task log as text/plain.

    This endpoint is for obtaining the task log stored in MongoDB. This
    approach is deprecated in favour of having the Manager store & serve the
    logs and upload them to the Server on demand (see flamenco.managers.api).
    """

    if not is_valid_id(task_id):
        raise wz_exceptions.UnprocessableEntity()

    # Required because the stream_log() generator will run outside the app context.
    app = current_app.real_app
    api = pillar_api()

    def stream_log():
        page_idx = 1
        while True:
            with app.app_context():
                logs = TaskLog.all(
                    {
                        'where': {
                            'task': task_id
                        },
                        'page': page_idx,
                        'max_results': TASK_LOG_PAGE_SIZE
                    },
                    api=api)

            for tasklog in logs['_items']:
                yield tasklog.log + '\n'

            if page_idx >= last_page_index(logs['_meta']):
                break

            page_idx += 1

    return Response(stream_log(), mimetype='text/plain')
Ejemplo n.º 6
0
def download_task_log_file(project, task_id):
    """Redirect to the storage backend for the task log.

    This endpoint is for obtaining the task log sent to us by Flamenco Manager,
    and stored as a gzipped file in the storage backend. See the Manager API
    for the endpoint that actually accepts the log file from the Manager.
    """
    from pillar.web.utils import is_valid_id
    from .sdk import Task

    if not is_valid_id(task_id):
        raise wz_exceptions.UnprocessableEntity()

    api = pillar_api()
    task = Task.find(task_id, api=api)

    if not task.log_file:
        return wz_exceptions.NotFound(
            f'Task {task_id} has no attached log file')

    blob = current_flamenco.task_manager.logfile_blob(task.to_dict())
    url = blob.get_url(is_public=False)
    return redirect(url, code=307)
Ejemplo n.º 7
0
    def test_bad_content(self):
        # 24-character non-hexadecimal string
        self.assertFalse(utils.is_valid_id('deadbeefbeefcakedeadcake'))

        # unicode variant of valid 12-byte str object
        self.assertFalse(utils.is_valid_id('beef€67890'))
Ejemplo n.º 8
0
 def test_non_string(self):
     self.assertFalse(utils.is_valid_id(None))
     self.assertFalse(utils.is_valid_id(1234))
     self.assertFalse(utils.is_valid_id([24 * 'a']))
Ejemplo n.º 9
0
 def test_bad_length(self):
     self.assertFalse(utils.is_valid_id(23 * 'a'))
     self.assertFalse(utils.is_valid_id(25 * 'a'))