Пример #1
0
def index():
    api = system_util.pillar_api()
    projects_user = Project.all({
        'where': {'user': current_user.objectid},
        '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']:
        attach_project_pictures(project, api)

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

    return render_template(
        'projects/index_dashboard.html',
        gravatar=gravatar(current_user.email, size=128),
        title='dashboard',
        projects_user=projects_user['_items'],
        projects_shared=projects_shared['_items'],
        api=system_util.pillar_api())
Пример #2
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
Пример #3
0
    def __init__(self, name):
        self.api = system_util.pillar_api()
        # Check if organization exists
        user = Organization.find_first({
            'where': '{"url" : "%s"}' % (name),
        },
                                       api=self.api)

        if user:
            self.is_organization = True
            self.name = user.name
            self.url = user.url
            self.description = user.description
            self.gravatar = gravatar(user.email)
        else:
            # Check if user exists
            user = User.find_first({
                'where': '{"username" : "%s"}' % (name),
            },
                                   api=self.api)
            if user:
                self.is_organization = False
                self.name = user.first_name
                self.url = user.username
            else:
                return abort(404)
        self._id = user._id
Пример #4
0
def groups_create():
    # Use current_project_id from the session instead of the cookie
    name = request.form['name']
    project_id = request.form['project_id']
    parent_id = request.form.get('parent_id')

    api = system_util.pillar_api()
    # We will create the Node object later on, after creating the file object
    node_asset_props = dict(
        name=name,
        user=current_user.objectid,
        node_type='group',
        project=project_id,
        properties=dict(
            status='published'))
    # Add parent_id only if provided (we do not provide it when creating groups
    # at the Project root)
    if parent_id:
        node_asset_props['parent'] = parent_id
    print parent_id

    node_asset = Node(node_asset_props)
    node_asset.create(api=api)
    return jsonify(status='success',
        data=dict(name=name, asset_id=node_asset._id))
Пример #5
0
def task_add():
    api = system_util.pillar_api()
    shot_id = request.form['shot_id']
    task_name = request.form['task_name']

    node_type_list = NodeType.all({
        'where': "name=='task'",
        }, api=api)
    node_type = node_type_list['_items'][0]

    node_type_id = node_type._id
    import datetime

    RFC1123_DATE_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
    node = Node()
    prop = {}
    prop['node_type'] = node_type_id
    prop['name'] = task_name
    prop['description'] = ''
    prop['user'] = current_user.objectid
    prop['parent'] = shot_id
    prop['properties'] = {
        'status': 'todo',
        'owners': {
            'users': [],
            'groups': []},
        'time': {
            'duration': 10,
            'start': datetime.datetime.strftime(datetime.datetime.now(), '%a, %d %b %Y %H:%M:%S GMT')}
        }
    post = node.post(prop, api=api)
    return jsonify(node.to_dict())
Пример #6
0
def comments_create():
    content = request.form['content']
    parent_id = request.form.get('parent_id')
    api = system_util.pillar_api()
    parent_node = Node.find(parent_id, api=api)

    node_asset_props = dict(
        project=parent_node.project,
        name='Comment',
        user=current_user.objectid,
        node_type='comment',
        properties=dict(
            content=content,
            status='published',
            confidence=0,
            rating_positive=0,
            rating_negative=0))

    if parent_id:
        node_asset_props['parent'] = parent_id

    # Get the parent node and check if it's a comment. In which case we flag
    # the current comment as a reply.
    parent_node = Node.find(parent_id, api=api)
    if parent_node.node_type == 'comment':
        node_asset_props['properties']['is_reply'] = True

    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(
        asset_id=node_asset._id,
        content=node_asset.properties.content)
Пример #7
0
def open_projects():
    projects = get_projects('film')
    return render_template(
        'projects/index_collection.html',
        title='open-projects',
        projects=projects._items,
        api=system_util.pillar_api())
Пример #8
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'] = gravatar(user['email'])

    if request.method == 'POST':
        user_id = request.form['user_id']
        action = request.form['action']
        if action == 'add':
            user = project.add_user(user_id, api=api)
        elif action == 'remove':
            user = project.remove_user(user_id, api=api)
        # Add gravatar to user
        user['avatar'] = gravatar(user['email'])
        return jsonify(user)

    attach_project_pictures(project, api)

    return render_template('projects/sharing.html',
                           api=api,
                           title="sharing",
                           project=project,
                           users=users['_items'])
Пример #9
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)
    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)
