def post_logout(): if not current_user.is_authenticated: response = jsonify(errors={"detail": "You are not logged in.".format(current_user.username)}) response.status_code = 400 return response logout_user() return jsonify(data=None)
def POST(self): attachment = UploadedFile('attachment') form = expenses_add() if not form.validates(): return jsonify(success=False, errors=dict((i.name, i.note) for i in form.inputs if i.note is not None)) else: url = (os.path.join(web.ctx.home, web.ctx.uploadman.add(attachment)) if attachment else None) e = Expense(user_id=self.current_user().id, amount=parsers.amount(form.d.amount), category=form.d.category, note=form.d.note, date=parsers.date_us(form.d.date), attachment=url) web.ctx.orm.add(e) web.ctx.orm.commit() e = web.ctx.orm.merge(e) if not Categories.exists(e.category, self.current_user().id): web.ctx.orm.add( Categories.new(e.category, self.current_user().id)) web.ctx.orm.commit() return jsonify(success=True, expense=ExpenseSerializer( e, self.current_user().currency))
def POST(self): form = expenses_import() if not form.validates(): return jsonify(success=False, errors=dict((i.name, i.note) for i in form.inputs if i.note is not None)) else: expenses = [ Expense(user_id=self.current_user().id, date=date, category=category, amount=amount, note=note) for (date, category, amount, note) in parsers.expenses(form.d.data) ] web.ctx.orm.add_all(expenses) web.ctx.orm.commit() expenses = [web.ctx.orm.merge(e) for e in expenses] return jsonify(success=True, expenses=[ ExpenseSerializer(e, self.current_user().currency) for e in expenses ])
def GET(self, task_id): try: retval = (tasks.ExpensesExportTSVTask.AsyncResult(task_id).get( timeout=1.0)) except celery.exceptions.TimeoutError: return jsonify(success=False, goto=web.ctx.path) else: return jsonify(success=True, goto=retval)
def POST(self): user = self.current_user() connect = users_connect() if not connect.validates(google=(user.google_id is not None), facebook=(user.facebook_id is not None), twitter=(user.twitter_id is not None)): return jsonify(success=False, reason=connect.note) return jsonify(success=True)
def GET(self, task_id): try: retval = (tasks.CategoriesResetTask.AsyncResult(task_id).get( timeout=1.0)) except celery.exceptions.TimeoutError: return jsonify(success=False, goto=web.ctx.path) else: return jsonify(success=True, goto=[CategorySerializer(c) for c in retval])
def delete_user_by_id(id): if current_user.id == id: response = jsonify(errors=[{'detail': "You can't delete yourself."}]) response.status_code = 403 return response Users.query.filter_by(id=id).delete() db.session.commit() response = jsonify() response.status_code = 204 return response
def POST(self): form = expenses_export() if not form.validates(): return jsonify(success=False, errors=dict((i.name, i.note) for i in form.inputs if i.note is not None)) else: task_id = tasks.ExpensesExportTSVTask.delay( web.ctx.exportman, self.current_user()).task_id return jsonify(success=True, goto='/expenses/export/tsv/status/%s' % task_id)
def POST(self, id): attachment = UploadedFile('attachment') form = expenses_edit() if not form.validates(): return jsonify(success=False, errors=dict((i.name, i.note) for i in form.inputs if i.note is not None)) else: url = (os.path.join(web.ctx.home, web.ctx.uploadman.add(attachment)) if attachment else None) e = self.current_item() # Add a new expense being the copy of the current expense before # the edit operations have been applied deleted = Expense(original_id=e.id, user_id=self.current_user().id, amount=e.amount, category=e.category, note=e.note, date=e.date, deleted=True, attachment=e.attachment, created=e.created) # Now apply edit operations on the current expense e.amount = parsers.amount(form.d.amount) e.category = form.d.category e.note = form.d.note e.date = parsers.date_us(form.d.date) if attachment: e.attachment = url # Touch the creation date not to break the algo used to return # categories sorted by the first time they were used e.created = datetime.now() # Bulk add web.ctx.orm.add_all([deleted, e]) web.ctx.orm.commit() e = web.ctx.orm.merge(e) # Add the associated category if not already present if not Categories.exists(e.category, self.current_user().id): web.ctx.orm.add( Categories.new(e.category, self.current_user().id)) web.ctx.orm.commit() return jsonify(success=True, expense=ExpenseSerializer( e, self.current_user().currency))
def test_jsonify(self): # test string r = jsonify(result="Hello") result = self.get_json(r)["result"] nt.assert_equal(result, "Hello") # test iterator r = jsonify(result=iter(["Hello", "World"])) result = self.get_json(r)["result"] nt.assert_equal(result, ["Hello", "World"]) # test date r = jsonify(result=datetime(2015, 1, 15)) result = self.get_json(r)["result"] nt.assert_equal(result, "2015-01-15 00:00:00")
def POST(self, name): form = categories_edit() if not form.validates(): return jsonify(success=False, errors=dict((i.name, i.note) for i in form.inputs if i.note is not None)) else: c = self.current_item() c.foreground = form.d.foreground c.background = form.d.background web.ctx.orm.add(c) web.ctx.orm.commit() c = web.ctx.orm.merge(c) return jsonify(success=True, user=CategorySerializer(c))
def GET(self): d = input_(since=lambda v: parsers.date(v), to=lambda v: parsers.date(v), bins=lambda v: int(v)) torightleg = days_to(d.to) if torightleg(d.since) < d.bins: # TODO add some log here raise web.badrequest() expenses = ( Expenses() .mine(self.current_user().id) .active() .in_between(d.since, d.to) .ordered_by(Expense.date.asc()) .all()) deltadays = torightleg(d.since) + 1 # Take right leg into account daysperbean = deltadays / d.bins dates = list(dates_for_bins(d.since, d.to, d.bins, daysperbean)) days = [{ 'date': date, 'income': 0.0, 'outcome': 0.0 } for date in dates] [ComputeDayAggregate(days[key], group) for key, group in groupby(expenses, key=groupby_bin(dates))] return jsonify( stats=dict( days=[StatByDaySerializer(d, self.current_user().currency) for d in days]))
def github_authorized(): resp = github.authorized_response() if resp is None: return "Access denied: reason=%s error=%s" % (request.args["error"], request.args["error_description"]) session["github_token"] = (resp["access_token"], "") me = github.get("user") return jsonify(me.data)
def lorem(): """Return a random bacon ipsum sentence Return: str: A bacon ipsum sentence """ return jsonify(objects=choice(BACON_IPSUM))
def result(jid): """ Displays a job result. Args: jid (str): The job id. """ job = q.fetch_job(jid) statuses = { 'queued': 202, 'started': 202, 'finished': 200, 'failed': 500, 'job not found': 404, } if job: job_status = job.get_status() result = job.result else: job_status = 'job not found' result = None resp = { 'status': statuses[job_status], 'job_id': jid, 'job_status': job_status, 'result': result } return jsonify(**resp)
def google_authorized(): resp = google.authorized_response() if resp is None: return "Access denied: reason=%s error=%s" % (request.args["error_reason"], request.args["error_description"]) session["google_token"] = (resp["access_token"], "") me = google.get("userinfo") return jsonify({"data": me.data})
def POST(self, id): """Changes one or more properties of the user identified by ``id``. The 'HTTP_ACCEPT' header is required to allow the controller to specify the acceptable media type for the response. There should be a logged-in user behind this request. The specified ``id`` should match the one of the logged-in user. If all these prerequisites hold true then the controller will try to update the logged-in user. On success the controller will return '204 No Content'. On error (e.g. one or more submitted fields are invalid), an object of the specified media format containing error descriptions will be sent back to the caller: { "success": false, "errors": { "currency": "Unknown" } } """ ok, arg = workflows.edit_user(web.ctx.logger, web.input(), Users, id) if not ok: return jsonify(**arg) else: raise _status_code('204 No Content')
def delete(self): """ Removes reports """ result = {} for day in range(self.days): start_date = self.end_date - timedelta(days=day) report_date = start_date.strftime(S3_DATE_FORMAT) _response = remove_report(report_date, **self.kwargs) result[report_date] = {**_response} ok = all(r["ok"] for r in result.values()) if ok: message = f"Successfully deleted data {report_phrase}!" status_code = 200 else: message = f"Error(s) encountered deleting data {report_phrase}!" status_code = 500 response = { "ok": ok, "message": message, "result": result, "status_code": status_code, } return jsonify(**response)
def status(): kwargs = parse_kwargs(app) use_s3 = kwargs.get("source", "s3") == "s3" response = get_status(use_s3=use_s3) response["description"] = "Displays the status of the s3 bucket" response["links"] = get_links(app.url_map.iter_rules()) return jsonify(**response)
def GET(self): since, to, latest = parsedateparams() # Find all the expenses which have been *created* in between `since` and # `to` and *modified* after `latest`. updated = ( LatestExpensesInBetween( self.current_user().id, since, to, latest) .order_by(Expense.category.asc()) .all()) # Of these, extract the categories and look for all the expenses # between `since` and `to` having one of the extracted categories. expenses = [] if not updated else ( ExpensesInBetween(self.current_user().id, since, to) .filter(Expense.category.in_(set(e.category for e in updated))) .order_by(Expense.category.asc()) .all()) # Finally aggretate the amounts and the last modified date categories = [ComputeCategoryAggregate(group) for (key, group) in groupby( expenses, key=attrgetter('category'))] return jsonify( stats=dict( categories=[StatByCategorySerializer(c, self.current_user().currency) for c in categories]))
def result(job_id): """ Displays a job result. Args: job_id (str): The job id. """ job = q.fetch_job(job_id) statuses = { "queued": 202, "started": 202, "finished": 200, "failed": 500, "job not found": 404, } if job: job_status = job.get_status() job_result = job.result else: job_status = "job not found" job_result = {} response = { "status_code": statuses[job_status], "job_id": job_id, "job_status": job_status, "result": job_result, "links": get_links(app.url_map.iter_rules()), } return jsonify(**response)
def get(self): """ Retrieves reports""" result = {} for day in range(self.days): start_date = self.end_date - timedelta(days=day) report_date = start_date.strftime(S3_DATE_FORMAT) _response = load_report(report_date, **self.kwargs) _result = _response.get("result") if _result: result[report_date] = _result if result: message = f"Successfully got data {report_phrase}!" status_code = 200 else: message = f"Error(s) encountered getting data {report_phrase}!" status_code = 500 response = { "ok": bool(result), "message": message, "result": result, "status_code": status_code, } return jsonify(**response)
def put_category_by_id(id): data, _ = update_category_serializer.loads(request.data) Categories.query.filter_by(id=id).update(data['attributes']) db.session.commit() response = jsonify() response.status_code = 204 return response
def lorem(): """Get a random 'bacon ipsum' sentence Return: str: A bacon ipsum sentence """ return jsonify(objects=choice(BACON_IPSUM))
def update(pid=None): """ Updates the database Args: pid (str): Package id of the package to update. """ kwargs = {k: parse(v) for k, v in request.args.to_dict().items()} sync = kwargs.pop('sync', False) whitelist = [ 'CHUNK_SIZE', 'ROW_LIMIT', 'ERR_LIMIT', 'MOCK_FREQ', 'TIMEOUT', 'RESULT_TTL'] with app.app_context(): defaults = { k.lower(): v for k, v in app.config.items() if k in whitelist} opts = defaultdict(int, pid=pid, **defaults) opts.update(kwargs) base = 'http://%(HOST)s:%(PORT)s%(API_URL_PREFIX)s' % app.config endpoint = '%s/age' % base if sync: resp = {'result': utils.update(endpoint, **opts)} else: job = q.enqueue(utils.update, endpoint, **opts) result_url = '%s/result/%s/' % (base, job.id) resp = { 'job_id': job.id, 'job_status': job.get_status(), 'result_url': result_url} return jsonify(**resp)
def post(self): """ Saves reports""" result = {} for day in range(self.days): start_date = self.end_date - timedelta(days=day) report_date = start_date.strftime(S3_DATE_FORMAT) _response = add_report(report_date, **self.kwargs) result[report_date] = {**_response} ok = result and all(r["ok"] for r in result.values()) # TODO: figure out how to find which dates erred report_phrase = get_report_phrase(report_date, **self.kwargs) if ok: message = f"Successfully posted data {report_phrase}!" status_code = 200 elif result: message = f"Error(s) encountered posting data {report_phrase}!" status_code = 500 response = { "ok": ok, "message": message, "result": result, "status_code": status_code, } return jsonify(**response)
def result(jid): """ Displays a job result. Args: jid (str): The job id. """ job = q.fetch_job(jid) statuses = { 'queued': 202, 'started': 202, 'finished': 200, 'failed': 500, 'job not found': 404, } if job: job_status = job.get_status() result = job.result else: job_status = 'job not found' result = None resp = { 'status': statuses[job_status], 'job_id': jid, 'job_status': job_status, 'result': result} return jsonify(**resp)
def home(): response = { "description": "Returns API documentation", "message": "Welcome to the Alegna Commission Calculator API!", "links": sort_links(gen_links()), } return jsonify(**response)
def category(): """Get all eBay categories Kwargs: country (str): eBay country (one of ['US', 'UK'], default: 'US') """ kwargs = {k: parse(v) for k, v in request.args.to_dict().items()} return jsonify(objects=get_categories(**kwargs))
def post_categories(): data, _ = create_category_serializer.loads(request.data) category = Categories(**data['attributes']) db.session.add(category) db.session.commit() response = jsonify(data=read_category_serializer.dump(category).data) response.status_code = 201 return response
def reset(): """Delete all cached urls Return: str: Caches reset """ cache.clear() return jsonify(objects='Caches reset')
def put_user_by_id(id): # Note: only admins can access this endpoint. data, _ = edit_user_admin_serializer.loads(request.data) Users.query.filter_by(id=id).update(data['attributes']) db.session.commit() response = jsonify() response.status_code = 204 return response
def ipsum(): response = { "description": "Displays a random sentence", "links": get_links(app.url_map.iter_rules()), "message": fake.sentence(), } return jsonify(**response)
def home(): response = { "description": "Returns API documentation", "message": "Welcome to the Alegna Commission Calculator API!", "links": get_links(app.url_map.iter_rules()), } return jsonify(**response)
def features(): user_id = None auth = request.authorization if auth: user_id = UserFinder.get_user_id_from_token(auth.password) if user_id is None: raise AuthError() features = FeatureFinder.get_active_features(user_id) return jsonify(dict(active_features=features))
def double(num): """ Displays the double of a given number. Included as an example of the `cache.memoize` decorator. Args: num (int): The number to double. """ resp = {'result': 2 * num} return jsonify(**resp)
def delete(base): """Delete a cached url Args: base (str): The base of the cached url to delete """ url = request.url.replace('delete/', '') cache.delete(url) return jsonify(objects='Key: {} deleted'.format(url))
def delete(resource): """ Deletes the cache of a given resource Args: resource (str): The resource to delete. """ url = request.url.replace('delete/', '') cache.delete(url) return jsonify(result='Key: %s deleted' % url)
def delete_category_by_id(id): data, _ = delete_category_serializer.loads(request.data) if data['id'] != str(id): raise ResourceIDMismatchError(data['id'], id) Categories.query.filter_by(id=id).delete() db.session.commit() response = jsonify() response.status_code = 204 return response
def result(job_id): """ Displays a job result. Args: job_id (str): The job id. """ response = get_job_result_by_id(job_id) response["links"] = get_links(app.url_map.iter_rules()) return jsonify(**response)
def POST(self, id): e = self.current_item() e.deleted = True web.ctx.orm.add(e) web.ctx.orm.commit() e = web.ctx.orm.merge(e) return jsonify(success=True, expense=ExpenseSerializer(e, self.current_user().currency))
def post_users(): data = request.data if not data: response = jsonify(errors=[{ 'detail': 'No JSON body found.' }]) response.status_code = 400 return response if current_user.is_admin: data, errors = create_user_admin_serializer.loads(data) else: data, errors = create_user_serializer.loads(data) user = Users(**data['attributes']) db.session.add(user) db.session.commit() data, errors = edit_user_profile_serializer.dump(user) response = jsonify(data=data) response.status_code = 201 return response
def GET(self): since, to, latest = parsedateparams() expenses = (LatestExpensesInBetween(self.current_user().id, since, to, latest).order_by( Expense.date.desc()).all()) return jsonify(expenses=[ ExpenseSerializer(e, self.current_user().currency) for e in expenses ])
def sub_category(name=None, cid=None): """Get all subcategories of a given eBay category Args: cid (int): eBay category ID, e.g., 267 name (str): eBay category name, e.g., 'Books' Kwargs: country (str): eBay country (one of ['US', 'UK'], default: 'US') """ if not (name or cid): return jsonify(400, objects="Either 'name' or 'id' must be provided") kwargs = {k: parse(v) for k, v in request.args.to_dict().items()} trading = Trading(**kwargs) url = url_for('blueprint.category', _external=True) msg = "Category {} doesn't exist. View {} to see valid categories." if name and not cid: categories = get_categories(**kwargs) lookup = trading.make_lookup(categories) try: cid = lookup[unquote(name.lower())]['id'] except KeyError: pass response = trading.get_hierarchy(cid) if cid else None try: result = trading.parse(response.CategoryArray.Category) except AttributeError: result = msg.format(name, url) status = 404 except TypeError: result = msg.format(cid, url) status = 404 else: status = 200 return jsonify(status, objects=result)
def put_comment_by_id(id): comment = Comments.query.filter_by(id=id).first() if not comment: raise PageNotFoundError() if not current_user.is_admin and comment.userId != current_user.id: raise PermissionDeniedError('edit', 'comment') data, _ = update_comment_serializer.loads(request.data) Comments.query.filter_by(id=id).update(data['attributes']) db.session.commit() response = jsonify() response.status_code = 204 return response
def delete_article_by_id(id): article = Articles.query.filter_by(id=id).first() if not article: raise utils.PageNotFoundError() if not current_user.is_admin and article.authorId != current_user.id: raise utils.PermissionDeniedError('delete', 'article') data, _ = delete_article_serializer.loads(request.data) db.session.delete(article) db.session.commit() response = jsonify() response.status_code = 204 return response
def delete_comment_by_id(id): comment = Comments.query.filter_by(id=id).first() if not comment: raise PageNotFoundError() if not current_user.is_admin and comment.userId != current_user.id: raise PermissionDeniedError('delete', 'comment') data, _ = read_comment_serializer.loads(request.data) db.session.delete(comment) db.session.commit() response = jsonify() response.status_code = 204 return response
def patch_user_by_id(id): if current_user.is_admin: data, errors, = edit_user_admin_serializer.loads(request.data) elif current_user.id != id: raise AdminRequiredError() else: data, errors, = edit_user_profile_serializer.loads(request.data) Users.query.filter_by(id=id).update(data['attributes']) db.session.commit() response = jsonify() response.status_code = 204 return response
def post_login(): if current_user.is_authenticated: response = jsonify(errors={"detail": "You are already login as {}.".format(current_user.username)}) response.status_code = 400 return response data = json.loads(request.data)["data"] emailOrUsername = data["username"] if "@" in emailOrUsername: user = Users.query.filter(Users.email_insensitive == emailOrUsername).first() else: user = Users.query.filter(Users.username_insensitive == emailOrUsername).first() if not user or not user.check_password(data["password"]): response = jsonify(errors={"detail": "Invalid username or password."}) response.status_code = 400 return response else: login_user(user, remember=True) response = jsonify(data=read_user_serializer.dump(user).data) response.status_code = 200 return response
def search(): """Perform an eBay site search Kwargs: q (str): The search term(s) (either this or the 'cid' parameter is required) cid (int): ID of the category to display (either this or the 'q' parameter is required) country (str): eBay country (one of ['US', 'UK'], default: 'US') verb (str): The type of search to perform (one of ['findCompletedItems', 'findItemsAdvanced', 'findItemsByCategory', 'findItemsByKeywords', 'findItemsByProduct', 'findItemsIneBayStores', 'getHistograms'], default: 'findItemsAdvanced') sort_order (str): Sort order (one of ['BestMatch', 'CurrentPriceHighest', 'DistanceNearest', 'EndTimeSoonest', 'PricePlusShippingHighest', 'PricePlusShippingLowest', 'StartTimeNewest'], default: 'EndTimeSoonest') limit (int): Number of results to return (default: 10) page (int): The results page to view (default: 1) """ kwargs = {k: parse(v) for k, v in request.args.to_dict().items()} query = kwargs.pop('q', None) cid = kwargs.pop('cid', None) if query: kwargs.setdefault('keywords', query) if cid: kwargs.setdefault('categoryId', cid) kwargs.setdefault('sortOrder', kwargs.pop('sort_order', 'EndTimeSoonest')) kwargs.setdefault('verb', 'findItemsAdvanced') limit = kwargs.pop('limit', 10) page = kwargs.pop('page', 1) finding = Finding(**kwargs) options = {'paginationInput': {'entriesPerPage': limit, 'pageNumber': page}} options.update(kwargs) try: response = finding.search(options) except ConnectionError as err: result = str(err) status = 500 else: result = finding.parse(response) status = 200 return jsonify(status, objects=result)
def put_article_by_id(id): article = Articles.query.filter_by(id=id).first() if not article: raise utils.PageNotFoundError() if not current_user.is_admin and article.authorId != current_user.id: raise utils.PermissionDeniedError('edit', 'article') data, errors, = update_article_serializer.loads(request.data) Articles.query.filter_by(id=id).update(data['attributes']) db.session.commit() response = jsonify() response.status_code = 204 return response
def status(): """ Displays the current status """ kwargs = {k: parse(v) for k, v in request.args.to_dict().items()} ckan = CKAN(**kwargs) resp = { 'online': True, 'message': 'Service for checking and updating HDX dataset ages.', 'CKAN_instance': ckan.address, 'version': __version__, 'repository': c.REPO } return jsonify(**resp)
def post_articles(): data, _ = create_article_serializer.loads(request.data) article = Articles(**data['attributes']) relationships = data['relationships'] if current_user.is_admin: article.authorId = relationships['author']['id'] else: article.authorId = current_user.id article.categoryId = data['relationships']['category']['id'] db.session.add(article) db.session.commit() response = jsonify(data=create_article_serializer.dump(article).data) response.status_code = 201 return response
def ship(item_id): """Calculate an item's shipping cost Args: item_id (str): ID of item to ship Kwargs: country (str): origin country (one of ['US', 'UK'], default: 'US') dest (str): destination country (see http://www.airlinecodes.co.uk/country.asp for valid codes, default: 'US') code (str): destination postal code (required if 'dest' is 'US') details (bool): include details? (default: False) quantity (int): quantity to ship (default: 1) """ kwargs = {k: parse(v) for k, v in request.args.to_dict().items()} dest = kwargs.pop('dest', 'US') code = kwargs.pop('code', None) details = kwargs.pop('details', None) quantity = kwargs.pop('quantity', None) options = { 'ItemID': item_id, 'MessageID': item_id, 'DestinationCountryCode': dest} if code: options['DestinationPostalCode'] = code if details: options['IncludeDetails'] = details if quantity: options['QuantitySold'] = quantity options.update(kwargs) shopping = Shopping(**kwargs) try: response = shopping.search(options) except ConnectionError as err: result = str(err) status = 500 else: result = shopping.parse(response) status = 200 return jsonify(status, objects=result)
def post_comments(): data, _ = create_comment_serializer.loads(request.data) relationships = data['relationships'] userId = relationships['user']['id'] if not current_user.is_admin and userId != str(current_user.id): raise PermissionDeniedError('create', 'comment') attributes = data['attributes'] attributes['userId'] = userId attributes['articleId'] = relationships['article']['id'] attributes['parentId'] = relationships['comment']['id'] comment = Comments(**attributes) db.session.add(comment) db.session.commit() response = jsonify(data=create_comment_serializer.dump(comment).data) response.status_code = 201 return response