コード例 #1
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)
コード例 #2
0
ファイル: __init__.py プロジェクト: aditiapratama/pillar-web
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)
    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=u'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 = [u'GET']

        project.update(api=api)
        # Reattach the pictures
        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,
                           title="edit",
                           api=api)
コード例 #3
0
ファイル: comments.py プロジェクト: aditiapratama/pillar-web
def comments_index():
    parent_id = request.args.get('parent_id')
    # Get data only if we format it
    api = system_util.pillar_api()
    if request.args.get('format'):
        nodes = Node.all({
            'where': '{"node_type" : "comment", "parent": "%s"}' % (parent_id),
            'embedded': '{"user":1}'}, api=api)

        comments = []
        for comment in nodes._items:
            # Query for first level children (comment replies)
            replies = Node.all({
                'where': '{"node_type" : "comment", "parent": "%s"}' % (comment._id),
                'embedded': '{"user":1}'}, api=api)
            replies = replies._items if replies._items else None
            if replies:
                replies = [format_comment(reply, is_reply=True) for reply in replies]

            comments.append(
                format_comment(comment, is_reply=False, replies=replies))

        if request.args.get('format') == 'json':
            return_content = jsonify(items=[c for c in comments if c is not None])
    else:
        parent_node = Node.find(parent_id, api=api)
        project = Project.find(parent_node.project, api=api)
        has_method_POST = project.node_type_has_method('comment', 'POST', api=api)
        # Data will be requested via javascript
        return_content = render_template('nodes/custom/_comments.html',
            parent_id=parent_id,
            has_method_POST=has_method_POST)
    return return_content
コード例 #4
0
def view_embed(node_id):
    api = system_util.pillar_api()

    # Get node, we'll embed linked objects later.
    try:
        node = Node.find(node_id, api=api)
    except ResourceNotFound:
        return render_template('errors/404_embed.html')
    except ForbiddenAccess:
        return render_template('errors/403_embed.html')

    project_projection = {'project': {'url': 1, 'name': 1}}
    project = Project.find(node.project, project_projection, api=api)

    node.picture = get_file(node.picture, api=api)
    node.user = node.user and User.find(node.user, api=api)

    write_access = 'PUT' in (node.allowed_methods or set())

    extra_template_args = {'project': project}

    return render_template(
        'nodes/custom/dillo_post/view_embed.html',
        node_id=node._id,
        node=node,
        write_access=write_access,
        api=api,
        **extra_template_args)
コード例 #5
0
def delete():
    """Unapologetically deletes a project"""
    api = system_util.pillar_api()
    project_id = request.form['project_id']
    project = Project.find(project_id, api=api)
    project.delete(api=api)
    return jsonify(dict(staus='success', data=dict(
        message='Project deleted {}'.format(project['_id']))))
コード例 #6
0
ファイル: __init__.py プロジェクト: aditiapratama/pillar-web
def delete():
    """Unapologetically deletes a project"""
    api = system_util.pillar_api()
    project_id = request.form['project_id']
    project = Project.find(project_id, api=api)
    project.delete(api=api)
    return jsonify(dict(staus='success', data=dict(
        message='Project deleted {}'.format(project['_id']))))
コード例 #7
0
ファイル: __init__.py プロジェクト: aditiapratama/pillar-web
def get_main_project():
    api = system_util.pillar_api()
    try:
        main_project = Project.find(app.config['MAIN_PROJECT_ID'], api=api)
    except ResourceNotFound:
        raise ConfigError('MAIN_PROJECT_ID was not found. Check config.py.')
    except KeyError:
        raise ConfigError('MAIN_PROJECT_ID missing from config.py')
    return main_project
