Example #1
0
def org_add_user(user, org_id_slug, user_email):

    if not user.admin:
        raise AuthError('You must be an admin to add a user to an Org.')

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    if not org:
        raise NotFoundError('This Org does not exist.')

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError('You are not allowed to edit this Org.')

    # localize
    localize(org)

    # get this new user by id / email
    new_org_user = fetch_by_id_or_field(User, 'email', user_email)

    if not new_org_user:
        raise RequestError('User "{}" does not exist'.format(user_email))

    # ensure that user is not already a part of this Org.
    if new_org_user.id in org.user_ids:
        raise RequestError('User "{}" is already a part of Org "{}"'.format(
            new_org_user.email, org.name))

    org.users.append(new_org_user)
    db.session.commit()

    return jsonify(new_org_user)
Example #2
0
def org_user(user, org_id_slug, user_email):

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    if not org:
        raise NotFoundError(
            'This Org does not exist.')

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError(
            'You are not allowed to access this Org')

    # localize
    localize(org)

    # get this new user by id / email
    org_user = fetch_by_id_or_field(User, 'email', user_email)

    if not org_user:
        raise RequestError(
            'This user does not yet exist')

    # check whether this user can view this other user:
    if not len(list(set(org_user.org_ids).intersection(set(user.org_ids)))):
        raise ForbiddenError(
            'You are not allowed to view this user.'
            .format(user.email))

    return jsonify(org_user)
Example #3
0
def org_user(user, org_id_slug, user_email):

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    if not org:
        raise NotFoundError('This Org does not exist.')

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError('You are not allowed to access this Org')

    # localize
    localize(org)

    # get this new user by id / email
    org_user = fetch_by_id_or_field(User, 'email', user_email)

    if not org_user:
        raise RequestError('This user does not yet exist')

    # check whether this user can view this other user:
    if not len(list(set(org_user.org_ids).intersection(set(user.org_ids)))):
        raise ForbiddenError('You are not allowed to view this user.'.format(
            user.email))

    return jsonify(org_user)
Example #4
0
def merge_authors(user, org, from_author_id, to_author_id):
    """
    Merge two authors.
    """
    from_a = fetch_by_id_or_field(Author, 'name', from_author_id,
                                  org_id=org.id, transform='upper')
    if not from_a:
        raise NotFoundError(
            'Author with ID/Name "{}" does not exist."'
            .format(from_author_id))

    to_a = fetch_by_id_or_field(Author, 'name', to_author_id,
                                org_id=org.id, transform='upper')
    if not to_a:
        raise NotFoundError(
            'Author with ID/Name "{}" does not exist."'
            .format(to_author_id))

    # re associate content
    stmt = update(content_items_authors)\
        .where(and_(
            content_items_authors.c.author_id == from_author_id,
            ~content_items_authors.c.content_item_id.in_(to_a.content_item_ids)))\
        .values(author_id=to_author_id)

    db.session.execute(stmt)

    # remove from author id
    db.session.delete(from_a)
    db.session.commit()

    return jsonify(to_a.to_dict(incl_content=True))
Example #5
0
def org_remove_user(user, org_id_slug, user_email):

    if not user.admin:
        raise AuthError(
            'You must be an admin to remove a user from an Org.')

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    # if it still doesn't exist, raise an error.
    if not org:
        raise NotFoundError('This Org does not exist.')

    # localize
    localize(org)

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError(
            "You are not allowed to access this Org.")

    # get this existing user by id / email
    existing_user = fetch_by_id_or_field(User, 'email', user_email)

    if not existing_user:
        raise RequestError(
            'User "{}" does not yet exist'
            .format(user_email))

    # ensure that user is not already a part of this Org.
    if existing_user.id not in org.user_ids:
        raise RequestError(
            'User "{}" is not a part of Org "{}"'
            .format(existing_user.email, org.name))

    # remove the user from the org
    org.users.remove(existing_user)

    # if we're force-deleting the user, do so
    # but make sure their recipes are re-assigned
    # to the super-user
    if arg_bool('force', False):
        cmd = "UPDATE recipes set user_id={} WHERE user_id={}"\
              .format(org.super_user.id, existing_user.id)
        db.session.execute(cmd)
        db.session.delete(user)

    db.session.commit()
    return delete_response()
Example #6
0
def delete_recipe(user, org, recipe_id):

    r = fetch_by_id_or_field(Recipe, 'slug', recipe_id, org_id=org.id)
    if not r:
        raise RequestError(
            'Recipe with id/slug {} does not exist.'.format(recipe_id))
    force = arg_bool('force', default=False)

    if force:
        db.session.delete(r)
    else:
        # just delete recipes with no approved events.
        event_cnt = r.events.filter_by(status='approved').count()
        if event_cnt > 0:
            r.status = 'inactive'
            db.session.add(r)
        else:
            db.session.delete(r)

    # set the status of associated events to 'deleted'
    cmd = """
    UPDATE events SET status='deleted' WHERE recipe_id = {} AND status='pending';
    """.format(r.id)
    db.session.execute(cmd)
    db.session.commit()

    return delete_response()
