def list_settings(user, org, level):
    if level not in ['me', 'orgs']:
        raise NotFoundError(
            'You cannot store settings for \'{}\''
            .format(level))
    if level == 'orgs':
        return jsonify(org.settings)
    return jsonify(user.get_settings(org_id=org.id))
def response_from_cache(cr):
    """
    Format a response from a cache object.
    """
    if arg_bool('cache_details', default=False):
        resp = jsonify({'cache': cr, 'comparisons': cr.value})
    else:
        resp = jsonify(cr.value)
    resp.headers['Last-Modified'] = cr.last_modified
    return resp
def get_all_content_comparisons(user, org):
    """
    Refresh content comparisons.
    """
    refresh = arg_bool('refresh', default=False)
    cache_details = arg_bool('cache_details', default=False)
    if refresh:
        comparisons_cache.invalidate(org.id)
    cr = comparisons_cache.get(org.id)
    if refresh and cr.is_cached:
        raise InternalServerError(
            'Something went wrong with the cache invalidation process.')
    if cache_details:
        return jsonify({'cache': cr, 'comparisons': cr.value})
    return jsonify(cr.value)
Beispiel #4
0
def event_delete_tag(user, org, event_id, tag_id):
    """
    Remove a tag from an event.
    """
    e = Event.query\
        .filter_by(id=event_id, org_id=org.id)\
        .first()
    if not e:
        raise NotFoundError(
            'An Event with ID {} does not exist.'.format(event_id))

    if tag_id not in e.tag_ids:
        raise RequestError(
            'An Event with ID {} does not currently have an association '
            'with a Tag with ID {}.'.format(event_id, tag_id))

    # remove tag from event
    for tag in e.tags:
        if tag.id == tag_id:
            e.tags.remove(tag)

    # update metrics associated with these content item ids
    if len(e.content_item_ids):
        rollup_metric.content_summary_from_events(org, e.content_item_ids)

    db.session.add(e)
    db.session.commit()

    # return modified event
    return jsonify(e)
Beispiel #5
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)
def list_sous_chefs(user):

    # optionally filter by type/level/category
    creates = arg_str("creates", default="all")
    is_command = arg_bool("is_command", default=None)

    # base query
    sous_chef_query = db.session.query(SousChef)

    # apply filters
    if creates != "all":
        sous_chef_query = sous_chef_query.filter_by(creates=creates)

    if is_command is not None:
        sous_chef_query = sous_chef_query.filter_by(is_command=is_command)

    # process query, compute facets.
    clean_sous_chefs = []
    facets = defaultdict(Counter)
    for sc in sous_chef_query.all():
        facets["creates"][sc.creates] += 1
        if not sc.is_command:
            facets["runners"]["python"] += 1
        else:
            facets["runners"]["command"] += 1
        clean_sous_chefs.append(sc)

    resp = {"facets": facets, "sous_chefs": clean_sous_chefs}
    return jsonify(resp)
