예제 #1
0
def index():
    api = pillar_api()

    # FIXME Sybren: add permission check.
    # TODO: add projections.
    projects = current_flamenco.flamenco_projects()

    for project in projects['_items']:
        attach_project_pictures(project, api)

    projs_with_summaries = [
        (proj, current_flamenco.job_manager.job_status_summary(proj['_id']))
        for proj in projects['_items']
    ]

    last_project = session.get('flamenco_last_project')
    if last_project:
        project = Project(last_project)
        navigation_links = project_navigation_links(project, pillar_api())
        extension_sidebar_links = current_app.extension_sidebar_links(project)
    else:
        project = None
        navigation_links = []
        extension_sidebar_links = []

    return render_template('flamenco/index.html',
                           projs_with_summaries=projs_with_summaries,
                           project=project,
                           navigation_links=navigation_links,
                           extension_sidebar_links=extension_sidebar_links)
예제 #2
0
def edit(project_url):
    api = system_util.pillar_api()
    # Fetch the Node or 404
    try:
        project = Project.find_one({'where': {'url': project_url}}, api=api)
        # project = Project.find(project_url, api=api)
    except ResourceNotFound:
        abort(404)
    utils.attach_project_pictures(project, api)
    form = ProjectForm(
        project_id=project._id,
        name=project.name,
        url=project.url,
        summary=project.summary,
        description=project.description,
        is_private='GET' not in project.permissions.world,
        category=project.category,
        status=project.status,
    )

    if form.validate_on_submit():
        project = Project.find(project._id, api=api)
        project.name = form.name.data
        project.url = form.url.data
        project.summary = form.summary.data
        project.description = form.description.data
        project.category = form.category.data
        project.status = form.status.data
        if form.picture_square.data:
            project.picture_square = form.picture_square.data
        if form.picture_header.data:
            project.picture_header = form.picture_header.data

        # Update world permissions from is_private checkbox
        if form.is_private.data:
            project.permissions.world = []
        else:
            project.permissions.world = ['GET']

        project.update(api=api)
        # Reattach the pictures
        utils.attach_project_pictures(project, api)
    else:
        if project.picture_square:
            form.picture_square.data = project.picture_square._id
        if project.picture_header:
            form.picture_header.data = project.picture_header._id

    # List of fields from the form that should be hidden to regular users
    if current_user.has_role('admin'):
        hidden_fields = []
    else:
        hidden_fields = ['url', 'status', 'is_private', 'category']

    return render_template('projects/edit.html',
                           form=form,
                           hidden_fields=hidden_fields,
                           project=project,
                           ext_pages=find_extension_pages(),
                           api=api)
예제 #3
0
def index():
    api = pillar_api()

    # FIXME Sybren: add permission check.
    # TODO: add projections.
    projects = current_flamenco.flamenco_projects()

    for project in projects['_items']:
        attach_project_pictures(project, api)

    projs_with_summaries = [
        (proj, current_flamenco.job_manager.job_status_summary(proj['_id']))
        for proj in projects['_items']
    ]

    last_project = session.get('flamenco_last_project')
    if last_project:
        project = Project(last_project)
        navigation_links = project_navigation_links(project, pillar_api())
        extension_sidebar_links = current_app.extension_sidebar_links(project)
    else:
        project = None
        navigation_links = []
        extension_sidebar_links = []

    return render_template('flamenco/index.html',
                           projs_with_summaries=projs_with_summaries,
                           project=project,
                           navigation_links=navigation_links,
                           extension_sidebar_links=extension_sidebar_links)
예제 #4
0
def index():
    api = system_util.pillar_api()

    # Get all projects, except the home project.
    projects_user = Project.all({
        'where': {'user': current_user.objectid,
                  'category': {'$ne': 'home'}},
        'sort': '-_created'
    }, api=api)

    projects_shared = Project.all({
        'where': {'user': {'$ne': current_user.objectid},
                  'permissions.groups.group': {'$in': current_user.groups},
                  'is_private': True},
        'sort': '-_created',
        'embedded': {'user': 1},
    }, api=api)

    # Attach project images
    for project in projects_user['_items']:
        utils.attach_project_pictures(project, api)

    for project in projects_shared['_items']:
        utils.attach_project_pictures(project, api)

    return render_template(
        'projects/index_dashboard.html',
        gravatar=utils.gravatar(current_user.email, size=128),
        projects_user=projects_user['_items'],
        projects_shared=projects_shared['_items'],
        api=api)