Example #7
0
def update_recipe(user, org, recipe_id):

    r = fetch_by_id_or_field(Recipe, 'slug', recipe_id, org_id=org.id)
    if not r:
        raise RequestError(
            'Recipe with id/slug {} does not exist.'.format(recipe_id))

    # fetch request date and update / validate.
    req_data = request_data()
    new_recipe = recipe_schema.update(r, req_data, r.sous_chef.to_dict())

    # if the requesting user hasn't initializied this recipe,
    # do it for them:
    status = new_recipe.get('status', 'uninitialized')
    if r.status == 'uninitialized' and status == 'uninitialized':
        new_recipe['status'] = 'stable'

    # update pickled options
    new_opts = new_recipe.pop('options')
    r.set_options(new_opts)

    # update all other fields
    for col, val in new_recipe.items():
        setattr(r, col, val)

    db.session.add(r)
    db.session.commit()

    return jsonify(r)
Example #8
0
def create_recipe(user, org):

    req_data = request_data()

    sous_chef = req_data.pop('sous_chef', arg_str('sous_chef', None))
    if not sous_chef:
        raise RequestError(
            'You must pass in a SousChef ID or slug to create a recipe.')

    sc = fetch_by_id_or_field(SousChef, 'slug', sous_chef)
    if not sc:
        raise RequestError(
            'A SousChef does not exist with ID/slug {}'.format(sous_chef))

    # validate the recipe and add it to the database.
    recipe = recipe_schema.validate(req_data, sc.to_dict())
    r = Recipe(sc, user_id=user.id, org_id=org.id, **recipe)
    db.session.add(r)
    db.session.commit()

    # if the recipe creates metrics create them in here.
    if 'metrics' in sc.creates:
        for name, params in sc.metrics.items():
            m = Metric(name=name, recipe_id=r.id, org_id=org.id, **params)
            db.session.add(m)
    try:
        db.session.commit()

    except Exception as e:
        raise ConflictError(
            "You tried to create a metric that already exists. "
            "Here's the exact error:\n{}".format(e.message))

    return jsonify(r)
Example #9
0
def update_sous_chef(user, sous_chef):

    sc = fetch_by_id_or_field(SousChef, 'slug', sous_chef)
    if not sc:
        raise NotFoundError(
            'A SousChef does not exist with ID/slug {}'
            .format(sous_chef))

    req_data = request_data()

    # validate the schema
    new_sous_chef = sous_chef_schema.update(sc, req_data)

    # udpate
    for name, value in new_sous_chef.items():
        setattr(sc, name, value)
    db.session.add(sc)

    try:
        db.session.commit()

    except Exception as e:
        raise RequestError(
            "An error occurred while updating SousChef '{}'. "
            "Here's the error message: {}"
            .format(sc.slug, e.message))
    return jsonify(sc)
Example #10
0
def update_metric(user, org, name_id):

    m = fetch_by_id_or_field(Metric, 'name', name_id, org_id=org.id)
    if not m:
        raise NotFoundError(
            'Metric "{}" does not yet exist for Org "{}"'
            .format(name_id, org.name))

    # get the request data
    req_data = request_data()

    # filter out any non-columns
    columns = get_table_columns(Metric)
    for k in req_data.keys():
        if k not in columns:
            req_data.pop(k)

    # don't ever overwrite these:
    for k in ['id', 'recipe_id', 'name', 'org_id', 'created', 'updated']:
        if k in req_data:
            req_data.pop(k, None)

    # update fields
    for k, v in req_data.items():
        setattr(m, k, v)
    try:
        db.session.add(m)
        db.session.commit()
    except Exception as e:
        raise RequestError("Error updating Metric: {}".format(e.message))

    return jsonify(m)
Example #11
0
def author_remove_content(user, org, author_id, content_item_id):
    """
    Remove an author from a content item.
    """
    a = fetch_by_id_or_field(Author, 'name', author_id,
                             org_id=org.id, transform='upper')
    if not a:
        raise NotFoundError(
            'Author with ID/Name "{}" does not exist."'
            .format(author_id))

    c = ContentItem.query\
        .filter_by(id=content_item_id, org_id=org.id)\
        .first()

    if not c:
        raise RequestError(
            'ContentItem with ID {} does not exist.'
            .format(content_item_id))

    if a.id in c.author_ids:
        a.content_items.remove(c)

    db.session.add(a)
    db.session.commit()
    return delete_response()