Пример #10
0
def feeds_blogs():
    """Global feed generator for latest blogposts across all projects"""
    feed = AtomFeed('Blender Cloud - Latest updates',
                    feed_url=request.url, url=request.url_root)
    # Get latest blog posts
    api = system_util.pillar_api()
    latest_posts = Node.all({
        'where': {'node_type': 'post', 'properties.status': 'published'},
        'embedded': {'user': 1},
        'sort': '-_created',
        'max_results': '15'
        }, api=api)

    # Populate the feed
    for post in latest_posts._items:
        author = post.user.fullname
        updated = post._updated if post._updated else post._created
        url = url_for_node(node=post)
        content = post.properties.content[:500]
        content = u'<p>{0}... <a href="{1}">Read more</a></p>'.format(content, url)
        feed.add(post.name, unicode(content),
                 content_type='html',
                 author=author,
                 url=url,
                 updated=updated,
                 published=post._created)
    return feed.get_response()
Пример #11
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)
    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)
Пример #12
0
def settings_emails():
    """Main email settings.
    """
    if current_user.has_role('protected'):
        return abort(404)  # TODO: make this 403, handle template properly
    api = system_util.pillar_api()
    user = User.find(current_user.objectid, api=api)

    # Force creation of settings for the user (safely remove this code once
    # implemented on account creation level, and after adding settings to all
    # existing users)
    if not user.settings:
        user.settings = dict(email_communications=1)
        user.update(api=api)

    if user.settings.email_communications is None:
        user.settings.email_communications = 1
        user.update(api=api)

    # Generate form
    form = UserSettingsEmailsForm(
        email_communications=user.settings.email_communications)

    if form.validate_on_submit():
        try:
            user.settings.email_communications = form.email_communications.data
            user.update(api=api)
            flash("Profile updated", 'success')
        except sdk_exceptions.ResourceInvalid as e:
            message = json.loads(e.content)
            flash(message)

    return render_template('users/settings/emails.html', form=form, title='emails')
Пример #13
0
def training():
    projects = get_projects('training')
    return render_template(
        'projects/index_collection.html',
        title='training',
        projects=projects._items,
        api=system_util.pillar_api())
Пример #14
0
def comments_create():
    content = request.form['content']
    parent_id = request.form.get('parent_id')
    api = system_util.pillar_api()
    parent_node = Node.find(parent_id, api=api)

    node_asset_props = dict(project=parent_node.project,
                            name='Comment',
                            user=current_user.objectid,
                            node_type='comment',
                            properties=dict(content=content,
                                            status='published',
                                            confidence=0,
                                            rating_positive=0,
                                            rating_negative=0))

    if parent_id:
        node_asset_props['parent'] = parent_id

    # Get the parent node and check if it's a comment. In which case we flag
    # the current comment as a reply.
    parent_node = Node.find(parent_id, api=api)
    if parent_node.node_type == 'comment':
        node_asset_props['properties']['is_reply'] = True

    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(asset_id=node_asset._id,
                   content=node_asset.properties.content)
Пример #15
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'] = gravatar(user['email'])

    if request.method == 'POST':
        user_id = request.form['user_id']
        action = request.form['action']
        if action == 'add':
            user = project.add_user(user_id, api=api)
        elif action == 'remove':
            user = project.remove_user(user_id, api=api)
        # Add gravatar to user
        user['avatar'] = gravatar(user['email'])
        return jsonify(user)

    attach_project_pictures(project, api)

    return render_template('projects/sharing.html',
                           api=api,
                           title="sharing",
                           project=project,
                           users=users['_items'])
Пример #16
0
def load_user(userid):
    from application import system_util

    api = system_util.pillar_api(token=userid)

    try:
        user = User.me(api=api)
    except sdk_exceptions.ForbiddenAccess:
        return None

    if not user:
        return None

    login_user = UserClass(userid)
    login_user.email = user.email
    login_user.objectid = user._id
    login_user.username = user.username
    login_user.gravatar = gravatar(user.email)
    login_user.roles = user.roles
    login_user.groups = user.groups
    try:
        login_user.full_name = user.full_name
    except KeyError:
        pass

    return login_user
