def upload_transaction_csv(): """ batch upload the transaction by a csv file """ if request.method == "POST": # parse the csv file f = request.files['csv'] df = pd.read_csv(f) # connect the database session = get_database_client() # update the db for i in range(df.shape[0]): # Check if category is nan if df.category[i] != df.category[i]: category = "" else: category = df.category[i] try: session.execute( """ INSERT INTO fisci.transactions (transaction_id, user_id, shop_name, category, labeled, amount, date) VALUES (now(), %s, %s, %s, %s, %s, %s) """, (df.user_id[i], df.shop_name[i], category, bool(df.labeled[i]), float(df.amount[i]), df.date[i])) except Exception as err: error_response(500, "Error parsing csv. " + str(err)) return {"message": "success"} else: return {"message": "Nothing happened. Please POST the csv file"}
def add_transaction(): """User send transaction details to be uploaded to the database Data is received in json format""" # parse the request data = request.get_json() or {} # check required fields required_fields = ["user_id", "shop_name", "category", "amount", "date"] for f in required_fields: if f not in data: return bad_request("Required field " + f + " is missing") # add labeled field data["labeled"] = len( data["category"]) == 0 # user provided the category or not # connect to db session = get_database_client() # update db try: session.execute( """ INSERT INTO fisci.transactions (transaction_id, user_id, shop_name, category, labeled, amount, date) VALUES (now(), %s, %s, %s, %s, %s, %s); """, (data["user_id"], data["shop_name"], data["category"], data["labeled"], float(data["amount"]), data["date"])) except Exception as err: return error_response(500, "Error in updating the database. " + str(err)) return {"message": "success"}
def get_new_firmware(): ver = request.args.get("ver", default=None) if ver is None or not ver.isdigit(): return bad_request( "Required parameter 'ver' is missing or not an int.") dev_type = request.args.get("dev_type", default=None) if dev_type is None: return bad_request("Required parameter 'dev_type' is missing.") dev_type = dev_type.lower() dev_id = request.args.get("dev_id", default=None) if dev_id is None: return bad_request("Required parameter 'dev_id' is missing.") app.logger.debug("ver: " + ver + ", dev: " + dev_type + " dev_id: " + dev_id) latest_firmware = find_latest_firmware(ver, dev_type) if latest_firmware is None: app.logger.debug("Device already up to date") return error_response(304, "Device already up to date") app.logger.debug("Found firmware version: " + latest_firmware) return send_from_directory( directory=os.path.join(ROOT_DIR, "firmwares"), filename=latest_firmware, as_attachment=True, mimetype="application/octet-stream", attachment_filename=latest_firmware, )
def texts_get(text_no): """Get a text. Note: The body will only be included in the response if the content type is text. .. rubric:: Request :: GET /texts/19680717 HTTP/1.0 .. rubric:: Responses Text exists:: HTTP/1.0 200 OK { "body": "r\u00e4ksm\u00f6rg\u00e5s", "recipient_list": [ { "conf_name": "Oskars Testperson", "type": "to", "loc_no": 29, "conf_no": 14506 } ], "author": { "pers_no": 14506, "pers_name": "Oskars Testperson" }, "creation_time": "2012-05-08 18:36:17", "comment_in_list": [], "content_type": "text/x-kom-basic", "text_no": 19680717, "comment_to_list": [], "subject": "jaha" } Text does not exist:: HTTP/1.0 404 NOT FOUND { TODO: error stuff } .. rubric:: Example :: curl -b cookies.txt -c cookies.txt -v \\ -X GET -H "Content-Type: application/json" \\ http://localhost:5001/texts/19680717 """ try: return jsonify(to_dict(g.ksession.get_text(text_no), True, g.ksession)) except kom.NoSuchText as ex: return error_response(404, kom_error=ex)
def texts_get_body(text_no): """Get the body of text, with the content type of the body set in the HTTP header. Useful for creating img-tags in HTML and specifying this URL as source. If the content type is text, the text will be recoded to UTF-8. For other types, the content type will be left untouched. .. rubric:: Request :: GET /texts/19680717/body HTTP/1.0 .. rubric:: Responses Text exists:: HTTP/1.0 200 OK Content-Type: text/x-kom-basic; charset=utf-8 räksmörgås Text does not exist:: HTTP/1.0 404 NOT FOUND { TODO: error stuff } .. rubric:: Example :: curl -b cookies.txt -c cookies.txt -v \\ -X GET -H "Content-Type: application/json" \\ http://localhost:5001/texts/19680717/body """ try: text = g.ksession.get_text(text_no) mime_type, encoding = parse_content_type(text.content_type) data = StringIO.StringIO() if mime_type[0] == 'text': data.write(text.body.encode('utf-8')) else: data.write(text.body) data.flush() data.seek(0) response = send_file(data, mimetype=text.content_type, as_attachment=False) return response except kom.NoSuchText as ex: return error_response(404, kom_error=ex)
def remove_transaction(transaction_id): """Remove transaction based on transaction_id""" try: session = get_database_client() session.execute( "DELETE FROM fisci.transactions WHERE transaction_id=%s;", (transaction_id, )) except Exception as err: return error_response(500, "Error in deleting the transaction. " + str(err)) return {"message": "success"}
def stats_by_time(user_id): """ Fetch all transactions and sum by time """ # connect the database session = get_database_client() # fetch user data df = fetch_by_user(user_id, session) if type(df) != pd.DataFrame: return error_response(500, "Error fetching transactions. " + df) # sum over time result = df.groupby("date").sum()["amount"] result_list = [{ "date": key, "spending": val } for key, val in dict(result).items()] return {"data": result_list}
def stats_by_category(user_id): """ Fetch all the transactions categorized """ # connect the database session = get_database_client() # fetch user-related transactions df = fetch_by_user(user_id, session) if type(df) != pd.DataFrame: return error_response(500, "Error fetching transactions. " + df) # sum by category result = df.groupby("category").sum()["amount"] result_list = [{ "category": key, "spending": val } for key, val in dict(result).items()] return {"data": result_list}
def conferences_get(conf_no): """Get information about a specific conference. ======= ======= ================================================================= Key Type Values ======= ======= ================================================================= micro boolean :true: (Default) Return micro conference information (`UConference <http://www.lysator.liu.se/lyskom/protocol/11.1/protocol-a.html#Conferences>`_) which causes less load on the server. :false: Return full conference information. ======= ======= ================================================================= .. rubric:: Request :: GET /conferences/14506 HTTP/1.1 .. rubric:: Responses With micro=true:: HTTP/1.0 200 OK { "highest_local_no": 1996, "nice": 77, "type": { "forbid_secret": 0, "allow_anonymous": 1, "rd_prot": 1, "secret": 0, "letterbox": 1, "original": 0, "reserved3": 0, "reserved2": 0 }, "name": "Oskars Testperson", "conf_no": 14506 } With micro=false:: HTTP/1.0 200 OK { "super_conf": { "conf_name": "", "conf_no": 0 }, "creator": { "pers_no": 14506, "pers_name": "Oskars Testperson" }, "no_of_texts": 1977, "no_of_members": 1, "creation_time": "2012-04-28 19:49:11", "permitted_submitters": { "conf_name": "", "conf_no": 0 }, "conf_no": 14506, "last_written": "2012-07-31 00:00:11", "keep_commented": 77, "name": "Oskars Testperson", "type": { "forbid_secret": 0, "allow_anonymous": 1, "rd_prot": 1, "secret": 0, "letterbox": 1, "original": 0, "reserved3": 0, "reserved2": 0 }, "first_local_no": 20, "expire": 0, "msg_of_day": 0, "supervisor": { "conf_name": "Oskars Testperson", "conf_no": 14506 }, "presentation": 0, "nice": 77 } Conference does not exist:: HTTP/1.0 404 NOT FOUND { TODO: error stuff } .. rubric:: Example :: curl -b cookies.txt -c cookies.txt -v \\ -X GET http://localhost:5001/conferences/14506?micro=true """ try: micro = get_bool_arg_with_default(request.args, 'micro', True) return jsonify( to_dict(g.ksession.get_conference(conf_no, micro), True, g.ksession)) except kom.UndefinedConference as ex: return error_response(404, kom_error=ex)
def persons_list(): """Lookup person names. An existing session is not required, but if one exist (i.e. valid cookie) it will be used. Otherwise a new session will be created temporarily for this request. Query parameters: ======= ======= ================================================================= Key Type Values ======= ======= ================================================================= name string Name to look up according to `KOM conventions <http://www.lysator.liu.se/lyskom/protocol/11.1/protocol-a.html#Name%20Expansion>`_. ======= ======= ================================================================= .. rubric:: Request :: GET /persons/?name=Osk%20t HTTP/1.0 .. rubric:: Response :: HTTP/1.0 200 OK { "persons": [ { "pers_no": 13212, "pers_name": "Oskars tredje person" }, { "pers_no": 14506, "pers_name": "Oskars Testperson" } ] } .. rubric:: Example :: curl -b cookies.txt -c cookies.txt -v \\ -X GET -H "Content-Type: application/json" \\ http://localhost:5001/persons/?name=Osk%20t """ name = request.args["name"] if g.ksession: # Use exising session if we have one ksession = g.ksession else: # .. otherwise create a new temporary session ksession = KomSession(_kom_server) ksession.connect() try: lookup = ksession.lookup_name(name, True, False) persons = [dict(pers_no=t[0], pers_name=t[1]) for t in lookup] return jsonify(dict(persons=persons)) except kom.Error as ex: return error_response(400, kom_error=ex) finally: # if we created a new session, close it if not g.ksession: ksession.disconnect()
def sessions_create(): """Create a new session (i.e. login). Note: If the login is successful, the matched full name will be returned in the response. If no client is specified in the request, "httpkom" will be used. .. rubric:: Request :: POST /sessions/ HTTP/1.1 { "person": { "pers_no": 14506 }, "password": "******", "client": { "name": "jskom", "version": "0.2" } } .. rubric:: Responses Successful login:: HTTP/1.0 200 OK Set-Cookie: session_id=033556ee-3e52-423f-9c9a-d85aed7688a1; expires=Sat, 19-May-2012 12:44:51 GMT; Max-Age=604800; Path=/ { "id": "033556ee-3e52-423f-9c9a-d85aed7688a1", "person": { "pers_no": 14506, "pers_name": "Oskars testperson" }, "client": { "name": "jskom", "version": "0.2" } } Failed login:: HTTP/1.1 401 Unauthorized { TODO: error stuff } .. rubric:: Example :: curl -b cookies.txt -c cookies.txt -v \\ -X POST -H "Content-Type: application/json" \\ -d '{ "pers_no": 14506, "password": "******" }' \\ http://localhost:5001/sessions/ """ old_ksession = _get_komsession(_get_session_id()) if old_ksession: # already loggedin, logout first, then try to login with the # supplied credentials. _logout(old_ksession) try: person = request.json['person'] except KeyError as ex: return error_response(400, error_msg='Missing "person".') try: pers_no = person['pers_no'] except KeyError as ex: return error_response(400, error_msg='Missing "pers_no" in "person".') try: password = request.json['password'] except KeyError as ex: return error_response(400, error_msg='Missing "password".') try: if 'client' in request.json and request.json['client'] is not None: ksession = _login(pers_no, password, request.json['client']['name'], request.json['client']['version']) else: ksession = _login(pers_no, password) response = jsonify(to_dict(ksession, True, ksession)) response.set_cookie('session_id', domain=app.config['HTTPKOM_COOKIE_DOMAIN'], value=ksession.id, max_age=7 * 24 * 60 * 60) return response except (kom.InvalidPassword, kom.UndefinedPerson, kom.LoginDisallowed, kom.ConferenceZero) as ex: return error_response(401, kom_error=ex)
def persons_list(): """Lookup person names. An existing session is not required, but if one exist (i.e. valid cookie) it will be used. Otherwise a new session will be created temporarily for this request. Query parameters: ======= ======= ================================================================= Key Type Values ======= ======= ================================================================= name string Name to look up according to `KOM conventions <http://www.lysator.liu.se/lyskom/protocol/11.1/protocol-a.html#Name%20Expansion>`_. ======= ======= ================================================================= .. rubric:: Request :: GET /persons/?name=Osk%20t HTTP/1.0 .. rubric:: Response :: HTTP/1.0 200 OK { "persons": [ { "pers_no": 13212, "pers_name": "Oskars tredje person" }, { "pers_no": 14506, "pers_name": "Oskars Testperson" } ] } .. rubric:: Example :: curl -b cookies.txt -c cookies.txt -v \\ -X GET -H "Content-Type: application/json" \\ http://localhost:5001/persons/?name=Osk%20t """ name = request.args['name'] if g.ksession: # Use exising session if we have one ksession = g.ksession else: # .. otherwise create a new temporary session ksession = KomSession(_kom_server) ksession.connect() try: lookup = ksession.lookup_name(name, True, False) persons = [dict(pers_no=t[0], pers_name=t[1]) for t in lookup] return jsonify(dict(persons=persons)) except kom.Error as ex: return error_response(400, kom_error=ex) finally: # if we created a new session, close it if not g.ksession: ksession.disconnect()
def sessions_create(): """Create a new session (i.e. login). Note: If the login is successful, the matched full name will be returned in the response. If no client is specified in the request, "httpkom" will be used. .. rubric:: Request :: POST /sessions/ HTTP/1.1 { "person": { "pers_no": 14506 }, "password": "******", "client": { "name": "jskom", "version": "0.2" } } .. rubric:: Responses Successful login:: HTTP/1.0 200 OK Set-Cookie: session_id=033556ee-3e52-423f-9c9a-d85aed7688a1; expires=Sat, 19-May-2012 12:44:51 GMT; Max-Age=604800; Path=/ { "id": "033556ee-3e52-423f-9c9a-d85aed7688a1", "person": { "pers_no": 14506, "pers_name": "Oskars testperson" }, "client": { "name": "jskom", "version": "0.2" } } Failed login:: HTTP/1.1 401 Unauthorized { TODO: error stuff } .. rubric:: Example :: curl -b cookies.txt -c cookies.txt -v \\ -X POST -H "Content-Type: application/json" \\ -d '{ "pers_no": 14506, "password": "******" }' \\ http://localhost:5001/sessions/ """ old_ksession = _get_komsession(_get_session_id()) if old_ksession: # already loggedin, logout first, then try to login with the # supplied credentials. _logout(old_ksession) try: person = request.json['person'] except KeyError as ex: return error_response(400, error_msg='Missing "person".') try: pers_no = person['pers_no'] except KeyError as ex: return error_response(400, error_msg='Missing "pers_no" in "person".') try: password = request.json['password'] except KeyError as ex: return error_response(400, error_msg='Missing "password".') try: if 'client' in request.json and request.json['client'] is not None: ksession = _login(pers_no, password, request.json['client']['name'], request.json['client']['version']) else: ksession = _login(pers_no, password) response = jsonify(to_dict(ksession, True, ksession)) response.set_cookie('session_id', domain=app.config['HTTPKOM_COOKIE_DOMAIN'], value=ksession.id, max_age=7*24*60*60) return response except (kom.InvalidPassword, kom.UndefinedPerson, kom.LoginDisallowed, kom.ConferenceZero) as ex: return error_response(401, kom_error=ex)
def conferences_get(conf_no): """Get information about a specific conference. ======= ======= ================================================================= Key Type Values ======= ======= ================================================================= micro boolean :true: (Default) Return micro conference information (`UConference <http://www.lysator.liu.se/lyskom/protocol/11.1/protocol-a.html#Conferences>`_) which causes less load on the server. :false: Return full conference information. ======= ======= ================================================================= .. rubric:: Request :: GET /conferences/14506 HTTP/1.1 .. rubric:: Responses With micro=true:: HTTP/1.0 200 OK { "highest_local_no": 1996, "nice": 77, "type": { "forbid_secret": 0, "allow_anonymous": 1, "rd_prot": 1, "secret": 0, "letterbox": 1, "original": 0, "reserved3": 0, "reserved2": 0 }, "name": "Oskars Testperson", "conf_no": 14506 } With micro=false:: HTTP/1.0 200 OK { "super_conf": { "conf_name": "", "conf_no": 0 }, "creator": { "pers_no": 14506, "pers_name": "Oskars Testperson" }, "no_of_texts": 1977, "no_of_members": 1, "creation_time": "2012-04-28 19:49:11", "permitted_submitters": { "conf_name": "", "conf_no": 0 }, "conf_no": 14506, "last_written": "2012-07-31 00:00:11", "keep_commented": 77, "name": "Oskars Testperson", "type": { "forbid_secret": 0, "allow_anonymous": 1, "rd_prot": 1, "secret": 0, "letterbox": 1, "original": 0, "reserved3": 0, "reserved2": 0 }, "first_local_no": 20, "expire": 0, "msg_of_day": 0, "supervisor": { "conf_name": "Oskars Testperson", "conf_no": 14506 }, "presentation": 0, "nice": 77 } Conference does not exist:: HTTP/1.0 404 NOT FOUND { TODO: error stuff } .. rubric:: Example :: curl -b cookies.txt -c cookies.txt -v \\ -X GET http://localhost:5001/conferences/14506?micro=true """ try: micro = get_bool_arg_with_default(request.args, 'micro', True) return jsonify(to_dict(g.ksession.get_conference(conf_no, micro), True, g.ksession)) except kom.UndefinedConference as ex: return error_response(404, kom_error=ex)