Example #12
0
def author_add_content(user, org, author_id, content_item_id):
    """
    Add an author to a content item.
    """
    a = fetch_by_id_or_field(Author, 'name', author_id,
                             org_id=org.id, transform='upper')
    if not a:
        raise NotFoundError(
            'Author with ID/Name "{}" does not exist."'
            .format(author_id))

    c = ContentItem.query\
        .filter_by(id=content_item_id, org_id=org.id)\
        .first()
    if not c:
        raise RequestError(
            'ContentItem with ID {} does not exist.'
            .format(content_item_id))

    if a.id not in c.author_ids:
        c.authors.append(a)

    db.session.add(c)
    db.session.commit()
    # return modified author
    return jsonify(a.to_dict(incl_content=True))
Example #13
0
def delete_metric(user, org, name_id):

    m = fetch_by_id_or_field(Metric, 'name', name_id, org_id=org.id)
    if not m:
        raise NotFoundError(
            'Metric "{}" does not yet exist.'
            .format(name_id))

    # format for deleting metrics from metric store.
    cmd_fmt = "UPDATE {table} " + \
              "SET metrics=json_del_keys(metrics, '{name}'::text);"\
              .format(name=m.name)

    # delete metric from metric stores.
    if 'timeseries' in m.content_levels:
        db.session.execute(cmd_fmt.format(table="content_metric_timeseries"))

    if 'summary' in m.content_levels:
        db.session.execute(cmd_fmt.format(table="content_metric_summary"))

    if 'timeseries' in m.org_levels:
        db.session.execute(cmd_fmt.format(table="org_metric_timeseries"))

    if 'summary' in m.org_levels:
        db.session.execute(cmd_fmt.format(table="org_metric_summary"))

    db.session.delete(m)
    db.session.commit()

    return delete_response()
Example #14
0
def update_author(user, org, author_id):
    """
    Update an author.
    """

    a = fetch_by_id_or_field(Author,
                             'name',
                             author_id,
                             org_id=org.id,
                             transform='upper')
    if not a:
        raise NotFoundError(
            'Author with ID/Name "{}" does not exist."'.format(author_id))

    req_data = request_data()

    cols = get_table_columns(Author)
    for k in req_data.keys():
        if k not in cols or k in ['id', 'org_id']:
            req_data.pop(k, None)

    for k, v in req_data.items():
        if k == 'name':
            if v:
                v = v.upper()
        setattr(a, k, v)

    db.session.add(a)
    db.session.commit()
    return jsonify(a)
Example #15
0
def cook_a_recipe(user, org, recipe_id):
    """
    Run recipes via the API.
    """
    r = fetch_by_id_or_field(Recipe, 'slug', recipe_id, org_id=org.id)
    if not r:
        raise RequestError(
            'Recipe with id/slug {} does not exist.'.format(recipe_id))

    # setup kwargs for merlynne
    kw = dict(org=org.to_dict(incl_auths=True,
                              auths_as_dict=True,
                              settings_as_dict=True,
                              incl_domains=True,
                              incl_users=True),
              apikey=user.apikey,
              recipe=r.to_dict(),
              recipe_obj=r,
              sous_chef_path=r.sous_chef.runs)

    # cook recipe
    merlynne = Merlynne(**kw)
    try:
        job_id = merlynne.cook_recipe()
    except Exception as e:
        raise RequestError(
            'There was a problem initializing the SousChef: {}'.format(
                e.message))

    # # return job status url
    ret = url_for_job_status(apikey=user.apikey, job_id=job_id, queue='recipe')
    return jsonify(ret, status=202)
Example #16
0
    def decorated_function(*args, **kw):

        # get the org
        org_id = arg_str('org', default=None)
        if not org_id:
            raise AuthError(
                'An org is required for this request.')

        # get the user object.
        user = kw.get('user')

        org = fetch_by_id_or_field(Org, 'slug', org_id)

        # if it still doesn't exist, raise an error.
        if not org:
            raise NotFoundError(
                'An Org with ID/Slug {} does exist.'
                .format(org_id))

        # otherwise ensure the active user can edit this Org
        if user.id not in org.user_ids:
            raise ForbiddenError(
                'User "{}" is not allowed to access Org "{}".'
                .format(user.name, org.name))

        # check if we should localize this request
        localize(org)

        kw['org'] = org
        return f(*args, **kw)
Example #17
0
def update_author(user, org, author_id):
    """
    Update an author.
    """

    a = fetch_by_id_or_field(Author, 'name', author_id,
                             org_id=org.id, transform='upper')
    if not a:
        raise NotFoundError(
            'Author with ID/Name "{}" does not exist."'
            .format(author_id))

    req_data = request_data()

    cols = get_table_columns(Author)
    for k in req_data.keys():
        if k not in cols or k in ['id', 'org_id']:
            req_data.pop(k, None)

    for k, v in req_data.items():
        if k == 'name':
            if v:
                v = v.upper()
        setattr(a, k, v)

    db.session.add(a)
    db.session.commit()
    return jsonify(a)