コード例 #8
0
def _homepage_context() -> dict:
    """Returns homepage template context variables."""

    # Get latest blog posts
    api = system_util.pillar_api()

    # Get latest comments to any node
    latest_comments = Node.latest('comments', api=api)

    # Get a list of random featured assets
    random_featured = get_random_featured_nodes()

    # Parse results for replies
    to_remove = []

    @functools.lru_cache()
    def _find_parent(parent_node_id) -> Node:
        return Node.find(parent_node_id, {
            'projection': {
                '_id': 1,
                'name': 1,
                'node_type': 1,
                'project': 1,
                'parent': 1,
                'properties.url': 1,
            }
        },
                         api=api)

    for idx, comment in enumerate(latest_comments._items):
        if comment.properties.is_reply:
            try:
                comment.attached_to = _find_parent(comment.parent.parent)
            except ResourceNotFound:
                # Remove this comment
                to_remove.append(idx)
        else:
            comment.attached_to = comment.parent

    for idx in reversed(to_remove):
        del latest_comments._items[idx]

    for comment in latest_comments._items:
        if not comment.attached_to:
            continue
        comment.attached_to.url = url_for_node(node=comment.attached_to)
        comment.url = url_for_node(node=comment)

    main_project = Project.find(current_app.config['MAIN_PROJECT_ID'], api=api)
    main_project.picture_header = get_file(main_project.picture_header,
                                           api=api)

    return dict(main_project=main_project,
                latest_comments=latest_comments._items,
                random_featured=random_featured)
コード例 #9
0
ファイル: __init__.py プロジェクト: aditiapratama/pillar-web
    def project_or_error():
        """Returns the project, raising a ValueError if it can't be found."""

        if project is not None:
            return project

        try:
            return Project.find(project_id, {'projection': {'url': 1}}, api=api)
        except ResourceNotFound:
            log.warning('url_for_node(node_id=%r): Unable to find project %r',
                        node_id, project_id)
            raise ValueError('Unable to find node project %r' % project_id)
コード例 #10
0
ファイル: __init__.py プロジェクト: aditiapratama/pillar-web
def homepage():
    """Homepage"""

    if not current_user.is_authenticated():
        return render_template(
            'join.html',
            title="join")

    # Get latest blog posts
    api = system_util.pillar_api()
    latest_posts = Node.all({
        'projection': {'name': 1, 'project': 1, 'user': 1, 'node_type': 1,
                       'picture': 1, 'properties.status': 1, 'properties.url': 1},
        'where': {'node_type': 'post', 'properties.status': 'published'},
        'embedded': {'user': 1, 'project': 1},
        'sort': '-_created',
        'max_results': '3'
        }, api=api)

    # Append picture Files to last_posts
    for post in latest_posts._items:
        if post.picture:
            post.picture = get_file(post.picture, api=api)

    # Get latest assets added to any project
    latest_assets = Node.latest('assets', api=api)

    # Append picture Files to latest_assets
    for asset in latest_assets._items:
        if asset.picture:
            asset.picture = get_file(asset.picture, api=api)

    # Get latest comments to any node
    latest_comments = Node.latest('comments', api=api)

    # Parse results for replies
    for comment in latest_comments._items:
        if comment.properties.is_reply:
            comment.parent = Node.find(comment.parent.parent, api=api)
        else:
            comment.parent = comment.parent

    main_project = Project.find(app.config['MAIN_PROJECT_ID'], api=api)
    main_project.picture_square = get_file(main_project.picture_square, api=api)
    main_project.picture_header = get_file(main_project.picture_header, api=api)

    return render_template(
        'homepage.html',
        main_project=main_project,
        latest_posts=latest_posts._items,
        latest_assets=latest_assets._items,
        latest_comments=latest_comments._items,
        api=api)
コード例 #11
0
    def project_or_error():
        """Returns the project, raising a ValueError if it can't be found."""

        if project is not None:
            return project

        try:
            return Project.find(project_id, {'projection': {
                'url': 1
            }},
                                api=api)
        except ResourceNotFound:
            log.warning('url_for_node(node_id=%r): Unable to find project %r',
                        node_id, project_id)
            raise ValueError('Unable to find node project %r' % project_id)