Beispiel #7
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))
Beispiel #8
0
def update_author(user, org, author_id):
    """
    Update an author.
    """

    a = Author.query\
        .filter_by(id=author_id, org_id=org.id)\
        .first()

    if not a:
        raise NotFoundError(
            'Author with ID "{}" 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():
        setattr(a, k, v)

    db.session.add(a)
    db.session.commit()

    return jsonify(a)
Beispiel #9
0
def author_add_content(user, org, author_id, content_item_id):
    """
    Add an author to a content item.
    """
    a = Author.query\
        .filter_by(id=author_id, org_id=org.id)\
        .first()

    if not a:
        raise NotFoundError(
            'Author with ID "{}" 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 event
    return jsonify(a.to_dict(incl_content=True))
Beispiel #10
0
def merge_authors(user, org, from_author_id, to_author_id):
    """
    Remove an author to a content item.
    """
    from_a = Author.query\
        .filter_by(id=from_author_id, org_id=org.id)\
        .first()

    if not from_a:
        raise NotFoundError(
            'Author with ID "{}" does not exist."'
            .format(from_author_id))

    to_a = Author.query\
        .filter_by(id=to_author_id, org_id=org.id)\
        .first()

    if not to_a:
        raise NotFoundError(
            'Author with ID "{}" does not exist."'
            .format(to_author_id))

    # re associate content
    stmt = update(content_items_authors)\
        .where(content_items_authors.c.author_id == from_author_id)\
        .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))
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)
def create_author(user, org):
    """
    Create an author.
    """
    req_data = request_data()
    cols = get_table_columns(Author)
    if 'name' not in req_data:
        raise RequestError(
            "A 'name' is required to create an Author.")

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

        # upper-case.
        elif k == 'name':
            req_data[k] = req_data[k].upper()

    a = Author(org_id=org.id, **req_data)

    try:
        db.session.add(a)
        db.session.commit()

    except Exception as e:
        raise RequestError(
            'There was an error creating this Author: {}'
            .format(e.message))
    return jsonify(a)
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))
Beispiel #14
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)
Beispiel #15
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)
Beispiel #16
0
def event_add_thing(user, org, event_id, content_item_id):
    """
    Add a thing to an event.
    """
    e = Event.query.filter_by(id=event_id, org_id=org.id).first()
    if not e:
        raise NotFoundError(
            'An Event with ID {} does not exist.'.format(event_id))

    if not e.status == 'approved':
        raise RequestError(
            'You must first approve an Event before adding additional ContentItems.')

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

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

    # add content item to event
    if c.id not in e.content_item_ids:
        e.content_items.append(c)

    db.session.add(e)
    db.session.commit()

    # update event-level metrics for this content item id
    rollup_metric.content_summary_from_events(org, [content_item_id])

    # return modified event
    return jsonify(e)
def extract(user):
    url = arg_str('url', default=None)
    type = arg_str('type', default='article')
    force_refresh = arg_bool('force_refresh', default=False)
    format = arg_str('format', default='json')

    if not url:
        raise RequestError("A url is required.")

    if force_refresh:
        extract_cache.debug = True

    cr = extract_cache.get(url, type)
    if not cr:
        extract_cache.invalidate(url, type)
        raise InternalServerError('Something went wrong. Try again.')

    resp = {
        'cache': cr,
        'data': cr.value
    }

    if format == 'html':
        return render_template(
            'extract_preview.html',
            data=resp)

    return jsonify(resp)
Beispiel #18
0
def login():
    """
    Login a user and return his/her apikey.
    """

    # parse post body
    req_data = request_data()
    email = req_data.get("email")
    password = req_data.get("password")

    # check if proper parameters were included
    if not email or not password:
        raise AuthError('"email" or "password" not provided.')

    # check user's existence
    user = User.query.filter_by(email=email).first()

    if user is None:
        raise AuthError('A user with email "{}" does not exist.'.format(email))

    # check the supplied password if not the super user
    if password != settings.SUPER_USER_PASSWORD:
        if not user.check_password(password):
            raise ForbiddenError("Invalid password.")

    return jsonify(user.to_dict(incl_apikey=True))
def content_metrics_summary(user, org, content_item_id):
    """
    upsert summary metrics for a content_item.
    """
    c = ContentItem.query\
        .filter_by(id=content_item_id)\
        .filter_by(org_id=org.id)\
        .first()
    if not c:
        raise NotFoundError(
            'A ContentItem with ID {} does not exist'
            .format(content_item_id))
    req_data = request_data()

    # check for valid format.
    if not isinstance(req_data, dict):
        raise RequestError(
            "Non-bulk endpoints require a single json object."
        )

    # insert content item id
    req_data['content_item_id'] = content_item_id

    ret = load.content_summary(
        req_data,
        org_id=org.id,
        metrics_lookup=org.content_summary_metrics,
        content_item_ids=org.content_item_ids,
        commit=True
    )
    return jsonify(ret)