Example #18
0
def update_sous_chef(user, sous_chef):

    sc = fetch_by_id_or_field(SousChef, 'slug', sous_chef)
    if not sc:
        raise NotFoundError(
            'A SousChef does not exist with ID/slug {}'.format(sous_chef))

    req_data = request_data()

    # validate the schema
    new_sous_chef = sous_chef_schema.update(sc, req_data)

    # udpate
    for name, value in new_sous_chef.items():
        setattr(sc, name, value)
    db.session.add(sc)

    try:
        db.session.commit()

    except Exception as e:
        raise RequestError("An error occurred while updating SousChef '{}'. "
                           "Here's the error message: {}".format(
                               sc.slug, e.message))

    return jsonify(sc)
Example #19
0
def org_delete(user, org_id_slug):

    if not user.admin:
        raise AuthError('You must be an admin to delete an Org')

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    # if it still doesn't exist, raise an error.
    if not org:
        raise NotFoundError('This Org does not exist.')

    # localize
    localize(org)

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError(
            'User "{}" is not allowed to access Org "{}".'.format(
                user.name, org.name))

    db.session.delete(org)
    db.session.commit()

    return delete_response()
Example #20
0
def delete_recipe(user, org, recipe_id):

    r = fetch_by_id_or_field(Recipe, 'slug', recipe_id, org_id=org.id)
    if not r:
        raise NotFoundError('Recipe with id/slug {} does not exist.'
                            .format(recipe_id))
    force = arg_bool('force', default=False)

    if force:
        db.session.delete(r)
    else:
        # just delete recipes with no approved events.
        event_cnt = r.events.filter_by(status='approved').count()
        if event_cnt > 0:
            r.status = 'inactive'
            db.session.add(r)
        else:
            db.session.delete(r)

    # set the status of associated pending events to 'deleted'
    cmd = """
    UPDATE events SET status='deleted' WHERE recipe_id = {} AND status='pending';
    """.format(r.id)
    db.session.execute(cmd)
    db.session.commit()
    return delete_response()
Example #21
0
def author_add_content(user, org, author_id, content_item_id):
    """
    Add an author to a content item.
    """
    a = fetch_by_id_or_field(Author,
                             'name',
                             author_id,
                             org_id=org.id,
                             transform='upper')
    if not a:
        raise NotFoundError(
            'Author with ID/Name "{}" does not exist."'.format(author_id))

    c = ContentItem.query\
        .filter_by(id=content_item_id, org_id=org.id)\
        .first()
    if not c:
        raise RequestError(
            'ContentItem with ID {} does not exist.'.format(content_item_id))

    if a.id not in c.author_ids:
        c.authors.append(a)

    db.session.add(c)
    db.session.commit()
    # return modified author
    return jsonify(a.to_dict(incl_content=True))
Example #22
0
    def decorated_function(*args, **kw):

        # get the org
        org_id = arg_str('org', default=None)
        if not org_id:
            raise AuthError('An org is required for this request.')

        # get the user object.
        user = kw.get('user')

        org = fetch_by_id_or_field(Org, 'slug', org_id)

        # if it still doesn't exist, raise an error.
        if not org:
            raise NotFoundError(
                'An Org with ID/Slug {} does exist.'.format(org_id))

        # otherwise ensure the active user can edit this Org
        if user.id not in org.user_ids:
            raise ForbiddenError(
                'User "{}" is not allowed to access Org "{}".'.format(
                    user.name, org.name))

        # check if we should localize this request
        localize(org)

        kw['org'] = org
        return f(*args, **kw)
Example #23
0
def get_sous_chef(user, sous_chef):

    sc = fetch_by_id_or_field(SousChef, "slug", sous_chef)
    if not sc:
        raise NotFoundError("A SousChef does not exist with ID/slug {}".format(sous_chef))

    return jsonify(sc)
Example #24
0
def org_delete(user, org_id_slug):

    if not user.admin:
        raise AuthError(
            'You must be an admin to delete an Org')

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    # if it still doesn't exist, raise an error.
    if not org:
        raise NotFoundError(
            'This Org does not exist.')

    # localize
    localize(org)

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError(
            'User "{}" is not allowed to access Org "{}".'
            .format(user.name, org.name))

    db.session.delete(org)
    db.session.commit()

    return delete_response()
