def post(self): """ Attempts to log in to the OECI web site using the provided username and password if successful, encrypt those credentials and return them in a cookie. If the credentials """ data = request.get_json() if data is None: error(400, "No json data in request body") check_data_fields(data, ["oeci_username", "oeci_password"]) credentials = {"oeci_username": data["oeci_username"], "oeci_password": data["oeci_password"]} crawler_session = requests.Session() try: Crawler.attempt_login(crawler_session, credentials["oeci_username"], credentials["oeci_password"]) except InvalidOECIUsernamePassword as e: error(401, str(e)) except OECIUnavailable as e: error(404, str(e)) finally: crawler_session.close() cipher = DataCipher(key=current_app.config.get("SECRET_KEY")) encrypted_credentials = cipher.encrypt(credentials) response = make_response() # TODO: We will need an OECILogout endpoint to remove httponly=true cookies from frontend response.set_cookie( "oeci_token", secure=os.getenv("TIER") == "production", httponly=False, samesite="strict", expires=time.time() + 2 * 60 * 60, # type: ignore # 2 hour lifetime value=encrypted_credentials, ) return response, 201
def post(self): request_data = request.get_json() if request_data is None: error(400, "No json data in request body") check_data_fields( request_data, ["first_name", "last_name", "middle_name", "birth_date"]) cipher = DataCipher(key=current_app.config.get("SECRET_KEY")) decrypted_credentials = cipher.decrypt(request.cookies["oeci_token"]) login_result = (decrypted_credentials["oeci_username"] == "username" and decrypted_credentials["oeci_password"] == "password") if login_result is False: error(401, "Attempted login to OECI failed") record = build_record() response_data = {"data": {"record": record}} current_app.json_encoder = ExpungeModelEncoder return response_data # Json-encoding happens automatically here
def post(self): request_data = request.get_json() if request_data is None or not request_data.get("aliases"): error(400, "No json data in request body") check_data_fields(request_data, ["aliases"]) for alias in request_data["aliases"]: check_data_fields( alias, ["first_name", "last_name", "middle_name", "birth_date"]) cipher = DataCipher(key=current_app.config.get("SECRET_KEY")) if not "oeci_token" in request.cookies.keys(): error(401, "Missing login credentials to OECI.") decrypted_credentials = cipher.decrypt(request.cookies["oeci_token"]) username, password = decrypted_credentials[ "oeci_username"], decrypted_credentials["oeci_password"] record, ambiguous_record, questions = RecordCreator.build_record( username, password, request_data["aliases"]) if questions: session["ambiguous_record"] = pickle.dumps(ambiguous_record) try: save_result(request_data, record) except Exception as ex: logging.error("Saving search result failed with exception: %s" % ex, stack_info=True) record_summary = RecordSummarizer.summarize(record, questions) response_data = {"data": {"record": record_summary}} encoded_response = json.dumps(response_data, cls=ExpungeModelEncoder) return encoded_response
def post(self): data = request.get_json() if data is None: error(400, "No json data in request body") check_data_fields(data, ["email", "password"]) user_db_result = user_db_util.read( g.database, user_db_util.identify_by_email(g.database, data["email"])) if not user_db_result or not check_password_hash( user_db_result["hashed_password"], data["password"]): error(401, "Invalid username or password") user = from_dict(data_class=User, data=user_db_result) User.login_user(user) response = make_response() if user.admin: response.set_cookie( "is_admin", expires=time.time() + 365 * 24 * 60 * 60, # type: ignore # 1 year lifetime matches flask login cookie ) return response, 200
def post(self): """ Attempts to log in to the OECI web site using the provided username and password if successful, encrypt those credentials and return them in a cookie. If the credentials """ data = request.get_json() if data is None: error(400, "No json data in request body") check_data_fields(data, ["oeci_username", "oeci_password"]) credentials = {"oeci_username": data["oeci_username"], "oeci_password": data["oeci_password"]} cipher = DataCipher(key=current_app.config.get("SECRET_KEY")) encrypted_credentials = cipher.encrypt(credentials) response = make_response() # TODO: We will need an OECILogout endpoint to remove httponly=true cookies from frontend response.set_cookie( "oeci_token", secure=os.getenv("TIER") == "production", httponly=False, samesite="strict", expires=time.time() + 15 * 60, # 15 minutes value=encrypted_credentials, ) return response, 201
def post(self): request_data = request.get_json() if request_data is None or not request_data.get("names"): error(400, "No json data in request body") for alias in request_data["names"]: check_data_fields( alias, ["first_name", "last_name", "middle_name", "birth_date"]) cipher = DataCipher(key=current_app.config.get("SECRET_KEY")) if not "oeci_token" in request.cookies.keys(): error(401, "Missing login credentials to OECI.") decrypted_credentials = cipher.decrypt(request.cookies["oeci_token"]) crawler = Crawler() login_result = crawler.login(decrypted_credentials["oeci_username"], decrypted_credentials["oeci_password"], close_session=False) if login_result is False: error(401, "Attempted login to OECI failed") cases: List[Case] = [] for alias in request_data["names"]: cases += crawler.search( alias["first_name"], alias["last_name"], alias["middle_name"], alias["birth_date"], ).cases cases_with_unique_case_number = [ list(group)[0] for key, group in groupby(cases, lambda case: case.case_number) ] record = Record(cases_with_unique_case_number) expunger = Expunger(record) expunger.run() try: save_result(request_data, record) except Exception as ex: logging.error("Saving search result failed with exception: %s" % ex, stack_info=True) record_summary = RecordSummarizer.summarize(record) response_data = {"data": {"record": record_summary}} current_app.json_encoder = ExpungeModelEncoder return response_data # Json-encoding happens automatically here
def post(self): data = request.get_json() if data is None: error(400, "No json data in request body") check_data_fields(data, ["email", "password"]) user_db_result = user_db_util.read(g.database, user_db_util.identify_by_email(g.database, data["email"])) if not user_db_result or not check_password_hash(user_db_result["hashed_password"], data["password"]): error(401, "Invalid username or password") user = from_dict(data_class=User, data=user_db_result) User.login_user(user) return jsonify({})
def post(self): """ Create a new user with provided email, password, and admin flag. - If required fields are missing in the request, return 400 - Password must be 8 or more characters long. Otherwise return 422 - Email must not already be in use by an existing user. Otherwise return 422 - If success, return 201 with the new user's email, admin flag, and creation timestamp. """ data = request.get_json() if data is None: error(400, "No json data in request body") check_data_fields(data, ["email", "name", "group_name", "password", "admin"]) if len(data["password"]) < 8: error(422, "New password is less than 8 characters long!") password_hash = generate_password_hash(data["password"]) try: create_user_result = user_db_util.create( g.database, email=data["email"], name=data["name"], group_name=data["group_name"], password_hash=password_hash, admin=data["admin"], ) except UniqueViolation: error(422, "User with that email address already exists") response_data = { "user_id": create_user_result["user_id"], "email": create_user_result["email"], "admin": create_user_result["admin"], "name": create_user_result["name"], "group_name": create_user_result["group_name"], "timestamp": create_user_result["date_created"], } return jsonify(response_data), 201
def post(self): request_data = request.get_json() if request_data is None: error(400, "No json data in request body") check_data_fields( request_data, ["first_name", "last_name", "middle_name", "birth_date"]) cipher = DataCipher(key=current_app.config.get("SECRET_KEY")) if not "oeci_token" in request.cookies.keys(): error(401, "Missing login credentials to OECI.") decrypted_credentials = cipher.decrypt(request.cookies["oeci_token"]) crawler = Crawler() login_result = crawler.login(decrypted_credentials["oeci_username"], decrypted_credentials["oeci_password"], close_session=False) if login_result is False: error(401, "Attempted login to OECI failed") record = crawler.search(request_data["first_name"], request_data["last_name"], request_data["middle_name"], request_data["birth_date"]) expunger = Expunger(record) expunger.run() try: save_result(request_data, record) except Exception as ex: logging.error("Saving search result failed with exception: %s" % ex, stack_info=True) response_data = {"data": {"record": record}} current_app.json_encoder = ExpungeModelEncoder return response_data #Json-encoding happens automatically here
def post(self): """ Create a new user with provided email, password, and admin flag. - If required fields are missing in the request, return 400 - Password must be 8 or more characters long. Otherwise return 422 - Email must not already be in use by an existing user. Otherwise return 422 - If success, return 201 with the new user's email, admin flag, and creation timestamp. """ data = request.get_json() if data is None: error(400, "No json data in request body") # print("data received by Users.post():", data) check_data_fields(data, ['email', 'name', 'group_name', 'password', 'admin']) if len(data['password']) < 8: error(422, 'New password is less than 8 characters long!') password_hash = generate_password_hash(data['password']) try: create_user_result = user.create(g.database, email=data['email'], name=data['name'], group_name=data['group_name'], password_hash=password_hash, admin=data['admin']) except UniqueViolation: error(422, 'User with that email address already exists') response_data = { 'email': create_user_result['email'], 'admin': create_user_result['admin'], 'timestamp': create_user_result['date_created'], } # user_id is not required by the frontend here so it is not included. # other endpoints may expose the user_id e.g. for other admin # user-management operations. return jsonify(response_data), 201
def post(self): data = request.get_json() if data == None: error(400, "No json data in request body") check_data_fields(data, ['email', 'password']) user_db_result = get_user_by_email(g.database, data['email']) if (not user_db_result or not check_password_hash(user_db_result['hashed_password'], data['password'])): error(401, 'Invalid username or password') response_data = { 'auth_token': get_auth_token(current_app, user_db_result['user_id']) } return jsonify(response_data)
def post(self): request_data = request.get_json() if request_data is None or not request_data.get("names"): error(400, "No json data in request body") for alias in request_data["names"]: check_data_fields( alias, ["first_name", "last_name", "middle_name", "birth_date"]) record = build_record() record_summary = RecordSummarizer.summarize(record) response_data = {"data": {"record": record_summary}} current_app.json_encoder = ExpungeModelEncoder return response_data # Json-encoding happens automatically here
def post(self): """ Attempts to log in to the OECI web site using the provided username and password if successful, encrypt those credentials and return them in a cookie. If the credentials """ data = request.get_json() if data is None: error(400, "No json data in request body") check_data_fields(data, ["oeci_username", "oeci_password"]) credentials = { "oeci_username": data["oeci_username"], "oeci_password": data["oeci_password"] } login_result = (data["oeci_username"] == "username" and data["oeci_password"] == "password") if not login_result: error(401, "Invalid OECI username or password.") cipher = DataCipher(key=current_app.config.get("JWT_SECRET_KEY")) encrypted_credentials = cipher.encrypt(credentials) response = make_response() response.set_cookie( "oeci_token", # currently nginx/flask app are running as HTTP # secure=True requires HTTPS to maintain secure cookies # https://resources.infosecinstitute.com/securing-cookies-httponly-secure-flags/#gref # We will need an OECILogout endpoint to remove httponly=true cookies from frontend secure=False, httponly=False, samesite="strict", expires=time.time() + 15 * 60, # 15 minutes value=encrypted_credentials) return response, 201
def post(self): request_data = request.get_json() if request_data is None: error(400, "No json data in request body") check_data_fields(request_data, ["first_name", "last_name", "middle_name", "birth_date"]) cipher = DataCipher( key=current_app.config.get("JWT_SECRET_KEY")) decrypted_credentials = cipher.decrypt(request.cookies["oeci_token"]) crawler = Crawler() login_result = crawler.login( decrypted_credentials["oeci_username"], decrypted_credentials["oeci_password"], close_session=False) if login_result is False: error(401, "Attempted login to OECI failed") record = crawler.search( request_data["first_name"], request_data["last_name"], request_data["middle_name"], request_data["birth_date"]) expunger = Expunger(record) expunger.run() response_data = { "data": { "record": record } } current_app.json_encoder = ExpungeModelEncoder return response_data #Json-encoding happens automatically here
def post(self): """ Attempts to log in to the OECI web site using the provided username and password if successful, encrypt those credentials and return them in a cookie. If the credentials """ data = request.get_json() if data is None: error(400, "No json data in request body") check_data_fields(data, ["oeci_username", "oeci_password"]) credentials = {"oeci_username": data["oeci_username"], "oeci_password": data["oeci_password"]} login_result = Crawler().login( credentials["oeci_username"], credentials["oeci_password"], close_session=True) if not login_result: error(401, "Invalid OECI username or password.") cipher = DataCipher( key=current_app.config.get("JWT_SECRET_KEY")) encrypted_credentials = cipher.encrypt(credentials) response = make_response() response.set_cookie( "oeci_token", secure=True, httponly=True, samesite="strict", expires=time.time() + 15 * 60, # 15 minutes value=encrypted_credentials) return response, 201
def _validate_request(request_data): check_data_fields(request_data, ["aliases"]) for alias in request_data["aliases"]: check_data_fields(alias, ["first_name", "last_name", "middle_name", "birth_date"])
def post(self): request_data = request.get_json() if request_data is None: error(400, "No json data in request body") check_data_fields( request_data, ["first_name", "last_name", "middle_name", "birth_date"]) cipher = DataCipher(key=current_app.config.get("JWT_SECRET_KEY")) decrypted_credentials = cipher.decrypt(request.cookies["oeci_token"]) crawler = Crawler() login_result = (decrypted_credentials["oeci_username"] == "username" and decrypted_credentials["oeci_password"] == "password") if login_result is False: error(401, "Attempted login to OECI failed") response_data = json.loads("""{"data": {"record": { "total_balance_due": 4550.4, "cases": [ { "name": "Doe, John D", "birth_year": 1943, "case_number": "X0001", "citation_number": "C0001", "location": "Multnomah", "date": "Sat, 23 Mar 1963 00:00:00 GMT", "violation_type": "Offense Misdemeanor", "current_status": "Closed", "charges": [ { "name": "Driving Uninsured", "statute": "806010", "level": "Class B Felony", "date": "Sun, 12 Mar 2017 00:00:00 GMT", "disposition": { "date": "Mon, 12 Jun 2017 00:00:00 GMT", "ruling": "Convicted - Failure to Appear" }, "expungement_result": { "type_eligibility": false, "type_eligibility_reason": "Ineligible under 137.225(5)", "time_eligibility": null, "time_eligibility_reason": null, "date_of_eligibility": null } }, { "name": "Violation Driving While Suspended or Revoked", "statute": "811175", "level": "Class B Felony", "date": "Sun, 12 Mar 2017 00:00:00 GMT", "disposition": { "date": "Mon, 12 Jun 2017 00:00:00 GMT", "ruling": "Dismissed" }, "expungement_result": { "type_eligibility": true, "type_eligibility_reason": "Eligible under 137.225(1)(b)", "time_eligibility": null, "time_eligibility_reason": null, "date_of_eligibility": null } }, { "name": "Failure to Obey Traffic Control Device", "statute": "811265", "level": "Class B Felony", "date": "Sun, 12 Mar 2017 00:00:00 GMT", "disposition": { "date": "Mon, 12 Jun 2017 00:00:00 GMT", "ruling": "Dismissed" }, "expungement_result": { "type_eligibility": true, "type_eligibility_reason": "Eligible under 137.225(1)(b)", "time_eligibility": null, "time_eligibility_reason": null, "date_of_eligibility": null } } ], "balance_due": 1516.8, "case_detail_link": "https://publicaccess.courts.oregon.gov/PublicAccessLogin/CaseDetail.aspx?CaseID=X0001" }, { "name": "Doe, John D", "birth_year": 1943, "case_number": "X0002", "citation_number": "C0002", "location": "Multnomah", "date": "Thu, 11 Apr 1963 00:00:00 GMT", "violation_type": "Offense Felony", "current_status": "Closed", "charges": [ { "name": "Driving Uninsured", "statute": "806010", "level": "Class B Felony", "date": "Sun, 12 Mar 2017 00:00:00 GMT", "disposition": { "date": "Mon, 12 Jun 2017 00:00:00 GMT", "ruling": "Convicted - Failure to Appear" }, "expungement_result": { "type_eligibility": false, "type_eligibility_reason": "Ineligible under 137.225(5)", "time_eligibility": null, "time_eligibility_reason": null, "date_of_eligibility": null } }, { "name": "Violation Driving While Suspended or Revoked", "statute": "811175", "level": "Class B Felony", "date": "Sun, 12 Mar 2017 00:00:00 GMT", "disposition": { "date": "Mon, 12 Jun 2017 00:00:00 GMT", "ruling": "Dismissed" }, "expungement_result": { "type_eligibility": true, "type_eligibility_reason": "Eligible under 137.225(1)(b)", "time_eligibility": null, "time_eligibility_reason": null, "date_of_eligibility": null } }, { "name": "Failure to Obey Traffic Control Device", "statute": "811265", "level": "Class B Felony", "date": "Sun, 12 Mar 2017 00:00:00 GMT", "disposition": { "date": "Mon, 12 Jun 2017 00:00:00 GMT", "ruling": "Dismissed" }, "expungement_result": { "type_eligibility": true, "type_eligibility_reason": "Eligible under 137.225(1)(b)", "time_eligibility": null, "time_eligibility_reason": null, "date_of_eligibility": null } } ], "balance_due": 1516.8, "case_detail_link": "https://publicaccess.courts.oregon.gov/PublicAccessLogin/CaseDetail.aspx?CaseID=X0002" }, { "name": "Doe, John D", "birth_year": 1943, "case_number": "X0003", "citation_number": "", "location": "Multnomah", "date": "Sun, 01 Apr 2012 00:00:00 GMT", "violation_type": "Offense Misdemeanor", "current_status": "Closed", "charges": [ { "name": "Driving Uninsured", "statute": "806010", "level": "Class B Felony", "date": "Sun, 12 Mar 2017 00:00:00 GMT", "disposition": { "date": "Mon, 12 Jun 2017 00:00:00 GMT", "ruling": "Convicted - Failure to Appear" }, "expungement_result": { "type_eligibility": false, "type_eligibility_reason": "Ineligible under 137.225(5)", "time_eligibility": null, "time_eligibility_reason": null, "date_of_eligibility": null } }, { "name": "Violation Driving While Suspended or Revoked", "statute": "811175", "level": "Class B Felony", "date": "Sun, 12 Mar 2017 00:00:00 GMT", "disposition": { "date": "Mon, 12 Jun 2017 00:00:00 GMT", "ruling": "Dismissed" }, "expungement_result": { "type_eligibility": true, "type_eligibility_reason": "Eligible under 137.225(1)(b)", "time_eligibility": null, "time_eligibility_reason": null, "date_of_eligibility": null } }, { "name": "Failure to Obey Traffic Control Device", "statute": "811265", "level": "Class B Felony", "date": "Sun, 12 Mar 2017 00:00:00 GMT", "disposition": { "date": "Mon, 12 Jun 2017 00:00:00 GMT", "ruling": "Dismissed" }, "expungement_result": { "type_eligibility": true, "type_eligibility_reason": "Eligible under 137.225(1)(b)", "time_eligibility": null, "time_eligibility_reason": null, "date_of_eligibility": null } } ], "balance_due": 1516.8, "case_detail_link": "https://publicaccess.courts.oregon.gov/PublicAccessLogin/CaseDetail.aspx?CaseID=X0003" } ], "errors": [] } }}""") return response_data #Json-encoding happens automatically here