예제 #5
0
def index(community_url):
    api = system_util.pillar_api()

    project = Project.find_first({'where': {'url': community_url}}, api=api)

    if project is None:
        return abort(404)

    attach_project_pictures(project, api)

    # Fetch all activities for the main project
    activities = Activity.all({
        'where': {
            'project': project['_id'],
        },
        'sort': [('_created', -1)],
        'max_results': 15,
    }, api=api)

    # Fetch more info for each activity.
    for act in activities['_items']:
        act.actor_user = subquery.get_user_info(act.actor_user)
        try:
            act.link = url_for_node(node_id=act.object)
        except ValueError:
            # If the node was delete, we get ValueError exception.
            # By setting act.link to '', it does not get displayed in the list.
            act.link = ''

    return render_template(
        'dillo/index.html',
        col_right={'activities': activities},
        project=project,
        submit_menu=project_submit_menu(project))
예제 #6
0
def search(project_url):
    """Search into a project"""
    api = system_util.pillar_api()
    project = find_project_or_404(project_url, api=api)
    utils.attach_project_pictures(project, api)

    return render_template('nodes/search.html',
                           project=project,
                           og_picture=project.picture_header)
예제 #7
0
def edit_node_type(project_url, node_type_name):
    api = system_util.pillar_api()
    # Fetch the Node or 404
    try:
        project = Project.find_one({'where': {'url': project_url}}, api=api)
    except ResourceNotFound:
        return abort(404)

    utils.attach_project_pictures(project, api)
    node_type = project.get_node_type(node_type_name)
    form = NodeTypeForm()

    if form.validate_on_submit():
        # Update dynamic & form schemas
        dyn_schema = json.loads(form.dyn_schema.data)
        node_type.dyn_schema = dyn_schema
        form_schema = json.loads(form.form_schema.data)
        node_type.form_schema = form_schema
        node_type.description = form.description.data

        # Update permissions
        permissions = json.loads(form.permissions.data)
        node_type.permissions = permissions

        project.update(api=api)
    elif request.method == 'GET':
        form.project_id.data = project._id
        if node_type:
            form.name.data = node_type.name
            form.description.data = node_type.description
            form.parent.data = node_type.parent

            dyn_schema = node_type.dyn_schema.to_dict()
            form_schema = node_type.form_schema.to_dict()
            if 'permissions' in node_type:
                permissions = node_type.permissions.to_dict()
            else:
                permissions = {}

            form.form_schema.data = json.dumps(form_schema, indent=4)
            form.dyn_schema.data = json.dumps(dyn_schema, indent=4)
            form.permissions.data = json.dumps(permissions, indent=4)

    if request.method == 'POST':
        # Send back a JSON response, as this is actually called
        # from JS instead of rendered as page.
        if form.errors:
            resp = jsonify({'_message': str(form.errors)})
            resp.status_code = 400
            return resp
        return jsonify({'_message': 'ok'})

    return render_template('projects/edit_node_type_embed.html',
                           form=form,
                           project=project,
                           api=api,
                           node_type=node_type)
예제 #8
0
def index_all():
    """Landing page. Posts are loaded asynchronously."""
    api = system_util.pillar_api()
    project = get_main_project()
    attach_project_pictures(project, api)

    return render_template(
        'dillo/index.html',
        col_right={'activities': {'_meta': {'total': 0}}},
        project=project)
예제 #9
0
        def main_project():
            """Fetch the current project, including images.

            Because this is a cached function, using a storage solution with
            expiring links is not supported.
            """

            # TODO: switch to get_main_project() from Pillar
            project = pillarsdk.Project.find_by_url('default-project', api=api)
            attach_project_pictures(project, api)
            return project
예제 #10
0
def index():
    api = pillar_api()

    # FIXME Sybren: add permission check.
    # TODO: add projections.
    projects = current_svnman.svnman_projects()

    for project in projects['_items']:
        attach_project_pictures(project, api)

    return render_template('svnman/index.html', projects=projects)
예제 #11
0
def index_all():
    """Aggregated view of all posts for the public communities.

    If a user has a set of favourite communites in its settings, use those
    instead.
    """
    api = system_util.pillar_api()
    project = get_main_project()
    attach_project_pictures(project, api)

    return render_template(
        'dillo/index.html',
        col_right={'activities': {'_meta': {'total': 0}}},
        project=project)