コード例 #12
0
def comments_index():
    parent_id = request.args.get('parent_id')
    # Get data only if we format it
    api = system_util.pillar_api()
    if request.args.get('format'):
        nodes = Node.all(
            {
                'where': '{"node_type" : "comment", "parent": "%s"}' %
                (parent_id),
                'embedded': '{"user":1}'
            },
            api=api)

        comments = []
        for comment in nodes._items:
            # Query for first level children (comment replies)
            replies = Node.all(
                {
                    'where':
                    '{"node_type" : "comment", "parent": "%s"}' %
                    (comment._id),
                    'embedded':
                    '{"user":1}'
                },
                api=api)
            replies = replies._items if replies._items else None
            if replies:
                replies = [
                    format_comment(reply, is_reply=True) for reply in replies
                ]

            comments.append(
                format_comment(comment, is_reply=False, replies=replies))

        if request.args.get('format') == 'json':
            return_content = jsonify(
                items=[c for c in comments if c is not None])
    else:
        parent_node = Node.find(parent_id, api=api)
        project = Project.find(parent_node.project, api=api)
        has_method_POST = project.node_type_has_method('comment',
                                                       'POST',
                                                       api=api)
        # Data will be requested via javascript
        return_content = render_template('nodes/custom/_comments.html',
                                         parent_id=parent_id,
                                         has_method_POST=has_method_POST)
    return return_content
コード例 #13
0
def populate_feed(feed: AtomFeed, latest_posts):
    """Populate the feed with the provided data."""
    for post in latest_posts._items:
        api = system_util.pillar_api()
        author = post.user.full_name
        updated = post._updated if post._updated else post._created
        project_projection = {'project': {'url': 1}}
        project = Project.find(post.project, project_projection, api=api)
        url = url_for('posts.view', post_shortcode=post.properties.shortcode,
                      community_url=project.url)
        content = post.properties.content[:500]
        feed.add(post.name, str(content),
                 content_type='html',
                 author=author,
                 url=url,
                 updated=updated,
                 published=post._created)
コード例 #14
0
ファイル: posts.py プロジェクト: aditiapratama/pillar-web
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)
コード例 #15
0
ファイル: posts.py プロジェクト: aditiapratama/pillar-web
def posts_edit(post_id):
    api = system_util.pillar_api()

    try:
        post = Node.find(post_id, {'embedded': '{"user": 1}'}, api=api)
    except ResourceNotFound:
        return abort(404)
    # Check if user is allowed to edit the post
    if not post.has_method('PUT'):
        return abort(403)

    project = Project.find(post.project, api=api)
    attach_project_pictures(project, api)

    node_type = project.get_node_type(post.node_type)
    form = get_node_form(node_type)
    if form.validate_on_submit():
        if process_node_form(form,
                             node_id=post_id,
                             node_type=node_type,
                             user=current_user.objectid):
            # The the post is published, add it to the list
            if form.status.data == 'published':
                project_update_nodes_list(post,
                                          project_id=project._id,
                                          list_name='blog')
            return redirect(url_for_node(node=post))
    form.parent.data = post.parent
    form.name.data = post.name
    form.content.data = post.properties.content
    form.status.data = post.properties.status
    form.url.data = post.properties.url
    if post.picture:
        form.picture.data = post.picture
        # Embed picture file
        post.picture = get_file(post.picture, api=api)
    if post.properties.picture_square:
        form.picture_square.data = post.properties.picture_square
    return render_template('nodes/custom/post/edit.html',
                           node_type=node_type,
                           post=post,
                           form=form,
                           project=project,
                           api=api)
コード例 #16
0
ファイル: __init__.py プロジェクト: aditiapratama/pillar-web
def create():
    """Create a node. Requires a number of params:

    - project id
    - node_type
    - parent node (optional)
    """
    if request.method != 'POST':
        return abort(403)

    project_id = request.form['project_id']
    parent_id = request.form.get('parent_id')
    node_type_name = request.form['node_type_name']

    api = system_util.pillar_api()
    # Fetch the Project or 404
    try:
        project = Project.find(project_id, api=api)
    except ResourceNotFound:
        return abort(404)

    node_type = project.get_node_type(node_type_name)
    node_type_name = 'folder' if node_type['name'] == 'group' else \
        node_type['name']

    node_props = dict(
        name='New {}'.format(node_type_name),
        project=project['_id'],
        user=current_user.objectid,
        node_type=node_type['name'],
        properties={}
    )

    if parent_id:
        node_props['parent'] = parent_id

    ensure_lists_exist_as_empty(node_props, node_type)

    node = Node(node_props)
    node.create(api=api)

    return jsonify(status='success', data=dict(asset_id=node['_id']))
