Beispiel #1
0
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
Beispiel #2
0
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(),
        })
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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,
    })
Beispiel #6
0
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,
    })
Beispiel #7
0
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")
Beispiel #8
0
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)))
Beispiel #9
0
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)))
Beispiel #10
0
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'})
Beispiel #11
0
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
    })
Beispiel #12
0
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),
    })
Beispiel #13
0
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,
    })
Beispiel #14
0
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)
Beispiel #15
0
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
Beispiel #16
0
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),
    })
Beispiel #17
0
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(),
    })
Beispiel #18
0
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))
    })
Beispiel #19
0
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'
    })
Beispiel #20
0
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))
    })
Beispiel #21
0
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(),
    })
Beispiel #22
0
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))
Beispiel #23
0
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
Beispiel #24
0
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))
    })
Beispiel #25
0
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()])
Beispiel #26
0
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))
    })
Beispiel #27
0
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))
    })
Beispiel #28
0
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'