def get_nodes(node_link=None): user_id = to_object_id(g.user._id) # if node_link is a base node if node_link in node_collection.name_to_class: return JSONEncoder().encode({ 'data': node_collection.name_to_class[node_link].get_default().to_dict(), 'resources_dict': resource_manager.resources_dict, 'status': 'success' }) else: try: node_id = to_object_id(node_link) except Exception: return make_fail_response('Invalid ID'), 404 node = node_collection_manager.get_db_node(node_id, user_id) if node: return JSONEncoder().encode({ 'data': node, 'resources_dict': resource_manager.resources_dict, 'status': 'success' }) else: return make_fail_response( 'Node `{}` was not found'.format(node_link)), 404
def update_graph(graph_id): app.logger.debug(request.data) data = json.loads(request.data) if not data: return make_fail_response('Expected json data'), 400 graph_dict = graph_collection_manager.get_db_graph(graph_id, g.user._id) if not graph_dict: return make_fail_response('Graph was not found'), 404 if graph_dict['_readonly']: return make_fail_response('Permission denied'), 403 if graph_dict['graph_running_status'] != GraphRunningStatus.CREATED: return make_fail_response('Cannot save graph with status `{}`'.format(graph_dict['graph_running_status'])) update_dict_recursively(graph_dict, data) graph = Graph.from_dict(graph_dict) graph.save() return JSONEncoder().encode({ 'status': 'success', 'message': 'Successfully updated', 'graph': graph.to_dict(), })
def get_nodes(collection, node_link=None): user_id = to_object_id(g.user._id) # if node_link is a base node if node_link in executor_manager.kind_to_executor_class and collection == Collections.TEMPLATES: kind = node_link node = executor_manager.kind_to_executor_class[kind].get_default_node( is_workflow=kind in workflow_manager.kind_to_workflow_dict) if isinstance(node, tuple): data = node[0].to_dict() tour_steps = node[1] else: data = node.to_dict() tour_steps = [] data['kind'] = kind return JSONEncoder().encode({ 'node': data, 'tour_steps': tour_steps, 'plugins_dict': PLUGINS_DICT, 'status': 'success' }) elif node_link in workflow_manager.kind_to_workflow_dict and collection == Collections.GROUPS: # TODO move group to a separate class group_dict = Group().to_dict() group_dict['kind'] = node_link return JSONEncoder().encode({ 'group': group_dict, 'plugins_dict': PLUGINS_DICT, 'status': 'success' }) else: try: node_id = to_object_id(node_link) except Exception: return make_fail_response('Invalid ID'), 404 if collection == Collections.GROUPS: # TODO move group to a separate class group = node_collection_managers[collection].get_db_object( node_id, user_id) if group: return JSONEncoder().encode({ 'group': group, 'plugins_dict': PLUGINS_DICT, 'status': 'success', }) else: make_fail_response( 'Group `{}` was not found'.format(node_link)), 404 node = node_collection_managers[collection].get_db_node( node_id, user_id) app.logger.debug(node) if node: return JSONEncoder().encode({ 'node': node, 'plugins_dict': PLUGINS_DICT, 'status': 'success' }) else: return make_fail_response( 'Node `{}` was not found'.format(node_link)), 404
def get_graph_node_action(graph_id, action): graph_dict = graph_collection_manager.get_db_graph(graph_id, g.user._id) if not graph_dict: return make_fail_response('Graph was not found'), 404 if action == GraphNodePostAction.LIST_NODES: return make_success_response(nodes=graph_dict['nodes']) else: return make_fail_response('Unknown action `{}`. Try POST method.'.format(action)), 400
def post_register(): query = json.loads(request.data) email = query['email'].lower() username = query['username'] password = query['password'] try: user = register_user( username=username, password=password, email=email, ) except RegisterUserException as ex: return make_fail_response( ex.message, error_code=ex.error_code, ), 400 g.user = user access_token = user.generate_access_token() refresh_token = user.generate_refresh_token() user_obj = user.to_dict() user_obj['hash_password'] = '' return make_success_response({ 'access_token': access_token.decode('ascii'), 'refresh_token': refresh_token.decode('ascii'), 'user': user_obj, })
def post_search_nodes(collection): query = json.loads(request.data) app.logger.debug(request.data) query['user_id'] = to_object_id(g.user._id) virtual_collection = query.pop('virtual_collection', None) if len(query.keys() - PAGINATION_QUERY_KEYS): return make_fail_response( 'Unknown keys: `{}`'.format(query.keys() - PAGINATION_QUERY_KEYS)), 400 if collection == 'in_hubs': hub = query.pop('hub') res = hub_manager.kind_to_hub_class[hub].search( plynx.base.hub.Query(**query)) else: if virtual_collection == NodeVirtualCollection.OPERATIONS: query['node_kinds'] = list( operation_manager.kind_to_operation_dict.keys()) elif virtual_collection == NodeVirtualCollection.WORKFLOWS: query['node_kinds'] = list( workflow_manager.kind_to_workflow_dict.keys()) res = node_collection_managers[collection].get_db_objects(**query) return make_success_response({ 'items': res['list'], 'total_count': res['metadata'][0]['total'] if res['metadata'] else 0, 'plugins_dict': PLUGINS_DICT, })
def post_user(): data = json.loads(request.data) app.logger.warn(data) action = data.get('action', '') old_password = data.get('old_password', '') new_password = data.get('new_password', '') if action == UserPostAction.MODIFY: posted_user = User.from_dict(data['user']) existing_user = UserCollectionManager.find_user_by_name( posted_user.username) if not existing_user: return make_fail_response('User not found'), 404 if g.user.username != posted_user.username and IAMPolicies.IS_ADMIN not in g.user.policies: return make_fail_response( 'You don`t have permission to modify this user'), 401 if set(posted_user.policies) != set(existing_user.policies): if IAMPolicies.IS_ADMIN not in g.user.policies: return make_fail_response( 'You don`t have permission to modify policies'), 401 existing_user.policies = posted_user.policies if new_password: if not existing_user.verify_password(old_password): return make_fail_response('Incorrect password'), 401 existing_user.hash_password(new_password) existing_user.settings = posted_user.settings existing_user.save() if g.user.username == posted_user.username: g.user = posted_user is_admin = IAMPolicies.IS_ADMIN in g.user.policies user_obj = existing_user.to_dict() user_obj['_is_admin'] = is_admin user_obj[ '_readonly'] = existing_user._id != g.user._id and not is_admin del user_obj['password_hash'] return make_success_response({ 'user': user_obj, }) else: raise Exception('Unknown action: `{}`'.format(action)) raise NotImplementedError("Nothing is to return")
def worker_states(): try: return make_success_response({ 'items': get_worker_states(), 'plugins_dict': PLUGINS_DICT, }) except Exception as e: app.logger.error(e) return make_fail_response('Internal error: "{}"'.format(str(e)))
def master_state(): try: return JSONEncoder().encode({ 'status': 'success', 'master_state': get_master_state() }) except Exception as e: app.logger.error(e) return make_fail_response('Internal error: "{}"'.format(str(e)))
def post_search_graphs(): app.logger.debug(request.data) query = json.loads(request.data) if len(query.keys() - PAGINATION_QUERY_KEYS): return make_fail_response('Unknown keys: `{}`'.format(query.keys() - PAGINATION_QUERY_KEYS)), 400 res = graph_collection_manager.get_db_graphs(**query) return JSONEncoder().encode({ 'items': res['list'], 'total_count': res['metadata'][0]['total'] if res['metadata'] else 0, 'status': 'success'})
def post_demo_user(): user = demo_user_manager.create_demo_user() if not user: return make_fail_response('Failed to create demo user') demo_user_manager.create_demo_graphs(user) access_token = user.generate_access_token(expiration=1800) return JSONEncoder().encode({ 'access_token': access_token.decode('ascii'), 'refresh_token': 'Not assigned', 'username': user.username })
def post_demo_user(): user = demo_user_manager.create_demo_user() if not user: return make_fail_response('Failed to create a demo user') template_id = DemoUserManager.demo_config.kind if DemoUserManager.demo_config.template_id: try: node_id = to_object_id(DemoUserManager.demo_config.template_id) except Exception as e: app.logger.error('node_id `{}` is invalid'.format( DemoUserManager.demo_config.template_id)) app.logger.error(e) return make_fail_response('Failed to create a demo node') try: user_id = user._id node = template_collection_manager.get_db_node(node_id, user_id) node = get_class(node['_type'])(node).clone( NodeClonePolicy.NODE_TO_NODE) node.author = user_id node.save() template_id = node._id except Exception as e: app.logger.error('Failed to create a demo node') app.logger.error(e) return make_fail_response(str(e)), 500 access_token = user.generate_access_token(expiration=1800) user_obj = user.to_dict() user_obj['hash_password'] = '' return JSONEncoder().encode({ 'access_token': access_token.decode('ascii'), 'refresh_token': 'Not assigned', 'user': user_obj, 'url': '/{}/{}'.format(Collections.TEMPLATES, template_id), })
def get_user(username): user = UserCollectionManager.find_user_by_name(username) if not user: return make_fail_response('User not found'), 404 user_obj = user.to_dict() is_admin = IAMPolicies.IS_ADMIN in g.user.policies user_obj['_is_admin'] = is_admin user_obj['_readonly'] = user._id != g.user._id and not is_admin del user_obj['password_hash'] return make_success_response({ 'user': user_obj, })
def get_resource(resource_id): preview = json.loads(request.args.get('preview', 'false')) file_type = request.args.get('file_type', None) if preview and not file_type: return make_fail_response( 'In preview mode `file_type` must be specified'), 400 fp = get_file_stream(resource_id, preview=preview, file_type=file_type) if preview: preview_object = PreviewObject( fp=fp, resource_id=resource_id, ) return resource_manager[file_type].preview(preview_object) return send_file(fp, attachment_filename=resource_id)
def get_graph(graph_id=None): if graph_id == 'new': return JSONEncoder().encode({ 'data': Graph().to_dict(), 'status': 'success', 'resources_dict': resource_manager.resources_dict, }) else: graph = graph_collection_manager.get_db_graph(graph_id) if graph: return JSONEncoder().encode({ 'data': graph, 'status': 'success', 'resources_dict': resource_manager.resources_dict, }) else: return make_fail_response('Graph was not found'), 404
def post_demo_user(): user = demo_user_manager.create_demo_user() if not user: return make_fail_response('Failed to create a demo user') access_token = user.generate_access_token(expiration=1800) return JSONEncoder().encode({ 'access_token': access_token.decode('ascii'), 'refresh_token': 'Not assigned', 'username': user.username, 'url': '/{}/{}'.format(Collections.TEMPLATES, DemoUserManager.demo_config.kind), })
def upload_file(): assert len(request.files) == 1 title = request.form.get('title', '{title}') description = request.form.get('description', '{description}') file_type = request.form.get('file_type', FILE_KIND) node_kind = request.form.get('node_kind', 'basic-file') app.logger.debug(request) if file_type not in RESOURCE_TYPES: app.logger.debug(file_type) app.logger.debug(RESOURCE_TYPES) return make_fail_response( 'Unknown file type `{}`'.format(file_type)), 400 resource_id = upload_file_stream(request.files['data']) file = plynx.db.node.Node.from_dict({ 'title': title, 'description': description, 'kind': node_kind, 'node_running_status': NodeRunningStatus.STATIC, 'node_status': NodeStatus.READY, }) file.outputs.append( plynx.db.node.Output.from_dict({ 'name': 'file', 'file_type': file_type, 'values': [resource_id], })) file.author = g.user._id file.save() return JSONEncoder().encode({ 'status': ResourcePostStatus.SUCCESS, 'resource_id': resource_id, 'node': file.to_dict(), })
def post_group(): app.logger.debug(request.data) data = json.loads(request.data) group = Group.from_dict(data['group']) group.author = g.user._id db_group = node_collection_managers[Collections.GROUPS].get_db_object( group._id, g.user._id) action = data['action'] if db_group and db_group['_readonly']: return make_fail_response('Permission denied'), 403 if action == NodePostAction.SAVE: group.save(force=True) return make_success_response({ 'message': 'Group(_id=`{}`) successfully updated'.format(str(group._id)) })
def post_search_nodes(): query = json.loads(request.data) user_id = to_object_id(g.user._id) if len(query.keys() - PAGINATION_QUERY_KEYS): return make_fail_response( 'Unknown keys: `{}`'.format(query.keys() - PAGINATION_QUERY_KEYS)), 400 res = node_collection_manager.get_db_nodes(user_id=user_id, **query) return JSONEncoder().encode({ 'items': res['list'], 'total_count': res['metadata'][0]['total'] if res['metadata'] else 0, 'resources_dict': resource_manager.resources_dict, 'status': 'success' })
def post_group(): app.logger.debug(request.data) data = json.loads(request.data) group = Group.from_dict(data['group']) group.author = g.user._id db_group = node_collection_managers[Collections.GROUPS].get_db_object( group._id, g.user._id) action = data['action'] if db_group and db_group[ '_readonly'] and action not in PERMITTED_READONLY_POST_ACTIONS: return make_fail_response('Permission denied'), 403 if action == NodePostAction.SAVE: group.save(force=True) return JSONEncoder().encode({ 'status': NodePostStatus.SUCCESS, 'message': 'Group(_id=`{}`) successfully updated'.format(str(group._id)) })
def upload_file(): assert len(request.files) == 1 title = request.form.get('title', '{title}') description = request.form.get('description', '{description}') file_type = request.form.get('file_type', FileCls.NAME) if file_type not in RESOURCE_TYPES: return make_fail_response( 'Unknown file type `{}`'.format(file_type)), 400 resource_id = upload_file_stream(request.files['data']) file = FileNodeClass.get_default() file.author = g.user._id file.title = title file.description = description file.outputs[0].resource_id = resource_id file.outputs[0].file_type = file_type file.save() return JSONEncoder().encode({ 'status': ResourcePostStatus.SUCCESS, 'resource_id': resource_id, 'node': file.to_dict(), })
def _perform_graph_actions(graph, actions): graph.author = g.user._id db_graph = graph_collection_manager.get_db_graph(graph._id, g.user._id) if db_graph and db_graph['_readonly'] and set(actions) - PERMITTED_READONLY_POST_ACTIONS: return make_fail_response('Permission denied'), 403 extra_response = {} response_status = GraphPostStatus.SUCCESS response_message = 'Actions completed with Graph(_id=`{}`)'.format(str(graph._id)) for action in actions: if action == GraphPostAction.SAVE: if graph.graph_running_status != GraphRunningStatus.CREATED: return make_fail_response('Cannot save graph with status `{}`'.format(graph.graph_running_status)) graph.save(force=True) elif action == GraphPostAction.REARRANGE: graph.arrange_auto_layout() elif action == GraphPostAction.UPGRADE_NODES: upd = graph_collection_manager.upgrade_nodes(graph) extra_response['upgraded_nodes_count'] = upd elif action == GraphPostAction.APPROVE: if graph.graph_running_status != GraphRunningStatus.CREATED: return make_fail_response('Graph status `{}` expected. Found `{}`'.format(GraphRunningStatus.CREATED, graph.graph_running_status)) validation_error = graph.get_validation_error() if validation_error: response_status = GraphPostStatus.VALIDATION_FAILED response_message = 'Graph validation failed' extra_response['validation_error'] = validation_error.to_dict() else: graph.graph_running_status = GraphRunningStatus.READY graph.save(force=True) elif action == GraphPostAction.VALIDATE: validation_error = graph.get_validation_error() if validation_error: response_status = GraphPostStatus.VALIDATION_FAILED response_message = 'Graph validation failed' extra_response['validation_error'] = validation_error.to_dict() elif action == GraphPostAction.CANCEL: if graph.graph_running_status not in [ GraphRunningStatus.RUNNING, GraphRunningStatus.FAILED_WAITING ]: return make_fail_response('Graph status `{}` expected. Found `{}`'.format(GraphRunningStatus.RUNNING, graph.graph_running_status)) graph_cancellation_manager.cancel_graph(graph._id) elif action == GraphPostAction.GENERATE_CODE: extra_response['code'] = graph.generate_code() elif action == GraphPostAction.CLONE: graph = graph.clone() graph.save() extra_response['new_graph_id'] = graph._id else: return make_fail_response('Unknown action `{}`'.format(action)) return JSONEncoder().encode(dict( { 'status': response_status, 'message': response_message, 'graph': graph.to_dict(), 'url': '{}/graphs/{}'.format(WEB_CONFIG.endpoint.rstrip('/'), str(graph._id)) }, **extra_response))
def get_nodes(collection, node_link=None): user_id = to_object_id(g.user._id) can_view_others_operations = g.user.check_role( IAMPolicies.CAN_VIEW_OTHERS_OPERATIONS) can_view_others_workflows = g.user.check_role( IAMPolicies.CAN_VIEW_OTHERS_WORKFLOWS) can_view_operations = g.user.check_role(IAMPolicies.CAN_VIEW_OPERATIONS) can_view_workflows = g.user.check_role(IAMPolicies.CAN_VIEW_WORKFLOWS) can_create_operations = g.user.check_role( IAMPolicies.CAN_CREATE_OPERATIONS) can_create_workflows = g.user.check_role(IAMPolicies.CAN_CREATE_WORKFLOWS) if node_link in executor_manager.kind_to_executor_class and collection == Collections.TEMPLATES: # if node_link is a base node # i.e. /templates/basic-bash kind = node_link if kind in workflow_manager.kind_to_workflow_dict and ( not can_view_workflows or not can_create_workflows): return make_permission_denied() if kind in operation_manager.kind_to_operation_dict and ( not can_view_operations or not can_create_operations): return make_permission_denied() node = executor_manager.kind_to_executor_class[kind].get_default_node( is_workflow=kind in workflow_manager.kind_to_workflow_dict) if isinstance(node, tuple): data = node[0].to_dict() tour_steps = node[1] else: data = node.to_dict() tour_steps = [] data['kind'] = kind return make_success_response({ 'node': data, 'tour_steps': tour_steps, 'plugins_dict': PLUGINS_DICT, }) elif node_link in workflow_manager.kind_to_workflow_dict and collection == Collections.GROUPS: # TODO move group to a separate class group_dict = Group().to_dict() group_dict['kind'] = node_link return make_success_response({ 'group': group_dict, 'plugins_dict': PLUGINS_DICT, }) else: # when node_link is an id of the object try: node_id = to_object_id(node_link) except Exception: return make_fail_response('Invalid ID'), 404 if collection == Collections.GROUPS: # TODO move group to a separate class group = node_collection_managers[collection].get_db_object( node_id, user_id) if group: return make_success_response({ 'group': group, 'plugins_dict': PLUGINS_DICT, }) else: make_fail_response( 'Group `{}` was not found'.format(node_link)), 404 node = node_collection_managers[collection].get_db_node( node_id, user_id) app.logger.debug(node) if node: is_owner = node['author'] == user_id kind = node['kind'] if kind in workflow_manager.kind_to_workflow_dict and not can_view_workflows: return make_permission_denied() if kind in operation_manager.kind_to_operation_dict and not can_view_operations: return make_permission_denied() if kind in workflow_manager.kind_to_workflow_dict and not can_view_others_workflows and not is_owner: return make_permission_denied() if kind in operation_manager.kind_to_operation_dict and not can_view_others_operations and not is_owner: return make_permission_denied() return make_success_response({ 'node': node, 'plugins_dict': PLUGINS_DICT, }) else: return make_fail_response( 'Node `{}` was not found'.format(node_link)), 404
def post_node(collection): app.logger.debug(request.data) data = json.loads(request.data) node = Node.from_dict(data['node']) node.starred = False action = data['action'] db_node = node_collection_managers[collection].get_db_node( node._id, g.user._id) if db_node: if not node.author: node.author = db_node['author'] if node.author != db_node['author']: raise Exception( "Author of the node does not match the one in the database") is_author = db_node['author'] == g.user._id else: # assign the author node.author = g.user._id is_author = True is_admin = g.user.check_role(IAMPolicies.IS_ADMIN) is_workflow = node.kind in workflow_manager.kind_to_workflow_dict can_create_operations = g.user.check_role( IAMPolicies.CAN_CREATE_OPERATIONS) can_create_workflows = g.user.check_role(IAMPolicies.CAN_CREATE_WORKFLOWS) can_modify_others_workflows = g.user.check_role( IAMPolicies.CAN_MODIFY_OTHERS_WORKFLOWS) can_run_workflows = g.user.check_role(IAMPolicies.CAN_RUN_WORKFLOWS) if action == NodePostAction.SAVE: if (is_workflow and not can_create_workflows) or ( not is_workflow and not can_create_operations): return make_permission_denied( 'You do not have permission to save this object') if node.node_status != NodeStatus.CREATED: return make_fail_response( 'Cannot save node with status `{}`'.format(node.node_status)) if is_author or is_admin or (is_workflow and can_modify_others_workflows): node.save(force=True) else: return make_permission_denied( 'Only the owners or users with CAN_MODIFY_OTHERS_WORKFLOWS role can save it' ) elif action == NodePostAction.APPROVE: if is_workflow: return make_fail_response('Invalid action for a workflow'), 400 if node.node_status != NodeStatus.CREATED: return make_fail_response( 'Node status `{}` expected. Found `{}`'.format( NodeStatus.CREATED, node.node_status)) validation_error = executor_manager.kind_to_executor_class[node.kind]( node).validate() if validation_error: return make_success_response({ 'status': NodePostStatus.VALIDATION_FAILED, 'message': 'Node validation failed', 'validation_error': validation_error.to_dict() }) node.node_status = NodeStatus.READY if is_author or is_admin: node.save(force=True) else: return make_permission_denied() elif action == NodePostAction.CREATE_RUN: if not is_workflow: return make_fail_response('Invalid action for an operation'), 400 if node.node_status != NodeStatus.CREATED: return make_fail_response( 'Node status `{}` expected. Found `{}`'.format( NodeStatus.CREATED, node.node_status)) validation_error = executor_manager.kind_to_executor_class[node.kind]( node).validate() if validation_error: return make_success_response({ 'status': NodePostStatus.VALIDATION_FAILED, 'message': 'Node validation failed', 'validation_error': validation_error.to_dict() }) node = node.clone(NodeClonePolicy.NODE_TO_RUN) node.author = g.user._id if is_admin or can_run_workflows: node.save(collection=Collections.RUNS) else: return make_permission_denied( 'You do not have CAN_RUN_WORKFLOWS role') return make_success_response({ 'status': NodePostStatus.SUCCESS, 'message': 'Run(_id=`{}`) successfully created'.format(str(node._id)), 'run_id': str(node._id), 'url': '/{}/{}'.format(Collections.RUNS, node._id), }) elif action == NodePostAction.CLONE: if (is_workflow and not can_create_workflows) or ( not is_workflow and not can_create_operations): return make_permission_denied( 'You do not have the role to create an object') node_clone_policy = None if collection == Collections.TEMPLATES: node_clone_policy = NodeClonePolicy.NODE_TO_NODE elif collection == Collections.RUNS: node_clone_policy = NodeClonePolicy.RUN_TO_NODE node = node.clone(node_clone_policy) node.save(collection=Collections.TEMPLATES) return make_success_response({ 'message': 'Node(_id=`{}`) successfully created'.format(str(node._id)), 'node_id': str(node._id), 'url': '/{}/{}'.format(Collections.TEMPLATES, node._id), }) elif action == NodePostAction.VALIDATE: validation_error = executor_manager.kind_to_executor_class[node.kind]( node).validate() if validation_error: return make_success_response({ 'status': NodePostStatus.VALIDATION_FAILED, 'message': 'Node validation failed', 'validation_error': validation_error.to_dict() }) elif action == NodePostAction.DEPRECATE: if node.node_status == NodeStatus.CREATED: return make_fail_response('Node status `{}` not expected.'.format( node.node_status)) node.node_status = NodeStatus.DEPRECATED if is_author or is_admin: node.save(force=True) else: return make_permission_denied( 'You are not an author to deprecate it') elif action == NodePostAction.MANDATORY_DEPRECATE: if node.node_status == NodeStatus.CREATED: return make_fail_response('Node status `{}` not expected.'.format( node.node_status)) node.node_status = NodeStatus.MANDATORY_DEPRECATED if is_author or is_admin: node.save(force=True) else: return make_permission_denied( 'You are not an author to deprecate it') elif action == NodePostAction.PREVIEW_CMD: return make_success_response({ 'message': 'Successfully created preview', 'preview_text': executor_manager.kind_to_executor_class[node.kind](node).run( preview=True) }) elif action == NodePostAction.REARRANGE_NODES: node.arrange_auto_layout() return make_success_response({ 'message': 'Successfully created preview', 'node': node.to_dict(), }) elif action == NodePostAction.UPGRADE_NODES: upd = node_collection_managers[collection].upgrade_sub_nodes(node) return make_success_response({ 'message': 'Successfully updated nodes', 'node': node.to_dict(), 'upgraded_nodes_count': upd, }) elif action == NodePostAction.CANCEL: if is_author or is_admin: run_cancellation_manager.cancel_run(node._id) else: return make_permission_denied( 'You are not an author to cancel the run') elif action == NodePostAction.GENERATE_CODE: raise NotImplementedError() else: return make_fail_response('Unknown action `{}`'.format(action)) return make_success_response({ 'message': 'Node(_id=`{}`) successfully updated'.format(str(node._id)) })
def post_graph_action(graph_id, action): graph_dict = graph_collection_manager.get_db_graph(graph_id) if not graph_dict: return make_fail_response('Graph was not found'), 404 return _perform_graph_actions(Graph.from_dict(graph_dict), [action.upper()])
def post_node(collection): app.logger.debug(request.data) data = json.loads(request.data) node = Node.from_dict(data['node']) node.author = g.user._id node.starred = False db_node = node_collection_managers[collection].get_db_node( node._id, g.user._id) action = data['action'] if db_node and db_node[ '_readonly'] and action not in PERMITTED_READONLY_POST_ACTIONS: return make_fail_response('Permission denied'), 403 if action == NodePostAction.SAVE: if node.node_status != NodeStatus.CREATED and node.base_node_name != 'file': return make_fail_response( 'Cannot save node with status `{}`'.format(node.node_status)) node.save(force=True) elif action == NodePostAction.APPROVE: if node.node_status != NodeStatus.CREATED: return make_fail_response( 'Node status `{}` expected. Found `{}`'.format( NodeStatus.CREATED, node.node_status)) validation_error = executor_manager.kind_to_executor_class[node.kind]( node).validate() if validation_error: return JSONEncoder().encode({ 'status': NodePostStatus.VALIDATION_FAILED, 'message': 'Node validation failed', 'validation_error': validation_error.to_dict() }) node.node_status = NodeStatus.READY node.save(force=True) elif action == NodePostAction.CREATE_RUN: if node.node_status != NodeStatus.CREATED: return make_fail_response( 'Node status `{}` expected. Found `{}`'.format( NodeStatus.CREATED, node.node_status)) validation_error = executor_manager.kind_to_executor_class[node.kind]( node).validate() if validation_error: return JSONEncoder().encode({ 'status': NodePostStatus.VALIDATION_FAILED, 'message': 'Node validation failed', 'validation_error': validation_error.to_dict() }) node = node.clone(NodeClonePolicy.NODE_TO_RUN) node.save(collection=Collections.RUNS) return JSONEncoder().encode({ 'status': NodePostStatus.SUCCESS, 'message': 'Run(_id=`{}`) successfully created'.format(str(node._id)), 'run_id': str(node._id), 'url': '/{}/{}'.format(Collections.RUNS, node._id), }) elif action == NodePostAction.CLONE: node_clone_policy = None if collection == Collections.TEMPLATES: node_clone_policy = NodeClonePolicy.NODE_TO_NODE elif collection == Collections.RUNS: node_clone_policy = NodeClonePolicy.RUN_TO_NODE node = node.clone(node_clone_policy) node.save(collection=Collections.TEMPLATES) return JSONEncoder().encode({ 'status': NodePostStatus.SUCCESS, 'message': 'Node(_id=`{}`) successfully created'.format(str(node._id)), 'node_id': str(node._id), 'url': '/{}/{}'.format(Collections.TEMPLATES, node._id), }) elif action == NodePostAction.VALIDATE: validation_error = executor_manager.kind_to_executor_class[node.kind]( node).validate() if validation_error: return JSONEncoder().encode({ 'status': NodePostStatus.VALIDATION_FAILED, 'message': 'Node validation failed', 'validation_error': validation_error.to_dict() }) elif action == NodePostAction.DEPRECATE: if node.node_status == NodeStatus.CREATED: return make_fail_response('Node status `{}` not expected.'.format( node.node_status)) node.node_status = NodeStatus.DEPRECATED node.save(force=True) elif action == NodePostAction.MANDATORY_DEPRECATE: if node.node_status == NodeStatus.CREATED: return make_fail_response('Node status `{}` not expected.'.format( node.node_status)) node.node_status = NodeStatus.MANDATORY_DEPRECATED node.save(force=True) elif action == NodePostAction.PREVIEW_CMD: return JSONEncoder().encode({ 'status': NodePostStatus.SUCCESS, 'message': 'Successfully created preview', 'preview_text': executor_manager.kind_to_executor_class[node.kind](node).run( preview=True) }) elif action == NodePostAction.REARRANGE_NODES: node.arrange_auto_layout() return JSONEncoder().encode( dict({ 'status': NodePostStatus.SUCCESS, 'message': 'Successfully created preview', 'node': node.to_dict(), })) elif action == NodePostAction.UPGRADE_NODES: upd = node_collection_managers[collection].upgrade_sub_nodes(node) return JSONEncoder().encode( dict({ 'status': NodePostStatus.SUCCESS, 'message': 'Successfully updated nodes', 'node': node.to_dict(), 'upgraded_nodes_count': upd, })) elif action == NodePostAction.CANCEL: run_cancellation_manager.cancel_run(node._id) elif action == NodePostAction.GENERATE_CODE: raise NotImplementedError() else: return make_fail_response('Unknown action `{}`'.format(action)) return JSONEncoder().encode({ 'status': NodePostStatus.SUCCESS, 'message': 'Node(_id=`{}`) successfully updated'.format(str(node._id)) })
def post_node(): app.logger.debug(request.data) data = json.loads(request.data) node = Node.from_dict(data['node']) node.author = g.user._id node.starred = False db_node = node_collection_manager.get_db_node(node._id, g.user._id) action = data['action'] if db_node and db_node[ '_readonly'] and action not in PERMITTED_READONLY_POST_ACTIONS: return make_fail_response('Permission denied'), 403 if action == NodePostAction.SAVE: if node.node_status != NodeStatus.CREATED and node.base_node_name != 'file': return make_fail_response( 'Cannot save node with status `{}`'.format(node.node_status)) node.save(force=True) elif action == NodePostAction.APPROVE: if node.node_status != NodeStatus.CREATED: return make_fail_response( 'Node status `{}` expected. Found `{}`'.format( NodeStatus.CREATED, node.node_status)) validation_error = node.get_validation_error() if validation_error: return JSONEncoder().encode({ 'status': NodePostStatus.VALIDATION_FAILED, 'message': 'Node validation failed', 'validation_error': validation_error.to_dict() }) node.node_status = NodeStatus.READY node.save(force=True) elif action == NodePostAction.VALIDATE: validation_error = node.get_validation_error() if validation_error: return JSONEncoder().encode({ 'status': NodePostStatus.VALIDATION_FAILED, 'message': 'Node validation failed', 'validation_error': validation_error.to_dict() }) elif action == NodePostAction.DEPRECATE: if node.node_status == NodeStatus.CREATED: return make_fail_response('Node status `{}` not expected.'.format( node.node_status)) node.node_status = NodeStatus.DEPRECATED node.save(force=True) elif action == NodePostAction.MANDATORY_DEPRECATE: if node.node_status == NodeStatus.CREATED: return make_fail_response('Node status `{}` not expected.'.format( node.node_status)) node.node_status = NodeStatus.MANDATORY_DEPRECATED node.save(force=True) elif action == NodePostAction.PREVIEW_CMD: job = node_collection.make_job(node) return JSONEncoder().encode({ 'status': NodePostStatus.SUCCESS, 'message': 'Successfully created preview', 'preview_text': job.run(preview=True) }) else: return make_fail_response('Unknown action `{}`'.format(action)) return JSONEncoder().encode({ 'status': NodePostStatus.SUCCESS, 'message': 'Node(_id=`{}`) successfully updated'.format(str(node._id)) })
def post_graph_node_action(graph_id, action): graph_dict = graph_collection_manager.get_db_graph(graph_id, g.user._id) if not graph_dict: return make_fail_response('Graph was not found'), 404 if graph_dict['_readonly']: return make_fail_response('Permission denied'), 403 if not request.data: return make_fail_response('Empty body'), 400 data = json.loads(request.data) graph = Graph.from_dict(graph_dict) if action == GraphNodePostAction.INSERT_NODE: node_id = data.get('node_id', None) x, y = int(data.get('x', 0)), int(data.get('y', 0)) node_dict = node_collection_manager.get_db_node(node_id) if not node_dict: return make_fail_response('Node was not found'), 404 node = Node.from_dict(node_dict) node.x, node.y = x, y node.parent_node = node._id node._id = ObjectId() graph.nodes.append(node) graph.save() return make_success_response(node=node.to_dict()) elif action == GraphNodePostAction.REMOVE_NODE: node_id = ObjectId(data.get('node_id', None)) node_index = -1 for index, node in enumerate(graph.nodes): for input in node.inputs: input.values = [value for value in input.values if ObjectId(value.node_id) != node_id] if ObjectId(node._id) == node_id: node_index = index if node_index < 0: return make_fail_response('Node was not found'), 404 del graph.nodes[node_index] graph.save() return make_success_response('Node removed') elif action == GraphNodePostAction.CHANGE_PARAMETER: node_id = data.get('node_id', None) parameter_name = data.get('parameter_name', None) parameter_value = data.get('parameter_value', None) if parameter_name is None: return make_fail_response('No parameter name'), 400 if parameter_value is None: return make_fail_response('No parameter value'), 400 node, = _find_nodes(graph, node_id) if not node: return make_fail_response('Node was not found'), 404 for parameter in node.parameters: if parameter.name == parameter_name: parameter_dict = parameter.to_dict() parameter_dict['value'] = parameter_value parameter.value = Parameter(obj_dict=parameter_dict).value graph.save() return make_success_response('Parameter updated') elif action in (GraphNodePostAction.CREATE_LINK, GraphNodePostAction.REMOVE_LINK): for field in ['from', 'to']: for sub_field in ['node_id', 'resource']: if field not in data: return make_fail_response('`{}` is missing'.format(field)), 400 if sub_field not in data[field]: return make_fail_response('`{}.{}` is missing'.format(field, sub_field)), 400 from_node_id = data['from']['node_id'] from_resource = data['from']['resource'] to_node_id = data['to']['node_id'] to_resource = data['to']['resource'] from_node, to_node = _find_nodes(graph, from_node_id, to_node_id) if not from_node or not to_node: return make_fail_response('Node was not found'), 404 from_output = None to_input = None for output in from_node.outputs: if output.name == from_resource: from_output = output break for input in to_node.inputs: if input.name == to_resource: to_input = input break if not from_output or not to_input: return make_fail_response('Input or output not found'), 404 if action == GraphNodePostAction.CREATE_LINK: # TODO graph.validate() it if from_output.file_type not in to_input.file_types and 'file' not in to_input.file_types: return make_fail_response('Incompatible types'), 400 # TODO graph.validate() it if to_input.max_count > 0 and len(to_input.values) >= to_input.max_count: return make_fail_response('Number of inputs reached the limit'), 400 new_input_value = InputValue() new_input_value.node_id = from_node_id new_input_value.output_id = from_resource # TODO graph.validate() it for value in to_input.values: if value.node_id == from_node_id and value.output_id == from_resource: return make_fail_response('Link already exists'), 400 to_input.values.append(new_input_value) elif action == GraphNodePostAction.REMOVE_LINK: rm_index = -1 # TODO graph.validate() it for index, value in enumerate(to_input.values): if value.node_id == from_node_id and value.output_id == from_resource: rm_index = index break if rm_index < 0: return make_fail_response('Link not found'), 404 del to_input.values[rm_index] graph.save() return make_success_response('Completed') else: return make_fail_response('Unknown action `{}`'.format(action)), 400 return 'ok'