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)
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)
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)
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))
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)
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))
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))
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)
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)
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)
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)
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)
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()))
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)
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)
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)
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)
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})
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)
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 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)
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)
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)
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)
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.')
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)
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 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))
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)
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))
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)
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))
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)
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))
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))
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.')