コード例 #17
0
ファイル: routes.py プロジェクト: armadillica/flamenco
def redir_job_id(job_id):
    """Redirects to the job view.

    This saves the client from performing another request to find the project URL;
    we do it for them.
    """

    from flask import redirect, url_for
    from .sdk import Job
    from pillarsdk import Project

    # FIXME Sybren: add permission check.

    api = pillar_api()
    j = Job.find(job_id, {'projection': {'project': 1, 'status': 1}}, api=api)
    p = Project.find(j.project, {'projection': {'url': 1}}, api=api)

    target_blueprint = blueprint_for_archived[j.status == 'archived']
    return redirect(url_for(f'{target_blueprint.name}.view_job',
                            project_url=p.url, job_id=j._id))
コード例 #18
0
ファイル: routes.py プロジェクト: wqlxx/flamenco
def redir_job_id(job_id):
    """Redirects to the job view.

    This saves the client from performing another request to find the project URL;
    we do it for them.
    """

    from flask import redirect, url_for
    from .sdk import Job
    from pillarsdk import Project

    # FIXME Sybren: add permission check.

    api = pillar_api()
    j = Job.find(job_id, {'projection': {'project': 1, 'status': 1}}, api=api)
    p = Project.find(j.project, {'projection': {'url': 1}}, api=api)

    target_blueprint = blueprint_for_archived[j.status == 'archived']
    return redirect(url_for(f'{target_blueprint.name}.view_job',
                            project_url=p.url, job_id=j._id))
コード例 #19
0
def redirect_to_task(task_id):
    """Allows creation of task links without knowing the job or project ID."""

    from flamenco.tasks.sdk import Task
    from pillarsdk import Project
    from flask import url_for, redirect

    api = pillar_api()

    task = Task.find(task_id, {'projection': {'project': 1}}, api=api)
    project = Project.find(task['project'], {'projection': {
        'url': 1
    }},
                           api=api)

    # FIXME Sybren: add permission check.

    url = url_for('flamenco.jobs.perproject.for_project_with_task',
                  project_url=project['url'],
                  task_id=task_id)
    return redirect(url, code=301)
コード例 #20
0
ファイル: routes.py プロジェクト: babbysross/pillar
def create():
    """Create a node. Requires a number of params:

    - project id
    - node_type
    - parent node (optional)
    """
    if request.method != 'POST':
        return abort(403)

    project_id = request.form['project_id']
    parent_id = request.form.get('parent_id')
    node_type_name = request.form['node_type_name']

    api = system_util.pillar_api()
    # Fetch the Project or 404
    try:
        project = Project.find(project_id, api=api)
    except ResourceNotFound:
        return abort(404)

    node_type = project.get_node_type(node_type_name)
    node_type_name = 'folder' if node_type['name'] == 'group' else \
        node_type['name']

    node_props = dict(name='New {}'.format(node_type_name),
                      project=project['_id'],
                      user=current_user.objectid,
                      node_type=node_type['name'],
                      properties={})

    if parent_id:
        node_props['parent'] = parent_id

    ensure_lists_exist_as_empty(node_props, node_type)

    node = Node(node_props)
    node.create(api=api)

    return jsonify(status='success', data=dict(asset_id=node['_id']))