Пример #17
0
def add_featured_node():
    """Feature a node in a project. This method belongs here, because it affects
    the project node itself, not the asset.
    """
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    action = project_update_nodes_list(node, list_name='featured')
    return jsonify(status='success', data=dict(action=action))
Пример #18
0
def add_featured_node():
    """Feature a node in a project. This method belongs here, because it affects
    the project node itself, not the asset.
    """
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    action = project_update_nodes_list(node, list_name='featured')
    return jsonify(status='success', data=dict(action=action))
Пример #19
0
def type_names():
    api = system_util.pillar_api()

    types = NodeType.all(api=api)["_items"]
    type_names = []
    for names in types:
        type_names.append(str(names['name']))
    return type_names
Пример #20
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']))))
Пример #21
0
def tasks():
    """User-assigned tasks"""
    # Pagination index
    page = request.args.get('page', 1)
    max_results = 50

    api = system_util.pillar_api()
    node_type_list = NodeType.all({'where': "name=='task'"}, api=api)

    if len(node_type_list['_items']) == 0:
        return "Empty NodeType list", 200

    node_type = node_type_list._items[0]

    tasks = Node.all({
        'where': '{"node_type" : "%s", "properties.owners.users": {"$in": ["%s"]}}'\
                % (node_type['_id'], current_user.objectid),
        'max_results': max_results,
        'page': page,
        'embedded': '{"parent":1, "picture":1}',
        'sort' : "order"}, api=api)

    # Build the pagination object
    # pagination = Pagination(int(page), max_results, tasks._meta.total)

    tasks_datatable = []
    for task in tasks._items:
        cut_in = 0
        cut_out = 0
        if task.parent.properties.cut_in:
            cut_in = task.parent.properties.cut_in
        if task.parent.properties.cut_out:
            cut_out = task.parent.properties.cut_out
        data = {
            'DT_RowId': "row_{0}".format(task._id),
            '_id': task._id,
            'order': task.order,
            'picture': None,
            'name': task.name,
            'timing': {
                'cut_in': task.parent.properties.cut_in,
                'cut_out': task.parent.properties.cut_out,
            },
            'parent': task.parent.to_dict(),
            'description': task.description,
            'url_view': url_for('nodes.view', node_id=task._id),
            'url_edit': url_for('nodes.edit', node_id=task._id, embed=1),
            'status': task.properties.status,
            }

        tasks_datatable.append(data)

    return render_template(
        'users/tasks.html',
        title="task",
        tasks_data=json.dumps(tasks_datatable),
        node_type=node_type)
Пример #22
0
def project_blog(project_url, url=None):
    """View project blog"""
    api = system_util.pillar_api()
    try:
        project = Project.find_one({
            'where': '{"url" : "%s"}' % (project_url)}, api=api)
        return posts_view(project._id, url=url)
    except ResourceNotFound:
        return abort(404)
Пример #23
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']))))
Пример #24
0
def project_blog(project_url, url=None):
    """View project blog"""
    api = system_util.pillar_api()
    try:
        project = Project.find_one({'where': '{"url" : "%s"}' % (project_url)},
                                   api=api)
        return posts_view(project._id, url=url)
    except ResourceNotFound:
        return abort(404)
Пример #25
0
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
Пример #26
0
def index():
    """Display the node types
    """
    api = system_util.pillar_api()
    node_types = NodeType.all(api=api)
    node_types = node_types['_items']
    return render_template('node_types/index.html',
                           title='node_types',
                           node_types=node_types)
Пример #27
0
def delete_node():
    """Delete a node"""
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    if not node.has_method('DELETE'):
        return abort(403)

    node.delete(api=api)

    return jsonify(status='success', data=dict(message='Node deleted'))
Пример #28
0
def delete_node():
    """Delete a node"""
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    if not node.has_method('DELETE'):
        return abort(403)

    node.delete(api=api)

    return jsonify(status='success', data=dict(message='Node deleted'))