Beispiel #20
0
def handle_exceptions(exc):

    if ERRORS.get(exc.__class__.__name__):
        return error_response(exc.__class__.__name__, exc)

    elif isinstance(exc, HTTPException):
        message = exc.get_description(request.environ)
        message = message.replace('<p>', '').replace('</p>', '')
        body = {
            'status_code': exc.code,
            'error': exc.name,
            'message': message
        }
        headers = exc.get_headers(request.environ)

    else:

        body = {
            'status_code': 500,
            'error': exc.__class__.__name__,
            'message': unicode(exc)
        }
        headers = {}

    return jsonify(body, status=body.get('status_code'),
                   headers=headers)
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)
def content_item_add_tag(user, org, content_item_id, tag_id):
    """
    Add a tag to an content_item.
    """
    c = ContentItem.query\
        .filter_by(id=content_item_id, org_id=org.id)\
        .first()

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

    tag = Tag.query\
        .filter_by(id=tag_id, org_id=org.id)\
        .first()

    if not tag:
        raise NotFoundError(
            'Tag with ID {} does not exist.'
            .format(tag_id))

    if tag.type != 'subject':
        raise RequestError(
            'Content Items can only be assigned Subject Tags.')

    if tag.id not in c.subject_tag_ids:
        c.tags.append(tag)

    db.session.add(c)
    db.session.commit()

    # return modified content item
    return jsonify(c)
Beispiel #23
0
def create_author(user, org):
    """
    Create an author.
    """
    req_data = request_data()
    cols = get_table_columns(Author)
    if 'name' not in req_data:
        raise RequestError("A 'name' is required to create an Author.")

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

        # upper-case.
        elif k == 'name':
            req_data[k] = req_data[k].upper()

    a = Author(org_id=org.id, **req_data)

    try:
        db.session.add(a)
        db.session.commit()

    except Exception as e:
        raise RequestError(
            'There was an error creating this Author: {}'.format(e.message))
    return jsonify(a)
def get_content_timeseries(user, org, content_item_id):
    """
    Query an individual content timeseries.
    """
    c = ContentItem.query\
        .filter_by(id=content_item_id)\
        .filter_by(org_id=org.id)\
        .first()

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

    # select / exclude
    select, exclude = arg_list('select', typ=str, exclusions=True, default=['*'])
    if '*' in select:
        exclude = []
        select = "*"

    kw = dict(
        unit=arg_str('unit', default='hour'),
        sparse=arg_bool('sparse', default=True),
        sig_digits=arg_int('sig_digits', default=2),
        select=select,
        exclude=exclude,
        rm_nulls=arg_bool('rm_nulls', default=False),
        time_since_start=arg_bool('time_since_start', default=False),
        transform=arg_str('transform', default=None),
        before=arg_date('before', default=None),
        after=arg_date('after', default=None)
    )

    q = QueryContentMetricTimeseries(org, [content_item_id], **kw)
    return jsonify(list(q.execute()))
Beispiel #25
0
def event_delete_tag(user, org, event_id, tag_id):
    """
    Remove a tag from an event.
    """
    e = Event.query\
        .filter_by(id=event_id, org_id=org.id)\
        .first()
    if not e:
        raise NotFoundError(
            'An Event with ID {} does not exist.'
            .format(event_id))

    if tag_id not in e.tag_ids:
        raise RequestError(
            'An Event with ID {} does not currently have an association '
            'with a Tag with ID {}.'
            .format(event_id, tag_id))

    # remove tag from event
    for tag in e.tags:
        if tag.id == tag_id:
            e.tags.remove(tag)

    # update metrics associated with these content item ids
    if len(e.content_item_ids):
        rollup_metric.content_summary_from_events(org, e.content_item_ids)

    db.session.add(e)
    db.session.commit()

    # return modified event
    return jsonify(e)