예제 #12
0
def edit_node_types(project_url):
    api = system_util.pillar_api()
    # Fetch the project or 404
    try:
        project = Project.find_one({
            'where': '{"url" : "%s"}' % (project_url)}, api=api)
    except ResourceNotFound:
        return abort(404)

    utils.attach_project_pictures(project, api)

    return render_template('projects/edit_node_types.html',
                           api=api,
                           ext_pages=find_extension_pages(),
                           project=project)
예제 #13
0
def index():
    api = pillar_api()

    user = flask_login.current_user
    if user.is_authenticated:
        tasks = current_flamenco.task_manager.tasks_for_user(user.objectid)

    else:
        tasks = None

    # TODO: add projections.
    projects = current_flamenco.flamenco_projects()

    for project in projects['_items']:
        attach_project_pictures(project, api)

    projs_with_summaries = [
        (proj, current_flamenco.job_manager.job_status_summary(proj['_id']))
        for proj in projects['_items']
    ]

    # Fetch all activities for all Flamenco projects.
    id_to_proj = {p['_id']: p for p in projects['_items']}
    activities = pillarsdk.Activity.all(
        {
            'where': {
                'project': {
                    '$in': list(id_to_proj.keys())
                },
            },
            'sort': [('_created', -1)],
            'max_results': 20,
        },
        api=api)

    # Fetch more info for each activity.
    for act in activities['_items']:
        act.actor_user = pillar.web.subquery.get_user_info(act.actor_user)
        act.project = id_to_proj[act.project]
        try:
            act.link = current_flamenco.link_for_activity(act)
        except ValueError:
            act.link = None

    return render_template('flamenco/index.html',
                           tasks=tasks,
                           projs_with_summaries=projs_with_summaries,
                           activities=activities)
예제 #14
0
        def wrapper(project_url, *args, **kwargs):
            if isinstance(project_url, pillarsdk.Resource):
                # This is already a resource, so this call probably is from one
                # view to another. Assume the caller knows what he's doing and
                # just pass everything along.
                return wrapped(project_url, *args, **kwargs)

            api = system_util.pillar_api()

            project = pillarsdk.Project.find_by_url(
                project_url,
                {'projection': projections} if projections else None,
                api=api)
            utils.attach_project_pictures(project, api)

            return wrapped(project, *args, **kwargs)
예제 #15
0
def edit_node_type(project_url, node_type_name):
    api = system_util.pillar_api()
    # Fetch the Node or 404
    try:
        project = Project.find_one({
            'where': '{"url" : "%s"}' % (project_url)}, api=api)
    except ResourceNotFound:
        return abort(404)
    utils.attach_project_pictures(project, api)
    node_type = project.get_node_type(node_type_name)
    form = NodeTypeForm()
    if form.validate_on_submit():
        # Update dynamic & form schemas
        dyn_schema = json.loads(form.dyn_schema.data)
        node_type.dyn_schema = dyn_schema
        form_schema = json.loads(form.form_schema.data)
        node_type.form_schema = form_schema
        node_type.description = form.description.data

        # Update permissions
        permissions = json.loads(form.permissions.data)
        node_type.permissions = permissions

        project.update(api=api)
    elif request.method == 'GET':
        form.project_id.data = project._id
        if node_type:
            form.name.data = node_type.name
            form.description.data = node_type.description
            form.parent.data = node_type.parent

            dyn_schema = node_type.dyn_schema.to_dict()
            form_schema = node_type.form_schema.to_dict()
            if 'permissions' in node_type:
                permissions = node_type.permissions.to_dict()
            else:
                permissions = {}

            form.form_schema.data = json.dumps(form_schema, indent=4)
            form.dyn_schema.data = json.dumps(dyn_schema, indent=4)
            form.permissions.data = json.dumps(permissions, indent=4)

    return render_template('projects/edit_node_type_embed.html',
                           form=form,
                           project=project,
                           api=api,
                           node_type=node_type)
예제 #16
0
def index():
    api = pillar_api()

    # FIXME Sybren: add permission check.
    # TODO: add projections.
    projects = current_flamenco.flamenco_projects()

    for project in projects['_items']:
        attach_project_pictures(project, api)

    projs_with_summaries = [
        (proj, current_flamenco.job_manager.job_status_summary(proj['_id']))
        for proj in projects['_items']
    ]

    return render_template('flamenco/index.html',
                           projs_with_summaries=projs_with_summaries)
예제 #17
0
def get_projects(category):
    """Utility to get projects based on category. Should be moved on the API
    and improved with more extensive filtering capabilities.
    """
    api = system_util.pillar_api()
    projects = Project.all(
        {
            'where': {
                'category': category,
                'is_private': False
            },
            'sort': '-_created',
        },
        api=api)
    for project in projects._items:
        attach_project_pictures(project, api)
    return projects