コード例 #21
0
ファイル: __init__.py プロジェクト: aditiapratama/pillar-web
def project_update_nodes_list(node, project_id=None, list_name='latest'):
    """Update the project node with the latest edited or favorited node.
    The list value can be 'latest' or 'featured' and it will determined where
    the node reference will be placed in.
    """
    if node.properties.status and node.properties.status == 'published':
        if not project_id and 'current_project_id' in session:
            project_id = session['current_project_id']
        elif not project_id:
            return None
        project_id = node.project
        if type(project_id) is not unicode:
            project_id = node.project._id
        api = system_util.pillar_api()
        project = Project.find(project_id, api=api)
        if list_name == 'latest':
            nodes_list = project.nodes_latest
        elif list_name == 'blog':
            nodes_list = project.nodes_blog
        else:
            nodes_list = project.nodes_featured

        if not nodes_list:
            node_list_name = 'nodes_' + list_name
            project[node_list_name] = []
            nodes_list = project[node_list_name]
        elif len(nodes_list) > 5:
            nodes_list.pop(0)

        if node._id in nodes_list:
            # Pop to put this back on top of the list
            nodes_list.remove(node._id)
            if list_name == 'featured':
                # We treat the action as a toggle and do not att the item back
                project.update(api=api)
                return "removed"

        nodes_list.append(node._id)
        project.update(api=api)
        return "added"
コード例 #22
0
def project_update_nodes_list(node, project_id=None, list_name='latest'):
    """Update the project node with the latest edited or favorited node.
    The list value can be 'latest' or 'featured' and it will determined where
    the node reference will be placed in.
    """
    if node.properties.status and node.properties.status == 'published':
        if not project_id and 'current_project_id' in session:
            project_id = session['current_project_id']
        elif not project_id:
            return None
        project_id = node.project
        if type(project_id) is not str:
            project_id = node.project._id
        api = system_util.pillar_api()
        project = Project.find(project_id, api=api)
        if list_name == 'latest':
            nodes_list = project.nodes_latest
        elif list_name == 'blog':
            nodes_list = project.nodes_blog
        else:
            nodes_list = project.nodes_featured

        if not nodes_list:
            node_list_name = 'nodes_' + list_name
            project[node_list_name] = []
            nodes_list = project[node_list_name]
        elif len(nodes_list) > 15:
            nodes_list.pop(0)

        if node._id in nodes_list:
            # Pop to put this back on top of the list
            nodes_list.remove(node._id)
            if list_name == 'featured':
                # We treat the action as a toggle and do not att the item back
                project.update(api=api)
                return "removed"

        nodes_list.append(node._id)
        project.update(api=api)
        return "added"
コード例 #23
0
def toggle_node_project_header():
    """Sets this node as the project header, or removes it if already there.
    """

    api = system_util.pillar_api()
    node_id = request.form['node_id']

    try:
        node = Node.find(node_id, {'projection': {'project': 1}}, api=api)
    except ResourceNotFound:
        log.info(
            'User %s trying to toggle non-existing node %s as project header',
            current_user.objectid, node_id)
        return jsonify(_status='ERROR', message='Node not found'), 404

    try:
        project = Project.find(node.project, api=api)
    except ResourceNotFound:
        log.info(
            'User %s trying to toggle node %s as project header, but project %s not found',
            current_user.objectid, node_id, node.project)
        return jsonify(_status='ERROR', message='Project not found'), 404

    # Toggle header node
    if project.header_node == node_id:
        log.debug('Un-setting header node of project %s', node.project)
        project.header_node = None
        action = 'unset'
    else:
        log.debug('Setting node %s as header of project %s', node_id,
                  node.project)
        project.header_node = node_id
        action = 'set'

    # Save the project
    project.update(api=api)

    return jsonify({'_status': 'OK', 'action': action})