Пример #29
0
def index():
    api = system_util.pillar_api()
    projects_user = Project.all(
        {
            'where': {
                'user': current_user.objectid
            },
            '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']:
        attach_project_pictures(project, api)

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

    return render_template('projects/index_dashboard.html',
                           gravatar=gravatar(current_user.email, size=128),
                           title='dashboard',
                           projects_user=projects_user['_items'],
                           projects_shared=projects_shared['_items'],
                           api=system_util.pillar_api())
Пример #30
0
def process_and_create_file(project_id, name, length, mime_type):
    """Base function that handles the hashing of a file name and the creation of
    a record in the files collection. This function is use in the nodes module
    on assets_create.

    :type project_id: string
    :param bucket_name: The project id, uset to fetch the gcs bucket.

    :type name: string
    :param subdir: The the filename (currently used to build the path).

    :type length: int
    :param subdir: Filesize in bit (in case we start the upload from the js
        interface, we get the size for free, otherwise at the moment we
        hardcode it to 0)

    :type mime_type: string
    :param subdir: MIME type used do display/preview the file accordingly

    """

    root, ext = os.path.splitext(name)
    # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'],
                                str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.move(src_file_path, dst_file_path)

    api = system_util.pillar_api()
    file_item = File({
        'name': link[3:],
        'filename': name,
        'user': current_user.objectid,
        'backend': 'gcs',
        'md5': '',
        'content_type': mime_type,
        'length': length,
        'project': project_id
    })
    file_item.create(api=api)
    return file_item
Пример #31
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)
Пример #32
0
def item_delete(item_id):
    """We run this when updating a preview picture (after succesfully uploading
    a new one).
    """
    api = system_util.pillar_api()
    try:
        file_item = File.find(item_id, api=api)
        file_item.delete(api=api)
        message = 'File deleted'
    except ResourceNotFound:
        message = 'File not found'
    return jsonify(status='success', data=dict(message=message))
Пример #33
0
def user_roles_update(user_id):
    api = system_util.pillar_api()
    group_subscriber = Group.find_one({'where': "name=='subscriber'"}, api=api)

    external_subscriptions_server = app.config['EXTERNAL_SUBSCRIPTIONS_MANAGEMENT_SERVER']

    # Fetch the user once outside the loop, because we only need to get the
    # subscription status once.
    user = User.me(api=api)

    r = requests.get(external_subscriptions_server, params={'blenderid': user.email})
    if r.status_code != 200:
        log.warning("Error communicating with %s, code=%i, unable to check "
                    "subscription status of user %s",
                    external_subscriptions_server, r.status_code, user_id)
        return
    store_user = r.json()

    max_retry = 5
    for retry_count in range(max_retry):
        # Update the user's role & groups for their subscription status.
        roles = set(user.roles or [])
        groups = set(user.groups or [])

        if store_user['cloud_access'] == 1:
            roles.add(u'subscriber')
            groups.add(group_subscriber._id)

        elif u'admin' not in roles:
            roles.discard(u'subscriber')
            groups.discard(group_subscriber._id)

        # Only send an API request when the user has actually changed
        if set(user.roles or []) == roles and set(user.groups or []) == groups:
            break

        user.roles = list(roles)
        user.groups = list(groups)

        try:
            user.update(api=api)
        except sdk_exceptions.PreconditionFailed:
            log.warning('User etag changed while updating roles, retrying.')
        else:
            # Successful update, so we can stop the loop.
            break

        # Fetch the user for the next iteration.
        if retry_count < max_retry - 1:
            user = User.me(api=api)
    else:
        log.warning('Tried %i times to update user %s, and failed each time. Giving up.',
                    max_retry, user_id)
Пример #34
0
def item_delete(item_id):
    """We run this when updating a preview picture (after succesfully uploading
    a new one).
    """
    api = system_util.pillar_api()
    try:
        file_item = File.find(item_id, api=api)
        file_item.delete(api=api)
        message = 'File deleted'
    except ResourceNotFound:
        message = 'File not found'
    return jsonify(status='success', data=dict(message=message))
Пример #35
0
def process_and_create_file(project_id, name, length, mime_type):
    """Base function that handles the hashing of a file name and the creation of
    a record in the files collection. This function is use in the nodes module
    on assets_create.

    :type project_id: string
    :param bucket_name: The project id, uset to fetch the gcs bucket.

    :type name: string
    :param subdir: The the filename (currently used to build the path).

    :type length: int
    :param subdir: Filesize in bit (in case we start the upload from the js
        interface, we get the size for free, otherwise at the moment we
        hardcode it to 0)

    :type mime_type: string
    :param subdir: MIME type used do display/preview the file accordingly

    """

    root, ext = os.path.splitext(name)
     # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'], str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.move(src_file_path, dst_file_path)

    api = system_util.pillar_api()
    file_item = File({
        'name': link[3:],
        'filename': name,
        'user': current_user.objectid,
        'backend': 'gcs',
        'md5': '',
        'content_type': mime_type,
        'length': length,
        'project': project_id
        })
    file_item.create(api=api)
    return file_item