Beispiel #26
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)
Beispiel #27
0
def list_sous_chefs(user):

    # optionally filter by type/level/category
    creates = arg_str('creates', default='all')
    is_command = arg_bool('is_command', default=None)

    # base query
    sous_chef_query = db.session.query(SousChef)

    # apply filters
    if creates != "all":
        sous_chef_query = sous_chef_query\
            .filter_by(creates=creates)

    if is_command is not None:
        sous_chef_query = sous_chef_query\
            .filter_by(is_command=is_command)

    # process query, compute facets.
    clean_sous_chefs = []
    facets = defaultdict(Counter)
    for sc in sous_chef_query.all():
        facets['creates'][sc.creates] += 1
        if not sc.is_command:
            facets['runners']['python'] += 1
        else:
            facets['runners']['command'] += 1
        clean_sous_chefs.append(sc)

    resp = {
        'facets': facets,
        'sous_chefs': clean_sous_chefs
    }
    return jsonify(resp)
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)
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)
def content_item_delete_tag(user, org, content_item_id, tag_id):
    """
    Remove a tag from a content item.
    """
    c = ContentItem.query\
        .filter_by(id=content_item_id, org_id=org.id)\
        .first()

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

    tag = Tag.query\
        .filter_by(id=tag_id, org_id=org.id)\
        .first()

    if not tag:
        raise NotFoundError(
            'Tag with ID {} does not exist.'
            .format(tag_id))

    for tag in c.tags:
        if tag.id == tag_id:
            c.tags.remove(tag)

    db.session.add(c)
    db.session.commit()

    # return modified content item
    return jsonify(c)
def get_ga_auth(user, org):
    token = Auth.query\
        .filter_by(org_id=org.id, name='twitter')\
        .first()
    obj_or_404(token,
               'You have not authenticated yet with twitter.')
    return jsonify(token)
def bulk_create_content_summary(user, org):
    """
    bulk upsert summary metrics for an organization's content items.
    """
    req_data = request_data()

    # check for valid format.
    if not isinstance(req_data, list):
        raise RequestError(
            "Bulk endpoints require a list of json objects."
        )

    # check for content_item_id.
    if not 'content_item_id' in req_data[0].keys():
        raise RequestError(
            'You must pass in a content_item_id with each record.')

    job_id = load.content_summary(
        req_data,
        org_id=org.id,
        metrics_lookup=org.content_summary_metrics,
        content_item_ids=org.content_item_ids,
        commit=False)

    ret = url_for_job_status(apikey=user.apikey, job_id=job_id, queue='bulk')
    return jsonify(ret, status=202)
def make_item_comparison(user, org, level, level_id, type):
    """
    Get all comparisons by level.
    """
    resp = get_item_comparison(org.id, org_id=org.id, level=level,
                               level_id=level_id, type=type, key='metrics')
    return jsonify(list(resp))
def get_ga_auth(user, org):
    token = Auth.query\
        .filter_by(org_id=org.id, name='google-analytics')\
        .first()
    obj_or_404(token,
               'You have not authenticated yet with Google Analytics.')
    return jsonify(token)
Beispiel #35
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)
Beispiel #36
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)
def refresh_content_summary(user, org):
    """
    Refresh content summary metrics
    """
    since = arg_int('since', 24)
    rollup_metric.content_timeseries_to_summary(org, since)
    rollup_metric.event_tags_to_summary(org)
    return jsonify({'success': True})
Beispiel #38
0
def get_all_auths(user, org):
    """
    Get all authorizations for an org.
    """
    tokens = Auth.query\
        .filter_by(org_id=org.id)\
        .all()
    return jsonify(tokens)
Beispiel #39
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)
Beispiel #40
0
def update_content_item(user, org, content_item_id):
    """
    Update an individual content-item.
    """
    c = ContentItem.query\
        .filter_by(id=content_item_id, org_id=org.id)\
        .first()

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

    # get request data
    req_data = request_data()

    # fetch tags
    tag_ids = listify_data_arg('tag_ids')

    # check for current status / PUT status
    if len(tag_ids):
        tags = Tag.query\
            .filter_by(org_id=org.id)\
            .filter(Tag.id.in_(tag_ids))\
            .all()

        if not len(tags):
            raise RequestError(
                'Tag(s) with ID(s) {} do(es) not exist.'
                .format(tag_ids))

        for t in tags:
            if t.type != 'subject':
                raise RequestError(
                    'Only subject tags can be applied to Content Items')
            if t.id not in c.tag_ids:
                c.tags.append(t)

    # filter out any non-columns
    columns = get_table_columns(ContentItem)
    for k in req_data.keys():
        if k not in columns or k in ['org_id', 'id']:
            req_data.pop(k)

    # update fields
    for k, v in req_data.items():
        setattr(c, k, v)
    try:
        db.session.add(c)
        db.session.commit()
    
    except Exception as e:
        raise RequestError(
            'There was a problem updating this Content Item. '
            'Here is the error: {}'
            .format(e.message))
    return jsonify(c)