Example #25
0
def bulk_create_org_timeseries(user, org_id_slug):

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    # if it still doesn't exist, raise an error.
    if not org:
        raise NotFoundError(
            'This Org does not exist.')

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError(
            'You are not allowed to access this Org')

    req_data = request_data()

    job_id = ingest_bulk.org_timeseries(
        req_data,
        org_id=org.id,
        metrics_lookup=org.timeseries_metrics,
        commit=False
    )
    ret = url_for_job_status(apikey=user.apikey, job_id=job_id, queue='bulk')
    return jsonify(ret)
Example #26
0
def author_remove_content(user, org, author_id, content_item_id):
    """
    Remove an author from a content item.
    """
    a = fetch_by_id_or_field(Author,
                             'name',
                             author_id,
                             org_id=org.id,
                             transform='upper')
    if not a:
        raise NotFoundError(
            'Author with ID/Name "{}" does not exist."'.format(author_id))

    c = ContentItem.query\
        .filter_by(id=content_item_id, org_id=org.id)\
        .first()

    if not c:
        raise RequestError(
            'ContentItem with ID {} does not exist.'.format(content_item_id))

    if a.id in c.author_ids:
        a.content_items.remove(c)

    db.session.add(a)
    db.session.commit()
    return delete_response()
Example #27
0
def org_metrics_summary(user, org_id_slug):

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    # if it still doesn't exist, raise an error.
    if not org:
        raise NotFoundError(
            'This Org does not exist.')

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError(
            'You are not allowed to access this Org')

    # localize
    localize(org)

    req_data = request_data()

    ret = ingest_metric.org_summary(
        req_data,
        org_id=org.id,
        valid_metrics=org.org_summary_metric_names,
        commit=True
    )
    return jsonify(ret)
Example #28
0
def get_recipe(user, org, recipe_id):
    r = fetch_by_id_or_field(Recipe, 'slug', recipe_id, org_id=org.id)
    if not r:
        raise RequestError('Recipe with id/slug {} does not exist.'
                           .format(recipe_id))

    # add in event counts.
    return jsonify(r)
Example #29
0
def get_template(user, org, slug_id):

    t = fetch_by_id_or_field(Template, 'slug', slug_id, org_id=org.id)
    if not t:
        raise NotFoundError(
            'Template "{}" does not yet exist for Org "{}"'
            .format(slug_id, org.name))
    return jsonify(t)
Example #30
0
def get_template(user, org, slug_id):

    t = fetch_by_id_or_field(Template, 'slug', slug_id, org_id=org.id)
    if not t:
        raise NotFoundError(
            'Template "{}" does not yet exist for Org "{}"'.format(
                slug_id, org.name))
    return jsonify(t)
Example #31
0
def get_recipe(user, org, recipe_id):
    r = fetch_by_id_or_field(Recipe, 'slug', recipe_id, org_id=org.id)
    if not r:
        raise RequestError(
            'Recipe with id/slug {} does not exist.'.format(recipe_id))

    # add in event counts.
    return jsonify(r)
Example #32
0
def get_sous_chef(user, sous_chef):

    sc = fetch_by_id_or_field(SousChef, 'slug', sous_chef)
    if not sc:
        raise NotFoundError(
            'A SousChef does not exist with ID/slug {}'.format(sous_chef))

    return jsonify(sc)
Example #33
0
def update_recipe(user, org, recipe_id):

    r = fetch_by_id_or_field(Recipe, 'slug', recipe_id, org_id=org.id)
    if not r:
        raise NotFoundError('Recipe with id/slug {} does not exist.'
                            .format(recipe_id))

    # keep track of current coptions hash.
    current_option_hash = copy.copy(r.options_hash)

    # fetch request date and update / validate.
    req_data = request_data()
    new_recipe = recipe_schema.update(r, req_data, r.sous_chef.to_dict())

    # if the requesting user hasn't initializied this recipe,
    # do it for them:
    status = new_recipe.get('status', 'uninitialized')
    if r.status == 'uninitialized' and status == 'uninitialized':
        new_recipe['status'] = 'stable'
        
    # update pickled options
    new_opts = new_recipe.pop('options')
    r.set_options(new_opts)

    # update all other fields
    for col, val in new_recipe.items():
        setattr(r, col, val)

    # if the new options hash is different than the old one, we should
    # override the last_job column to be null
    if current_option_hash != r.options_hash:
        r.last_job = {}

    db.session.add(r)

    # now install metrics + reports
    if new_recipe.get('status', 'uninitialized') and r.status == 'stable':

        for name, params in r.sous_chef.metrics.items():

            m = Metric.query\
                .filter_by(org_id=org.id, recipe_id=r.id, name=name, type=params['type'])\
                .first()

            if not m:
                m = Metric(
                    name=name,
                    recipe_id=r.id,
                    org_id=org.id,
                    **params)
            else:
                for k, v in params.items():
                    setattr(m, k, v)

            db.session.add(m)

    db.session.commit()
    return jsonify(r)