예제 #18
0
def posts_create(project_id):
    api = system_util.pillar_api()
    try:
        project = Project.find(project_id, api=api)
    except ResourceNotFound:
        return abort(404)
    attach_project_pictures(project, api)

    blog = Node.find_one(
        {'where': {
            'node_type': 'blog',
            'project': project_id
        }}, api=api)
    node_type = project.get_node_type('post')
    # Check if user is allowed to create a post in the blog
    if not project.node_type_has_method('post', 'POST', api=api):
        return abort(403)
    form = get_node_form(node_type)
    if form.validate_on_submit():
        # Create new post object from scratch
        post_props = dict(node_type='post',
                          name=form.name.data,
                          picture=form.picture.data,
                          user=current_user.objectid,
                          parent=blog._id,
                          project=project._id,
                          properties=dict(content=form.content.data,
                                          status=form.status.data,
                                          url=form.url.data))
        if form.picture.data == '':
            post_props['picture'] = None
        post = Node(post_props)
        post.create(api=api)
        # Only if the node is set as published, push it to the list
        if post.properties.status == 'published':
            project_update_nodes_list(post,
                                      project_id=project._id,
                                      list_name='blog')
        return redirect(url_for_node(node=post))
    form.parent.data = blog._id
    return render_template('nodes/custom/post/create.html',
                           node_type=node_type,
                           form=form,
                           project=project,
                           api=api)
예제 #19
0
def view(community_url, post_shortcode, slug=None):
    api = system_util.pillar_api()
    project = Project.find_by_url(community_url, api=api)
    attach_project_pictures(project, api)

    post = Node.find_one({
        'where': {
            'project': project['_id'],
            'properties.shortcode': post_shortcode},
        'embedded': {'user': 1}}, api=api)

    if post.picture:
        post.picture = get_file(post.picture, api=api)

    return render_template(
        'dillo/index.html',
        project=project,
        submit_menu=project_submit_menu(project),
        col_right={'post': post})
예제 #20
0
def sharing(project_url):
    api = system_util.pillar_api()
    # Fetch the project or 404
    try:
        project = Project.find_one({'where': {'url': project_url}}, api=api)
    except ResourceNotFound:
        return abort(404)

    # Fetch users that are part of the admin group
    users = project.get_users(api=api)

    if request.method == 'POST':
        user_id = request.form['user_id']
        action = request.form['action']
        try:
            if action == 'add':
                user = project.add_user(user_id, api=api)
            elif action == 'remove':
                user = project.remove_user(user_id, api=api)
            else:
                raise wz_exceptions.BadRequest(f'invalid action {action}')
        except ResourceNotFound:
            log.info('/p/%s/edit/sharing: User %s not found', project_url,
                     user_id)
            return jsonify({
                '_status': 'ERROR',
                'message': 'User %s not found' % user_id
            }), 404

        user['avatar'] = pillar.api.users.avatar.url(user)
        return jsonify(user)

    utils.attach_project_pictures(project, api)

    return render_template('projects/sharing.html',
                           api=api,
                           project=project,
                           ext_pages=find_extension_pages(),
                           users=users['_items'])
예제 #21
0
def sharing(project_url):
    api = system_util.pillar_api()
    # Fetch the project or 404
    try:
        project = Project.find_one({
            'where': '{"url" : "%s"}' % (project_url)}, api=api)
    except ResourceNotFound:
        return abort(404)

    # Fetch users that are part of the admin group
    users = project.get_users(api=api)
    for user in users['_items']:
        user['avatar'] = utils.gravatar(user['email'])

    if request.method == 'POST':
        user_id = request.form['user_id']
        action = request.form['action']
        try:
            if action == 'add':
                user = project.add_user(user_id, api=api)
            elif action == 'remove':
                user = project.remove_user(user_id, api=api)
        except ResourceNotFound:
            log.info('/p/%s/edit/sharing: User %s not found', project_url, user_id)
            return jsonify({'_status': 'ERROR',
                            'message': 'User %s not found' % user_id}), 404

        # Add gravatar to user
        user['avatar'] = utils.gravatar(user['email'])
        return jsonify(user)

    utils.attach_project_pictures(project, api)

    return render_template('projects/sharing.html',
                           api=api,
                           project=project,
                           ext_pages=find_extension_pages(),
                           users=users['_items'])