コード例 #24
0
def edit(node_id):
    """Generic node editing form
    """
    def set_properties(dyn_schema,
                       form_schema,
                       node_properties,
                       form,
                       prefix="",
                       set_data=True):
        """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.
        """
        for prop in dyn_schema:
            schema_prop = dyn_schema[prop]
            form_prop = form_schema[prop]
            prop_name = "{0}{1}".format(prefix, prop)

            if schema_prop['type'] == 'dict':
                set_properties(schema_prop['schema'], form_prop['schema'],
                               node_properties[prop_name], form,
                               "{0}__".format(prop_name))
                continue

            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, 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

            # Assign data to the field
            if set_data:
                if prop_name == 'attachments':
                    for attachment_collection in db_prop_value:
                        for a in attachment_collection['files']:
                            attachment_form = ProceduralFileSelectForm()
                            attachment_form.file = a['file']
                            attachment_form.slug = a['slug']
                            attachment_form.size = 'm'
                            form[prop_name].append_entry(attachment_form)

                elif prop_name == 'files':
                    schema = 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) > 0:
                        while len(field_list):
                            field_list.pop_entry()

                    for file_data in db_prop_value:
                        file_form_class = build_file_select_form(schema)
                        subform = file_form_class()
                        for key, value in file_data.iteritems():
                            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
            else:
                # Default population of multiple file form list (only if
                # we are getting the form)
                if request.method == 'POST':
                    continue
                if prop_name == 'attachments':
                    if not db_prop_value:
                        attachment_form = ProceduralFileSelectForm()
                        attachment_form.file = 'file'
                        attachment_form.slug = ''
                        attachment_form.size = ''
                        form[prop_name].append_entry(attachment_form)

    api = system_util.pillar_api()
    node = Node.find(node_id, api=api)
    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, list_name='blog')
            else:
                project_update_nodes_list(node)
            # Emergency hardcore cache flush
            # cache.clear()
            return redirect(
                url_for('nodes.view',
                        node_id=node_id,
                        embed=1,
                        _external=True,
                        _scheme=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)

    # 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'):
        if request.args.get('embed') == '1':
            # Define the prefix for the embedded template
            embed_string = '_embed'

    template = '{0}/edit{1}.html'.format(node_type['name'], embed_string)

    # We should more simply check if the template file actually exsists on
    # the filesystem level
    try:
        return render_template(template,
                               node=node,
                               parent=parent,
                               form=form,
                               errors=form.errors,
                               error=error,
                               api=api)
    except TemplateNotFound:
        template = 'nodes/edit{1}.html'.format(node_type['name'], embed_string)
        return render_template(template,
                               node=node,
                               parent=parent,
                               form=form,
                               errors=form.errors,
                               error=error,
                               api=api)
コード例 #25
0
ファイル: __init__.py プロジェクト: aditiapratama/pillar-web
def edit(node_id):
    """Generic node editing form
    """

    def set_properties(dyn_schema, form_schema, node_properties, form,
                       prefix="",
                       set_data=True):
        """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.
        """
        for prop in dyn_schema:
            schema_prop = dyn_schema[prop]
            form_prop = form_schema[prop]
            prop_name = "{0}{1}".format(prefix, prop)

            if schema_prop['type'] == 'dict':
                set_properties(
                    schema_prop['schema'],
                    form_prop['schema'],
                    node_properties[prop_name],
                    form,
                    "{0}__".format(prop_name))
                continue

            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,
                                                  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

            # Assign data to the field
            if set_data:
                if prop_name == 'attachments':
                    for attachment_collection in db_prop_value:
                        for a in attachment_collection['files']:
                            attachment_form = ProceduralFileSelectForm()
                            attachment_form.file = a['file']
                            attachment_form.slug = a['slug']
                            attachment_form.size = 'm'
                            form[prop_name].append_entry(attachment_form)

                elif prop_name == 'files':
                    schema = 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) > 0:
                        while len(field_list):
                            field_list.pop_entry()

                    for file_data in db_prop_value:
                        file_form_class = build_file_select_form(schema)
                        subform = file_form_class()
                        for key, value in file_data.iteritems():
                            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
            else:
                # Default population of multiple file form list (only if
                # we are getting the form)
                if request.method == 'POST':
                    continue
                if prop_name == 'attachments':
                    if not db_prop_value:
                        attachment_form = ProceduralFileSelectForm()
                        attachment_form.file = 'file'
                        attachment_form.slug = ''
                        attachment_form.size = ''
                        form[prop_name].append_entry(attachment_form)

    api = system_util.pillar_api()
    node = Node.find(node_id, api=api)
    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, list_name='blog')
            else:
                project_update_nodes_list(node)
            # Emergency hardcore cache flush
            # cache.clear()
            return redirect(url_for('nodes.view', node_id=node_id, embed=1,
                                    _external=True,
                                    _scheme=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)

    # 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'):
        if request.args.get('embed') == '1':
            # Define the prefix for the embedded template
            embed_string = '_embed'

    template = '{0}/edit{1}.html'.format(node_type['name'], embed_string)

    # We should more simply check if the template file actually exsists on
    # the filesystem level
    try:
        return render_template(
            template,
            node=node,
            parent=parent,
            form=form,
            errors=form.errors,
            error=error,
            api=api)
    except TemplateNotFound:
        template = 'nodes/edit{1}.html'.format(node_type['name'], embed_string)
        return render_template(
            template,
            node=node,
            parent=parent,
            form=form,
            errors=form.errors,
            error=error,
            api=api)
コード例 #26
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,
        )