Пример #36
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
Пример #37
0
    def validate(self):
        rv = Form.validate(self)
        if not rv:
            return False

        api = system_util.pillar_api()
        project = Project.find(self.project_id.data, api=api)
        if project.url != self.url.data:
            project_url = Project.find_one({'where': '{"url": "%s"}' % (self.url.data)},
                api=api)
            if project_url:
                self.url.errors.append('Sorry, project url already exists!')
                return False
        return True
Пример #38
0
    def validate(self):
        rv = Form.validate(self)
        if not rv:
            return False

        api = system_util.pillar_api()
        project = Project.find(self.project_id.data, api=api)
        if project.url != self.url.data:
            project_url = Project.find_one(
                {'where': '{"url": "%s"}' % (self.url.data)}, api=api)
            if project_url:
                self.url.errors.append('Sorry, project url already exists!')
                return False
        return True
Пример #39
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)

    attach_project_pictures(project, api)

    return render_template('projects/edit_node_types.html',
                           api=api,
                           title="edit_node_types",
                           project=project)
Пример #40
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)

    attach_project_pictures(project, api)

    return render_template('projects/edit_node_types.html',
                           api=api,
                           title="edit_node_types",
                           project=project)
Пример #41
0
def action_read_toggle(notification_id):
    api = system_util.pillar_api()
    notification = Notification.find(notification_id, api=api)
    if notification.user == current_user.objectid:
        notification.is_read = not notification.is_read
        notification.update(api=api)
        return jsonify(
            status='success',
            data=dict(
                message="Notification {0} is_read {1}".format(
                    notification_id,
                    notification.is_read),
                is_read=notification.is_read))
    else:
        return abort(403)
Пример #42
0
def action_read_all():
    """Mark all notifications as read"""
    api = system_util.pillar_api()
    notifications = Notification.all({
        'where': '{"user": "******"}' % (current_user.objectid),
        'sort': '-_created'}, api=api)

    for notification in notifications._items:
        notification = Notification.find(notification._id, api=api)
        notification.is_read = True
        notification.update(api=api)

    return jsonify(status='success',
        data=dict(
            message="All notifications mark as read"))
Пример #43
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
Пример #44
0
def get_file(file_id, api=None):
    # TODO: remove this function and just use the Pillar SDK directly.
    if file_id is None:
        return None

    if api is None:
        api = system_util.pillar_api()

    try:
        return File.find(file_id, api=api)
    except ResourceNotFound:
        f = sys.exc_info()[2].tb_frame.f_back
        tb = traceback.format_stack(f=f, limit=2)
        log.warning('File %s not found, but requested from %s\n%s', file_id,
                    request.url, ''.join(tb))
        return None
Пример #45
0
def create():
    """Create a new project. This is a multi step operation that involves:
    - initialize basic node types
    - initialize basic permissions
    - create and connect storage space
    """
    api = system_util.pillar_api()
    project_properties = dict(name='My project',
                              user=current_user.objectid,
                              category='assets',
                              status='pending')
    project = Project(project_properties)
    project.create(api=api)

    return redirect(
        url_for('projects.edit', project_url="p-{}".format(project['_id'])))
Пример #46
0
def create():
    """Endpoint hit by the automatic upload of a picture, currently used in the
    edit node form. Some sanity checks are already done in the fronted, but
    additional checks can be implemented here.
    """
    name = request.form['name']
    size = request.form['size']
    content_type = request.form['type']
    field_name = request.form['field_name']
    project_id = request.form['project_id']
    file_item = process_and_create_file(project_id, name, size, content_type)
    api = system_util.pillar_api()
    f = File.find(file_item['_id'], api=api)
    thumbnail_link = f.thumbnail('s', api=api)

    return jsonify(status='success', data=dict(id=file_item._id,
        link=thumbnail_link, field_name=field_name))
Пример #47
0
    def validate(self):
        rv = Form.validate(self)
        if not rv:
            return False

        api = system_util.pillar_api()
        user = User.find(current_user.objectid, api=api)
        if user.username != self.username.data:
            username = User.find_first({'where': '{"username": "******"}' % (self.username.data)},
                api=api)

            if username:
                self.username.errors.append('Sorry, username already exists!')
                return False

        self.user = user
        return True