예제 #22
0
        def communities():
            """Fetch all public communities."""

            params = {
                'where': {
                    'extension_props.dillo': {
                        '$exists': 1
                    },
                    'is_private': False,
                },
                'projection': {
                    'picture_square': 1,
                    'url': 1,
                    'name': 1,
                    'summary': 1,
                    'extension_props': 1,
                }
            }

            projects = pillarsdk.Project.all(params, api=api)
            for project in projects['_items']:
                attach_project_pictures(project, api)

            return projects['_items']
예제 #23
0
파일: routes.py 프로젝트: babbysross/pillar
def edit(node_id):
    """Generic node editing form, displayed only if the user is allowed.
    """
    def set_properties(dyn_schema,
                       form_schema,
                       node_properties,
                       form,
                       set_data,
                       prefix=""):
        """Initialize custom properties for the form. We run this function once
        before validating the function with set_data=False, so that we can set
        any multiselect field that was originally specified empty and fill it
        with the current choices.
        """

        log.debug('set_properties(..., prefix=%r, set_data=%r) called', prefix,
                  set_data)

        for prop, schema_prop in dyn_schema.items():
            prop_name = "{0}{1}".format(prefix, prop)

            if prop_name not in form:
                continue

            try:
                db_prop_value = node_properties[prop]
            except KeyError:
                log.debug('%s not found in form for node %s', prop_name,
                          node_id)
                continue

            if schema_prop['type'] == 'datetime':
                db_prop_value = datetime.strptime(
                    db_prop_value, current_app.config['RFC1123_DATE_FORMAT'])

            if isinstance(form[prop_name], SelectMultipleField):
                # If we are dealing with a multiselect field, check if
                # it's empty (usually because we can't query the whole
                # database to pick all the choices). If it's empty we
                # populate the choices with the actual data.
                if not form[prop_name].choices:
                    form[prop_name].choices = [(d, d) for d in db_prop_value]
                    # Choices should be a tuple with value and name
            if not set_data:
                continue

            # Assign data to the field
            if prop_name == 'attachments':
                # If attachments is an empty list, do not append data
                if not db_prop_value:
                    continue
                attachments.attachment_form_group_set_data(
                    db_prop_value, schema_prop, form[prop_name])
            elif prop_name == 'files':
                subschema = schema_prop['schema']['schema']
                # Extra entries are caused by min_entries=1 in the form
                # creation.
                field_list = form[prop_name]
                if len(db_prop_value):
                    while len(field_list):
                        field_list.pop_entry()

                for file_data in db_prop_value:
                    file_form_class = build_file_select_form(subschema)
                    subform = file_form_class()
                    for key, value in file_data.items():
                        setattr(subform, key, value)
                    field_list.append_entry(subform)

            # elif prop_name == 'tags':
            #     form[prop_name].data = ', '.join(data)
            else:
                form[prop_name].data = db_prop_value

    api = system_util.pillar_api()
    node = Node.find(node_id, api=api)

    # We do not want to display the page to users who can't PUT
    if 'PUT' not in node.allowed_methods:
        raise wz_exceptions.Forbidden()

    project = Project.find(node.project, api=api)
    node_type = project.get_node_type(node.node_type)
    form = get_node_form(node_type)
    user_id = current_user.objectid
    dyn_schema = node_type['dyn_schema'].to_dict()
    form_schema = node_type['form_schema'].to_dict()
    error = ""
    node_properties = node.properties.to_dict()

    ensure_lists_exist_as_empty(node.to_dict(), node_type)
    set_properties(dyn_schema,
                   form_schema,
                   node_properties,
                   form,
                   set_data=False)

    if form.validate_on_submit():
        if process_node_form(form,
                             node_id=node_id,
                             node_type=node_type,
                             user=user_id):
            # Handle the specific case of a blog post
            if node_type.name == 'post':
                project_update_nodes_list(node,
                                          project_id=project._id,
                                          list_name='blog')
            else:
                try:
                    project_update_nodes_list(node, project_id=project._id)
                except ForbiddenAccess:
                    # TODO (fsiddi): Implement this as a blender-cloud-only hook
                    log.debug(
                        'User %s not allowed to update latest_nodes in %s' %
                        (user_id, project._id))
            return redirect(
                url_for('nodes.view',
                        node_id=node_id,
                        embed=1,
                        _external=True,
                        _scheme=current_app.config['SCHEME']))
        else:
            log.debug('Error sending data to Pillar, see Pillar logs.')
            error = 'Server error'
    else:
        if form.errors:
            log.debug('Form errors: %s', form.errors)
    # Populate Form
    form.name.data = node.name
    form.description.data = node.description
    if 'picture' in form:
        form.picture.data = node.picture
    if node.parent:
        form.parent.data = node.parent
    set_properties(dyn_schema,
                   form_schema,
                   node_properties,
                   form,
                   set_data=True)

    # Get previews
    node.picture = get_file(node.picture, api=api) if node.picture else None

    # Get Parent
    try:
        parent = Node.find(node['parent'], api=api)
    except KeyError:
        parent = None
    except ResourceNotFound:
        parent = None

    embed_string = ''
    # Check if we want to embed the content via an AJAX call
    if request.args.get('embed') == '1':
        # Define the prefix for the embedded template
        embed_string = '_embed'
    else:
        attach_project_pictures(project, api)

    template = 'nodes/custom/{0}/edit{1}.html'.format(node_type['name'],
                                                      embed_string)
    # We should more simply check if the template file actually exists on the filesystem
    try:
        return render_template(
            template,
            node=node,
            parent=parent,
            form=form,
            errors=form.errors,
            error=error,
            api=api,
            project=project,
        )
    except TemplateNotFound:
        template = 'nodes/edit{1}.html'.format(node_type['name'], embed_string)
        is_embedded_edit = True if embed_string else False
        return render_template(
            template,
            node=node,
            parent=parent,
            form=form,
            errors=form.errors,
            error=error,
            api=api,
            project=project,
            is_embedded_edit=is_embedded_edit,
        )