Example #34
0
def get_setting(user, org, level, name_id):

    if level not in ['me', 'orgs']:
        raise NotFoundError(
            'You cannot store settings for \'{}\''
            .format(level))
    if level == 'me':
        s = fetch_by_id_or_field(
            Setting, 'name', name_id, org_id=org.id, user_id=user.id, level=level)
    else:
        s = fetch_by_id_or_field(
                Setting, 'name', name_id, org_id=org.id, level=level)
    if not s:
        raise NotFoundError(
            'Setting "{}" does not yet exist for Org "{}"'
            .format(name_id, org.name))

    return jsonify(s)
Example #35
0
def update_tag(user, org, tag_id):
    """
    Update an individual tag.
    """
    # fetch the tag object
    tag = fetch_by_id_or_field(Tag, 'slug', tag_id, org_id=org.id)
    if not tag:
        raise NotFoundError(
            'A Tag with ID {} does not exist'
            .format(tag_id))

    # fetch the request data.
    req_data = request_data()

    # check hex code
    if 'color' in req_data:
        validate_hex_code(req_data['color'])

    # check tag type
    if 'type' in req_data:
        validate_tag_types(req_data['type'])

        # if tag type is "impact" ensure a proper category and
        # level are included
        if req_data['type'] == 'impact':
            validate_tag_categories(req_data['category'])
            validate_tag_levels(req_data['level'])

    # check if levels + categories are being assigned to
    # subject tags
    if tag.type == 'subject':
        if req_data.get('category') or req_data.get('level'):
            raise RequestError(
                'Categories and Levels can only be set for Impact Tags')

    # set org id
    req_data['org_id'] = org.id

    # filter out non-table columns
    columns = get_table_columns(Tag)
    for k in req_data.keys():
        if k not in columns:
            req_data.pop(k)

    # update attributes
    for k, v in req_data.items():
        setattr(tag, k, v)

    db.session.add(tag)

    # check for dupes
    try:
        db.session.commit()
    except Exception as err:
        raise RequestError(err.message)

    return jsonify(tag)
Example #36
0
def get_metric(user, org, name_id):

    m = fetch_by_id_or_field(Metric, 'name', name_id, org_id=org.id)
    if not m:
        raise NotFoundError(
            'Metric "{}" does not yet exist for Org "{}"'
            .format(name_id, org.name))

    return jsonify(m)
Example #37
0
def get_setting(user, org, name_id):

    s = fetch_by_id_or_field(Setting, 'name', name_id, org_id=org.id)
    if not s:
        raise NotFoundError(
            'Setting "{}" does not yet exist for Org "{}"'
            .format(name_id, org.name))

    return jsonify(s)
Example #38
0
def org_remove_user(user, org_id_slug, user_email):

    if not user.admin:
        raise AuthError('You must be an admin to remove a user from an Org.')

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    # if it still doesn't exist, raise an error.
    if not org:
        raise NotFoundError('This Org does not exist.')

    # localize
    localize(org)

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError("You are not allowed to access this Org.")

    # get this existing user by id / email
    existing_user = fetch_by_id_or_field(User, 'email', user_email)

    if not existing_user:
        raise RequestError('User "{}" does not yet exist'.format(user_email))

    # ensure that user is not already a part of this Org.
    if existing_user.id not in org.user_ids:
        raise RequestError('User "{}" is not a part of Org "{}"'.format(
            existing_user.email, org.name))

    # remove the user from the org
    org.users.remove(existing_user)

    # if we're force-deleting the user, do so
    # but make sure their recipes are re-assigned
    # to the super-user
    if arg_bool('force', False):
        cmd = "UPDATE recipes set user_id={} WHERE user_id={}"\
              .format(org.super_user.id, existing_user.id)
        db.session.execute(cmd)
        db.session.delete(user)

    db.session.commit()
    return delete_response()
Example #39
0
def delete_template(user, org, slug_id):

    t = fetch_by_id_or_field(Template, 'slug', slug_id, org_id=org.id)
    if not t:
        raise NotFoundError(
            'Template "{}" does not yet exist for Org "{}"'.format(
                slug_id, org.name))
    db.session.delete(t)
    db.session.commit()
    return delete_response()
Example #40
0
def delete_template(user, org, slug_id):

    t = fetch_by_id_or_field(Template, 'slug', slug_id, org_id=org.id)
    if not t:
        raise NotFoundError(
            'Template "{}" does not yet exist for Org "{}"'
            .format(slug_id, org.name))
    db.session.delete(t)
    db.session.commit()
    return delete_response()