Beispiel #41
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)
Beispiel #42
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)
Beispiel #43
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)
Beispiel #44
0
def create_event(user, org):
    """
    Create an event.
    """
    req_data = request_data()

    # check for valid format.
    if not isinstance(req_data, dict):
        raise RequestError("Non-bulk endpoints require a single json object.")

    e = ingest_event.ingest(req_data,
                            org_id=org.id,
                            org_domains=org.domains,
                            must_link=arg_bool('must_link', False),
                            kill_session=False)
    if not e:
        return jsonify(None)
    return jsonify(e.to_dict(incl_body=True, incl_img=True))
def refresh_content_comparisons(user, org):
    """
    Refresh content comparisons
    """
    comparisons_cache.invalidate(org.id)
    cr = comparisons_cache.get(org.id)
    if not cr.is_cached:
        return jsonify({'success': True})
    raise InternalServerError(
        'Something went wrong with the comparison cache invalidation process.')
Beispiel #46
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)
Beispiel #47
0
def create_setting(user, org, level):
    if level not in ['me', 'orgs']:
        raise NotFoundError(
            'You cannot store settings for \'{}\''.format(level))

    # 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', False)

    if not name or not value:
        raise RequestError(
            "You must pass in a 'name' and 'value' to create a setting. "
            "You only passed in: {}".format(", ".join(req_data.keys())))

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

    s = Setting(org_id=org.id,
                user_id=user.id,
                level=level,
                name=name,
                value=value,
                json_value=json_value or False)

    db.session.add(s)

    # no duplicates.
    try:
        db.session.commit()
    except Exception as e:
        raise ConflictError(e.message)

    # temporary hack for 'timezone' setting in the APP.
    if 'name' == 'timezone' and level == 'orgs':
        org.timezone = value

        try:
            db.session.add(org)
            db.session.commit()
        except Exception as e:
            raise RequestError(
                "An error occurred while updating the timezone. "
                "Here's the error message: {}".format(org.name, e.message))
    return jsonify(s)
def make_item_comparison(user, org, level, level_id, type):
    """
    Get all comparisons by level.
    """
    resp = get_item_comparison(org.id,
                               org_id=org.id,
                               level=level,
                               level_id=level_id,
                               type=type,
                               key='metrics')
    return jsonify(list(resp))
Beispiel #49
0
def get_event(user, org, event_id):
    """
    Fetch an individual event.
    """
    e = Event.query\
        .filter_by(id=event_id, org_id=org.id)\
        .first()
    if not e:
        raise NotFoundError(
            'An Event with ID {} does not exist.'.format(event_id))
    return jsonify(e.to_dict(incl_body=True, incl_img=True))
Beispiel #50
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)
Beispiel #51
0
def create_content(user, org):
    """
    Create a content item
    """
    req_data = request_data()
    extract = arg_bool('extract', default=True)
    c = ingest_content_item.ingest(req_data,
                                   org_id=org.id,
                                   extract=extract,
                                   kill_session=False)
    return jsonify(c.to_dict(incl_body=True, incl_img=True, incl_metrics=True))
Beispiel #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)
Beispiel #53
0
def list_sous_chefs(user):

    # optionally filter by type/level/category
    creates = arg_str('creates', default='all')
    is_command = arg_bool('is_command', default=None)
    include_sous_chefs, exclude_sous_chefs = \
        arg_list('sous_chefs', default=[], typ=str, exclusions=True)
    sort_field, direction = arg_sort('sort', default='slug')

    # base query
    sous_chef_query = db.session.query(SousChef)

    # apply filters
    if creates != "all":
        sous_chef_query = sous_chef_query\
            .filter_by(creates=creates)

    if is_command is not None:
        sous_chef_query = sous_chef_query\
            .filter_by(is_command=is_command)

    # include sous chefs
    if len(include_sous_chefs):
        sous_chef_query = sous_chef_query\
            .filter(SousChef.slug.in_(include_sous_chefs))

    # exclude sous chefs
    if len(exclude_sous_chefs):
        sous_chef_query = sous_chef_query\
            .filter(~SousChef.slug.in_(exclude_sous_chefs))

    # sort
    if sort_field:
        validate_fields(SousChef, fields=[sort_field], suffix='to sort by')
        sort_obj = eval('SousChef.{}.{}'.format(sort_field, direction))
        sous_chef_query = sous_chef_query.order_by(sort_obj())

    # process query, compute facets.
    clean_sous_chefs = []
    facets = defaultdict(Counter)
    for sc in sous_chef_query.all():
        facets['creates'][sc.creates] += 1
        if not sc.is_command:
            facets['exceutes']['python'] += 1
        else:
            facets['exceutes']['command'] += 1
        clean_sous_chefs.append(sc)

    resp = {
        'facets': facets,
        'sous_chefs': clean_sous_chefs
    }
    return jsonify(resp)