예제 #24
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)
    project: typing.Optional[Project] = None
    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:
            if theatre_mode:
                pass  # In theatre mode, we don't need access to the project at all.
            else:
                raise wz_exceptions.NotFound('No such project')

    navigation_links = []
    extension_sidebar_links = ''
    og_picture = node.picture = utils.get_file(node.picture, api=api)
    if project:
        utils.attach_project_pictures(project, api)
        if not node.picture:
            og_picture = project.picture_16_9
        navigation_links = project_navigation_links(project, api)
        extension_sidebar_links = current_app.extension_sidebar_links(project)

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

    if node.node_type == 'page':
        return render_template(
            'nodes/custom/page/view_embed.html',
            api=api,
            node=node,
            project=project,
            navigation_links=navigation_links,
            extension_sidebar_links=extension_sidebar_links,
            og_picture=og_picture,
        )

    return render_template(
        'projects/view{}.html'.format(theatre),
        api=api,
        project=project,
        node=node,
        show_node=True,
        show_project=False,
        og_picture=og_picture,
        navigation_links=navigation_links,
        extension_sidebar_links=extension_sidebar_links,
    )
예제 #25
0
def posts_view(project_id=None,
               project_url=None,
               url=None,
               *,
               archive=False,
               page=1):
    """View individual blogpost"""

    if bool(project_id) == bool(project_url):
        raise ValueError('posts_view(): pass either project_id or project_url')

    if url and archive:
        raise ValueError('posts_view(): cannot pass both url and archive')

    api = system_util.pillar_api()

    # Fetch project (for background images and links generation)
    if project_id:
        project = Project.find(project_id, api=api)
    else:
        project = Project.find_one({'where': {'url': project_url}}, api=api)
        project_id = project['_id']

    attach_project_pictures(project, api)

    blog = Node.find_one(
        {
            'where': {
                'node_type': 'blog',
                'project': project_id
            },
        }, api=api)

    status_query = {} if blog.has_method('PUT') else {
        'properties.status': 'published'
    }
    posts = Node.all(
        {
            'where': {
                'parent': blog._id,
                **status_query
            },
            'embedded': {
                'user': 1
            },
            'sort': '-_created',
            'max_results': 20 if archive else 5,
            'page': page,
        },
        api=api)

    for post in posts._items:
        post.picture = get_file(post.picture, api=api)
        post.url = url_for_node(node=post)

    # Use the *_main_project.html template for the main blog
    is_main_project = project_id == current_app.config['MAIN_PROJECT_ID']
    main_project_template = '_main_project' if is_main_project else ''
    main_project_template = '_main_project'
    index_arch = 'archive' if archive else 'index'
    template_path = f'nodes/custom/blog/{index_arch}{main_project_template}.html',

    if url:
        template_path = f'nodes/custom/post/view{main_project_template}.html',

        post = Node.find_one(
            {
                'where': {
                    'parent': blog._id,
                    'properties.url': url
                },
                'embedded': {
                    'node_type': 1,
                    'user': 1
                },
            },
            api=api)

        if post.picture:
            post.picture = get_file(post.picture, api=api)

        post.url = url_for_node(node=post)
    elif posts._items:
        post = posts._items[0]
    else:
        post = None

    if post is not None:
        # If post is not published, check that the user is also the author of
        # the post. If not, return an error.
        if post.properties.status != "published":
            if not (current_user.is_authenticated and post.has_method('PUT')):
                abort(403)

    can_create_blog_posts = project.node_type_has_method('post',
                                                         'POST',
                                                         api=api)

    # Use functools.partial so we can later pass page=X.
    if is_main_project:
        url_func = functools.partial(url_for, 'main.main_blog_archive')
    else:
        url_func = functools.partial(url_for,
                                     'main.project_blog_archive',
                                     project_url=project.url)

    project.blog_archive_url = url_func()
    pmeta = posts._meta
    seen_now = pmeta['max_results'] * pmeta['page']
    if pmeta['total'] > seen_now:
        project.blog_archive_next = url_func(page=pmeta['page'] + 1)
    else:
        project.blog_archive_next = None
    if pmeta['page'] > 1:
        project.blog_archive_prev = url_func(page=pmeta['page'] - 1)
    else:
        project.blog_archive_prev = None

    title = 'blog_main' if is_main_project else 'blog'

    pages = Node.all(
        {
            'where': {
                'project': project._id,
                'node_type': 'page'
            },
            'projection': {
                'name': 1
            }
        },
        api=api)

    return render_template(
        template_path,
        blog=blog,
        node=post,
        posts=posts._items,
        posts_meta=pmeta,
        more_posts_available=pmeta['total'] > pmeta['max_results'],
        project=project,
        title=title,
        node_type_post=project.get_node_type('post'),
        can_create_blog_posts=can_create_blog_posts,
        pages=pages._items,
        api=api)