Example #41
0
def delete_sous_chef(user, sous_chef):

    sc = fetch_by_id_or_field(SousChef, "slug", sous_chef)
    if not sc:
        raise NotFoundError("A SousChef does not exist with ID/slug {}".format(sous_chef))

    db.session.delete(sc)
    db.session.commit()

    return delete_response()
Example #42
0
def get_tag(user, org, tag_id):
    """
    GET an individual tag.
    """
    # fetch the tag object
    tag = fetch_by_id_or_field(Tag, 'slug', tag_id, org_id=org.id)
    if not tag:
        raise NotFoundError('A Tag with ID {} does not exist'.format(tag_id))

    return jsonify(tag)
Example #43
0
def delete_sous_chef(user, sous_chef):

    sc = fetch_by_id_or_field(SousChef, 'slug', sous_chef)
    if not sc:
        raise NotFoundError(
            'A SousChef does not exist with ID/slug {}'.format(sous_chef))

    db.session.delete(sc)
    db.session.commit()

    return delete_response()
Example #44
0
def cook_a_recipe(user, org, recipe_id):
    """
    Run recipes via the API.
    """
    r = fetch_by_id_or_field(Recipe, 'slug', recipe_id, org_id=org.id)
    if not r:
        raise RequestError('Recipe with id/slug {} does not exist.'
                           .format(recipe_id))

    # setup kwargs for merlynne
    kw = dict(
        org=org.to_dict(
            incl_auths=True,
            auths_as_dict=True,
            settings_as_dict=True,
            incl_domains=True,
            incl_users=True),
        apikey=user.apikey,
        recipe=r.to_dict(),
        recipe_obj=r,
        passthrough=arg_bool('passthrough', default=False),
        sous_chef_path=r.sous_chef.runs
    )

    # initialize merlynne
    merlynne = Merlynne(**kw)
    try:
        resp = merlynne.cook_recipe()
    
    except Exception as e:
        raise RequestError(
            'There was a problem initializing the SousChef: {}'
            .format(e.message))

    # queued job
    if not kw['passthrough']:
        # set its status as 'queued'
        r.status = 'queued'
        db.session.add(r)
        db.session.commit()
        # # return job status url
        ret = url_for_job_status(apikey=user.apikey, job_id=resp, queue='recipe')
        return jsonify(ret, status=202)
    
    # format non-iterables.
    if isinstance(resp, dict):
        resp = [resp]

    # stream results
    def generate():
        for item in resp:
            yield obj_to_json(item) + "\n"

    return Response(stream_with_context(generate()))
Example #45
0
def update_recipe(user, org, recipe_id):

    r = fetch_by_id_or_field(Recipe, 'slug', recipe_id, org_id=org.id)
    if not r:
        raise NotFoundError(
            'Recipe with id/slug {} does not exist.'.format(recipe_id))

    # keep track of current coptions hash.
    current_option_hash = copy.copy(r.options_hash)

    # fetch request date and update / validate.
    req_data = request_data()
    new_recipe = recipe_schema.update(r, req_data, r.sous_chef.to_dict())

    # if the requesting user hasn't initializied this recipe,
    # do it for them:
    status = new_recipe.get('status', 'uninitialized')
    if r.status == 'uninitialized' and status == 'uninitialized':
        new_recipe['status'] = 'stable'

    # update pickled options
    new_opts = new_recipe.pop('options')
    r.set_options(new_opts)

    # update all other fields
    for col, val in new_recipe.items():
        setattr(r, col, val)

    # if the new options hash is different than the old one, we should
    # override the last_job column to be null
    if current_option_hash != r.options_hash:
        r.last_job = {}

    db.session.add(r)

    # now install metrics + reports
    if new_recipe.get('status', 'uninitialized') and r.status == 'stable':

        for name, params in r.sous_chef.metrics.items():

            m = Metric.query\
                .filter_by(org_id=org.id, recipe_id=r.id, name=name, type=params['type'])\
                .first()

            if not m:
                m = Metric(name=name, recipe_id=r.id, org_id=org.id, **params)
            else:
                for k, v in params.items():
                    setattr(m, k, v)

            db.session.add(m)

    db.session.commit()
    return jsonify(r)
Example #46
0
def delete_tag(user, org, tag_id):
    """
    Delete an individual tag.
    """
    # fetch the tag object
    tag = fetch_by_id_or_field(Tag, 'slug', tag_id, org_id=org.id)
    if not tag:
        raise NotFoundError('A Tag with ID {} does not exist'.format(tag_id))

    db.session.delete(tag)
    db.session.commit()
    return delete_response()