コード例 #27
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)
コード例 #28
0
ファイル: posts.py プロジェクト: aditiapratama/pillar-web
def posts_view(project_id, url=None):
    """View individual blogpost"""
    api = system_util.pillar_api()
    # Fetch project (for backgroud images and links generation)
    project = Project.find(project_id, api=api)
    attach_project_pictures(project, api)
    try:
        blog = Node.find_one(
            {
                'where': {
                    'node_type': 'blog',
                    'project': project_id
                },
            }, api=api)
    except ResourceNotFound:
        abort(404)
    if url:
        try:
            post = Node.find_one(
                {
                    'where':
                    '{"parent": "%s", "properties.url": "%s"}' %
                    (blog._id, url),
                    'embedded':
                    '{"node_type": 1, "user": 1}',
                },
                api=api)
            if post.picture:
                post.picture = get_file(post.picture, api=api)
        except ResourceNotFound:
            return abort(404)

        # 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 current_user.is_authenticated():
                if not post.has_method('PUT'):
                    abort(403)
            else:
                abort(403)

        return render_template('nodes/custom/post/view.html',
                               blog=blog,
                               node=post,
                               project=project,
                               title='blog',
                               api=api)
    else:
        node_type_post = project.get_node_type('post')
        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)

        return render_template('nodes/custom/blog/index.html',
                               node_type_post=node_type_post,
                               posts=posts._items,
                               project=project,
                               title='blog',
                               api=api)
コード例 #29
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)
コード例 #30
0
def homepage():
    """Homepage"""

    if not current_user.is_authenticated():
        return render_template('join.html', title="join")

    # Get latest blog posts
    api = system_util.pillar_api()
    latest_posts = Node.all(
        {
            'projection': {
                'name': 1,
                'project': 1,
                'user': 1,
                'node_type': 1,
                'picture': 1,
                'properties.status': 1,
                'properties.url': 1
            },
            'where': {
                'node_type': 'post',
                'properties.status': 'published'
            },
            'embedded': {
                'user': 1,
                'project': 1
            },
            'sort': '-_created',
            'max_results': '3'
        },
        api=api)

    # Append picture Files to last_posts
    for post in latest_posts._items:
        if post.picture:
            post.picture = get_file(post.picture, api=api)

    # Get latest assets added to any project
    latest_assets = Node.latest('assets', api=api)

    # Append picture Files to latest_assets
    for asset in latest_assets._items:
        if asset.picture:
            asset.picture = get_file(asset.picture, api=api)

    # Get latest comments to any node
    latest_comments = Node.latest('comments', api=api)

    # Parse results for replies
    for comment in latest_comments._items:
        if comment.properties.is_reply:
            comment.parent = Node.find(comment.parent.parent, api=api)
        else:
            comment.parent = comment.parent

    main_project = Project.find(app.config['MAIN_PROJECT_ID'], api=api)
    main_project.picture_square = get_file(main_project.picture_square,
                                           api=api)
    main_project.picture_header = get_file(main_project.picture_header,
                                           api=api)

    return render_template('homepage.html',
                           main_project=main_project,
                           latest_posts=latest_posts._items,
                           latest_assets=latest_assets._items,
                           latest_comments=latest_comments._items,
                           api=api)