예제 #26
0
파일: routes.py 프로젝트: jonike/dillo
def users_view(username):
    """View public user page.

    Use direct db call to retrieve the user and then use the api to query the paginated list of all
    published dillo_posts from the user.

    """
    users_coll = current_app.db('users')
    user = users_coll.find_one({'username': username},
                               projection={
                                   'username': 1,
                                   'full_name': 1,
                                   'email': 1,
                                   'extension_props_public': 1,
                                   '_updated': 1,
                                   '_created': 1,
                               })
    if user is None:
        return abort(404)
    api = system_util.pillar_api()
    nodes_coll = current_app.db('nodes')

    pipeline = [{
        '$match': {
            'user': ObjectId(user['_id']),
            'node_type': 'dillo_post',
            'properties.status': 'published',
            '_deleted': False
        }
    }, {
        '$lookup': {
            'from': 'projects',
            'localField': 'project',
            'foreignField': '_id',
            'as': 'project'
        }
    }, {
        '$project': {
            'name': 1,
            'properties': 1,
            'user': 1,
            'picture': 1,
            '_created': 1,
            'project': {
                '$arrayElemAt': ['$project', 0]
            }
        }
    }, {
        '$sort': {
            '_created': -1
        }
    }]

    posts = list(nodes_coll.aggregate(pipeline=pipeline))

    for post in posts:
        if post.get('picture'):
            post['picture'] = get_file(post['picture'], api=api)

    main_project_url = current_app.config['DEFAULT_COMMUNITY']
    project = Project.find_by_url(main_project_url, api=api)
    attach_project_pictures(project, api)

    # Fetch all comments activity for the user
    activities = Activity.all(
        {
            'where': {
                'actor_user': str(user['_id']),
                'node_type': 'comment'
            },
            'sort': [('_created', -1)],
            'max_results': 15,
        },
        api=api)

    # Fetch more info for each activity.
    for act in activities['_items']:
        act.actor_user = subquery.get_user_info(act.actor_user)
        try:
            act.link = url_for_node(node_id=act.object)
        except ValueError:
            # TODO: properly handle the case when the activity object has been deleted
            continue

    return render_template('dillo/user.html',
                           col_right={'activities': activities},
                           user=user,
                           posts=posts,
                           project=project)