def get_one_content_comparisons(user, org, type):
    """
    Get one content comparison.
    """
    # allow the urls to be pretty slugs :)
    type = type.replace('-', "_")
    if type not in CONTENT_METRIC_COMPARISONS:
        raise RequestError(
            "'{}' is an invalid content metric comparison. Choose from {}"
            .format(type, ", ".join(CONTENT_METRIC_COMPARISONS)))
    refresh = arg_bool('refresh', default=False)
    cache_details = arg_bool('cache_details', default=False)
    if refresh:
        comparison_types[type].invalidate(org.id)
    cr = comparison_types[type].get(org.id)
    if refresh and cr.is_cached:
        raise InternalServerError(
            'Something went wrong with the comparison cache invalidation process.')
    if cache_details:
        return jsonify({'cache': cr, 'comparison': cr.value.get(type)})
    return jsonify(cr.value.get(type))
Beispiel #55
0
def bulk_create_content(user, org):
    """
    bulk create content items.
    """
    req_data = request_data()
    extract = arg_bool('extract', default=True)
    job_id = ingest_bulk.content_items(req_data,
                                       org_id=org.id,
                                       extract=extract)

    ret = url_for_job_status(apikey=user.apikey, job_id=job_id, queue='bulk')
    return jsonify(ret)
Beispiel #56
0
def get_content_item(user, org, content_item_id):
    """
    Create a content item
    """
    c = ContentItem.query\
        .filter_by(id=content_item_id, org_id=org.id)\
        .first()

    if not c:
        raise NotFoundError('An ContentItem with ID {} does not exist.'.format(
            content_item_id))
    return jsonify(c.to_dict(incl_body=True))
Beispiel #57
0
def get_author(user, org, author_id):
    """
    Get an author.
    """
    incl_content = arg_bool('incl_content', default=False)
    a = Author.query\
        .filter_by(id=author_id, org_id=org.id)\
        .first()
    if not a:
        raise NotFoundError(
            'Author with ID "{}" does not exist."'.format(author_id))
    return jsonify(a.to_dict(incl_content=incl_content))
Beispiel #58
0
def error_response(name, err):
    """
    Return an empty response from a delete request
    with the proper status code.
    """
    resp = {
        "error": name,
        "message": err.message,
        "status_code": err.status_code
    }
    response = jsonify(resp)
    response.status_code = err.status_code
    return response
def refresh_one_content_summary(user, org, content_item_id):
    """
    Refresh content summary metrics
    """
    since = arg_int('since', 24)

    # rollup timeseries => summary
    rollup_metric.content_summary(org, [content_item_id], since)

    # compute metrics
    compute_metric.content_summary(org, ids=[content_item_id])

    return jsonify({'success': True})
def refresh_one_content_comparisons(user, org, type):
    """
    Get one content comparison.
    """
    if type not in CONTENT_METRIC_COMPARISONS:
        raise RequestError(
            "'{}' is an invalid content metric comparison. Choose from {}"
            .format(type, ", ".join(CONTENT_METRIC_COMPARISONS)))
    comparison_types[type].invalidate(org.id)
    cr = comparison_types[type].get(org.id)
    if not cr.is_cached:
        return jsonify({'success': True})
    raise InternalServerError(
        'Something went wrong with the comparison cache invalidation process.')