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())
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
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
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))
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())
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)
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())
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'])
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)
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()
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')
def training(): projects = get_projects('training') return render_template( 'projects/index_collection.html', title='training', projects=projects._items, api=system_util.pillar_api())
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)
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'])
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
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))
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
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']))))
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)
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)
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']))))
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)
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
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)
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'))
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())
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
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)
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))
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)
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
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
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
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)
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)
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)
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"))
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
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
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'])))
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))
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
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')
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
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')))
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)
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'])))
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
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)
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)