예제 #27
0
def posts_view(project_id=None, project_url=None, url=None):
    """View individual blogpost"""

    if bool(project_id) == bool(project_url):
        raise ValueError('posts_view(): pass either project_id or project_url')

    api = system_util.pillar_api()

    # Fetch project (for backgroud images and links generation)
    if project_id:
        project = Project.find(project_id, api=api)
    else:
        project = Project.find_one({'where': {'url': project_url}}, api=api)
        project_id = project['_id']

    attach_project_pictures(project, api)

    blog = Node.find_one(
        {
            'where': {
                'node_type': 'blog',
                'project': project_id
            },
        }, api=api)

    status_query = "" if blog.has_method(
        'PUT') else ', "properties.status": "published"'
    posts = Node.all(
        {
            'where': '{"parent": "%s" %s}' % (blog._id, status_query),
            'embedded': '{"user": 1}',
            'sort': '-_created'
        },
        api=api)

    for post in posts._items:
        post.picture = get_file(post.picture, api=api)

        post['properties'][
            'content'] = pillar.web.nodes.attachments.render_attachments(
                post, post['properties']['content'])

    # Use the *_main_project.html template for the main blog
    main_project_template = '_main_project' if project_id == current_app.config[
        'MAIN_PROJECT_ID'] else ''

    if url:
        post = Node.find_one(
            {
                'where': {
                    'parent': blog._id,
                    'properties.url': url
                },
                'embedded': {
                    'node_type': 1,
                    'user': 1
                },
            },
            api=api)
        if post.picture:
            post.picture = get_file(post.picture, api=api)

        # If post is not published, check that the user is also the author of
        # the post. If not, return 404.
        if post.properties.status != "published":
            if not (current_user.is_authenticated and post.has_method('PUT')):
                abort(403)

        post['properties'][
            'content'] = pillar.web.nodes.attachments.render_attachments(
                post, post['properties']['content'])
        return render_template(
            'nodes/custom/post/view{0}.html'.format(main_project_template),
            blog=blog,
            node=post,
            posts=posts._items,
            project=project,
            title='blog',
            api=api)
    else:
        node_type_post = project.get_node_type('post')
        template_path = 'nodes/custom/blog/index.html'

        return render_template(
            'nodes/custom/blog/index{0}.html'.format(main_project_template),
            node_type_post=node_type_post,
            posts=posts._items,
            project=project,
            title='blog',
            api=api)
예제 #28
0
def render_project(project, api, extra_context=None, template_name=None):
    utils.attach_project_pictures(project, api)

    def load_latest(list_of_ids, node_type=None):
        """Loads a list of IDs in reversed order."""

        if not list_of_ids:
            return []

        # Construct query parameters outside the loop.
        projection = {
            'name': 1,
            'user': 1,
            'node_type': 1,
            'project': 1,
            'properties.url': 1,
            'properties.content_type': 1,
            'properties.duration_seconds': 1,
            'picture': 1
        }
        params = {'projection': projection, 'embedded': {'user': 1}}

        if node_type == 'post':
            projection['properties.content'] = 1
        elif node_type == 'asset':
            projection['description'] = 1

        list_latest = []
        for node_id in reversed(list_of_ids or ()):
            try:
                node_item = Node.find(node_id, params, api=api)

                node_item.picture = utils.get_file(node_item.picture, api=api)
                list_latest.append(node_item)
            except ForbiddenAccess:
                pass
            except ResourceNotFound:
                log.warning('Project %s refers to removed node %s!',
                            project._id, node_id)

        return list_latest

    project.nodes_featured = load_latest(project.nodes_featured,
                                         node_type='asset')
    project.nodes_blog = load_latest(project.nodes_blog, node_type='post')

    # Merge featured assets and blog posts into one activity stream
    def sort_key(item):
        return item._created

    activities = itertools.chain(project.nodes_featured, project.nodes_blog)
    activity_stream = sorted(activities, key=sort_key, reverse=True)

    if extra_context is None:
        extra_context = {}

    if project.category == 'home' and not current_app.config[
            'RENDER_HOME_AS_REGULAR_PROJECT']:
        template_name = template_name or 'projects/home_index.html'
        return render_template(template_name,
                               project=project,
                               api=system_util.pillar_api(),
                               **extra_context)

    if template_name is None:
        if request.args.get('embed'):
            embed_string = '_embed'
        else:
            embed_string = ''
        template_name = "projects/view{0}.html".format(embed_string)

    navigation_links = project_navigation_links(project, api)
    extension_sidebar_links = current_app.extension_sidebar_links(project)

    return render_template(template_name,
                           api=api,
                           project=project,
                           node=None,
                           show_node=False,
                           show_project=True,
                           og_picture=project.picture_16_9,
                           activity_stream=activity_stream,
                           navigation_links=navigation_links,
                           extension_sidebar_links=extension_sidebar_links,
                           **extra_context)