Пример #48
0
def settings_billing():
    """View the subscription status of a user
    """
    if current_user.has_role('protected'):
        return abort(404)  # TODO: make this 403, handle template properly
    api = system_util.pillar_api()
    user = User.find(current_user.objectid, api=api)
    groups = []
    if user.groups:
        for group_id in user.groups:
            group = Group.find(group_id, api=api)
            groups.append(group.name)
    external_subscriptions_server = app.config['EXTERNAL_SUBSCRIPTIONS_MANAGEMENT_SERVER']
    r = requests.get(external_subscriptions_server, params={'blenderid': user.email})
    store_user = r.json()
    return render_template('users/settings/billing.html',
        store_user=store_user, groups=groups, title='billing')
Пример #49
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
Пример #50
0
def action_subscription_toggle(notification_id):
    """Given a notification id, get the ActivitySubscription and update it by
    toggling the notifications status for the web key.
    """
    api = system_util.pillar_api()
    # Get the notification
    notification = notification_parse(
        Notification.find(notification_id, {'parse':'1'}, api=api))
    # Get the subscription and modify it
    subscription = ActivitySubscription.find(
        notification['subscription'], api=api)
    subscription.notifications['web'] = not subscription.notifications['web']
    subscription.update(api=api)
    return jsonify(status='success',
        data=dict(
            message="You have been {}subscribed".format(
                '' if subscription.notifications['web'] else 'un')))
Пример #51
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)
Пример #52
0
def create():
    """Create a new project. This is a multi step operation that involves:
    - initialize basic node types
    - initialize basic permissions
    - create and connect storage space
    """
    api = system_util.pillar_api()
    project_properties = dict(
        name='My project',
        user=current_user.objectid,
        category='assets',
        status='pending'
    )
    project = Project(project_properties)
    project.create(api=api)

    return redirect(url_for('projects.edit',
                            project_url="p-{}".format(project['_id'])))
Пример #53
0
    def validate(self):
        rv = Form.validate(self)
        if not rv:
            return False

        api = system_util.pillar_api()
        user = User.find(current_user.objectid, api=api)
        if user.username != self.username.data:
            username = User.find_first(
                {'where': '{"username": "******"}' % (self.username.data)},
                api=api)

            if username:
                self.username.errors.append('Sorry, username already exists!')
                return False

        self.user = user
        return True
Пример #54
0
def assets_create():
    project_id = request.form['project_id']
    name = request.form['name']
    parent_id = request.form.get('parent_id')
    # Detect filetype by extension (improve by detectin real file type)
    root, ext = os.path.splitext(name)
    if ext in ['.jpg', '.jpeg', '.png', '.tif', '.tiff']:
        filetype = 'image'
    elif ext in ['.blend', '.txt', '.zip']:
        filetype = 'file'
    elif ext in ['.mov', '.avi', '.mp4', '.m4v']:
        filetype = 'video'
    else:
        filetype = 'file'

    api = system_util.pillar_api()
    # We will create the Node object later on, after creating the file object
    node_asset_props = dict(
        name=name,
        project=project_id,
        user=current_user.objectid,
        node_type='asset',
        properties=dict(
            content_type=filetype,
            status='processing'))

    if filetype == 'file':
        mime_type_base = 'application'
    else:
        mime_type_base = filetype
    mime_type = "{0}/{1}".format(mime_type_base, ext.replace(".", ""))
    node_file = process_and_create_file(project_id, name, 0, mime_type)

    node_asset_props['properties']['file'] = node_file._id
    if parent_id:
        node_asset_props['parent'] = parent_id
    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(
        #link=link,
        name=name,
        filetype=filetype,
        asset_id=node_asset._id)
Пример #55
0
def toggle_node_public():
    """Give a node GET permissions for the world. Later on this can turn into
    a more powerful permission management function.
    """
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    if node.has_method('PUT'):
        if node.permissions and 'world' in node.permissions.to_dict():
            node.permissions = {}
            message = "Node is not public anymore."
        else:
            node.permissions = dict(world=['GET'])
            message = "Node is now public!"
        node.update(api=api)
        # Delete cached parent template fragment
        delete_redis_cache_template('group_view', node.parent)
        return jsonify(status='success', data=dict(message=message))
    else:
        return abort(403)