Example #47
0
def update_setting(user, org, level, name_id):

    if level not in ['me', 'orgs']:
        raise NotFoundError(
            'You cannot store settings for \'{}\''.format(level))

    s = fetch_by_id_or_field(Setting,
                             'name',
                             name_id,
                             org_id=org.id,
                             user_id=user.id,
                             level=level)

    if not s:
        raise NotFoundError('Setting "{}" does not yet exist.'.format(
            name_id, org.name))

    # get the request data
    req_data = request_data()

    name = req_data.get('name')
    value = req_data.get('value')
    json_value = req_data.get('json_value')

    # if it's a json_value check whether we can parse it as such
    if json_value:
        if isinstance(value, basestring):
            try:
                obj_to_json(value)
            except:
                raise RequestError(
                    "Setting '{}' with value '{}' was declared as a "
                    "'json_value' but could not be parsed as such.".format(
                        name_id, value))

    # upsert / patch values.
    if name:
        s.name = name

    if json_value:
        if not isinstance(json_value, bool):
            if str(json_value).lower() in TRUE_VALUES:
                json_value = True
            else:
                json_value = False
        s.json_value = json_value
        s.value = obj_to_json(value)
    else:
        s.value = value
    db.session.add(s)
    db.session.commit()

    return jsonify(s)
Example #48
0
def get_tag(user, org, tag_id):
    """
    GET an individual tag.
    """
    # fetch the tag object
    tag = fetch_by_id_or_field(Tag, 'slug', tag_id, org_id=org.id)
    if not tag:
        raise NotFoundError(
            'A Tag with ID {} does not exist'
            .format(tag_id))

    return jsonify(tag)
Example #49
0
def get_author(user, org, author_id):
    """
    Get an author.
    """
    incl_content = arg_bool('incl_content', default=False)
    a = fetch_by_id_or_field(Author, 'name', author_id,
                             org_id=org.id, transform='upper')
    if not a:
        raise NotFoundError(
            'Author with ID/Name "{}" does not exist."'
            .format(author_id))
    return jsonify(a.to_dict(incl_content=incl_content))
Example #50
0
def org_create_user(user, org_id_slug):

    if not user.admin:
        raise AuthError(
            'You must be an admin to create a user for an Org.')

    # get the form.
    req_data = request_data()
    email = req_data.get('email')
    password = req_data.get('password')
    name = req_data.get('name')
    admin = req_data.get('admin', False)

    if not all([email, password, name]):
        raise RequestError(
            'An email, password, and name are required to create a User.')

    # fetch org
    org = fetch_by_id_or_field(Org, 'slug', org_id_slug)

    # if it still doesn't exist, raise an error.
    if not org:
        raise NotFoundError('This Org does not exist.')

    # localize
    localize(org)

    # ensure the active user can edit this Org
    if user.id not in org.user_ids:
        raise ForbiddenError(
            "You are not allowed to access this Org.")

    if User.query.filter_by(email=email).first():
        raise RequestError(
            'A User with email "{}" already exists'
            .format(email))

    if not mail.validate(email):
        raise RequestError(
            '{} is an invalid email address.'
            .format(email))

    new_org_user = User(
        email=email,
        password=password,
        name=name,
        admin=admin)

    org.users.append(new_org_user)
    db.session.commit()

    return jsonify(new_org_user)
Example #51
0
def delete_setting(user, org, name_id):

    s = fetch_by_id_or_field(Setting, 'name', name_id, org_id=org.id)

    if not s:
        raise NotFoundError(
            'Setting "{}" does not yet exist for Org "{}"'
            .format(name_id, org.name))

    db.session.delete(s)
    db.session.commit()

    return delete_response()
Example #52
0
def update_setting(user, org, level, name_id):

    if level not in ['me', 'orgs']:
        raise NotFoundError(
            'You cannot store settings for \'{}\''
            .format(level))

    s = fetch_by_id_or_field(
        Setting, 'name', name_id, org_id=org.id, user_id=user.id, level=level)

    if not s:
        raise NotFoundError(
            'Setting "{}" does not yet exist.'
            .format(name_id, org.name))

    # get the request data
    req_data = request_data()

    name = req_data.get('name')
    value = req_data.get('value')
    json_value = req_data.get('json_value')

    # if it's a json_value check whether we can parse it as such
    if json_value:
        if isinstance(value, basestring):
            try:
                obj_to_json(value)
            except:
                raise RequestError(
                    "Setting '{}' with value '{}' was declared as a "
                    "'json_value' but could not be parsed as such."
                    .format(name_id, value))

    # upsert / patch values.
    if name:
        s.name = name

    if json_value:
        if not isinstance(json_value, bool):
            if str(json_value).lower() in TRUE_VALUES:
                json_value = True
            else:
                json_value = False
        s.json_value = json_value
        s.value = obj_to_json(value)
    else:
       s.value = value
    db.session.add(s)
    db.session.commit()

    return jsonify(s)