def terminate_manager(): database.get_conn().close() if constants.IS_REMOTE: clean_all_workers() ec2 = aws_helper.session.client("ec2") ec2.stop_instances(InstanceIds=['i-0d92ec486e6faeb22']) sys.exit(4) else: shutdown = request.environ.get("werkzeug.server.shutdown") if not shutdown: flash("Failed to terminate manager app", constants.ERROR) return clean_all_workers() shutdown() return redirect(url_for("manager.display_main_page"))
def show_image(image_id): try: # query image data from the database sql_stmt = ''' SELECT processed_image_path, unprocessed_image_path, thumbnail_image_path, category, num_faces, num_masked, num_unmasked, username FROM image WHERE image_id="{}" '''.format(image_id) db_conn = get_conn() cursor = db_conn.cursor() cursor.execute(sql_stmt) image_record = cursor.fetchone() db_conn.commit() # if not found the image record if not image_record: flash("Couldn't find the image", constants.ERROR) return redirect(url_for("detection.detect")) # prevent unwanted access from other user if image_record[-1] != g.user[constants.USERNAME]: flash("Not allowed to access the image uploaded by other user", constants.ERROR) return redirect(url_for("detection.detect")) # error handling except Exception as e: flash("Unexpected exception {}".format(e), constants.ERROR) return redirect(url_for("detection.detect")) return render_template("detection/show.html", image_record=image_record, category_map=constants.CATEGORY_MAP, is_remote=constants.IS_REMOTE)
def auto_scaler_policy(): policy = get_auto_scaler_policy() if request.method == "POST": with manager.lock: try: expand_ratio = request.form.get("expand_ratio") shrink_ratio = request.form.get("shrink_ratio") grow_threshold = request.form.get("grow_threshold") shrink_threshold = request.form.get("shrink_threshold") is_valid, error = validate_input_policy(policy, expand_ratio, shrink_ratio, grow_threshold, shrink_threshold) if not is_valid: flash(error, constants.ERROR) return redirect(url_for("auto_scaler.auto_scaler_policy")) policy[constants.EXPAND_RATIO] = float(expand_ratio) if expand_ratio else policy[constants.EXPAND_RATIO] policy[constants.SHRINK_RATIO] = float(shrink_ratio) if shrink_ratio else policy[constants.SHRINK_RATIO] policy[constants.CPU_UTIL_GROW_THRESHOLD] = int(grow_threshold) if grow_threshold else policy[constants.CPU_UTIL_GROW_THRESHOLD] policy[constants.CPU_UTIL_SHRINK_THRESHOLD] = int(shrink_threshold) if shrink_threshold else policy[constants.CPU_UTIL_SHRINK_THRESHOLD] db_conn = database.get_conn() cursor = db_conn.cursor() sql_stmt = '''UPDATE policy SET expand_ratio={}, shrink_ratio={}, cpu_util_grow_threshold={}, cpu_util_shrink_threshold={} WHERE policy_id=1'''.format( policy[constants.EXPAND_RATIO], policy[constants.SHRINK_RATIO], policy[constants.CPU_UTIL_GROW_THRESHOLD], policy[constants.CPU_UTIL_SHRINK_THRESHOLD] ) cursor.execute(sql_stmt) db_conn.commit() flash("Successfully updated Auto-Scaler policy", constants.INFO) except Exception as e: flash("Unexpected error, failed to update Auto-Scaler policy, please try again", constants.ERROR) return redirect(url_for("auto_scaler.auto_scaler_policy")) return render_template("auto_scaler.html", policy=policy)
def get_sensor_time_series_data(sensor_id): """Get the time series data in a Pandas DataFrame, for the sensor chosen in the dropdown""" sql = f""" SELECT --Get the 3-hour average instead of every single data point time_bucket('03:00:00'::interval, time) as time, sensor_id, avg(temperature) as temperature, avg(cpu) as cpu FROM sensor_data WHERE sensor_id = {sensor_id} GROUP BY time_bucket('03:00:00'::interval, time), sensor_id ORDER BY time_bucket('03:00:00'::interval, time), sensor_id; """ conn = get_conn() with conn.cursor(cursor_factory=RealDictCursor) as cursor: cursor.execute(sql) rows = cursor.fetchall() columns = [str.lower(x[0]) for x in cursor.description] df = pd.DataFrame(rows, columns=columns) return df
def user_management(): # show a list of user for selection to delete db_conn = get_conn() cursor = db_conn.cursor() sql_stmt = "SELECT username FROM user WHERE role='{}'".format( constants.USER) cursor.execute(sql_stmt) user = [i[0] for i in cursor.fetchall()] db_conn.commit() return render_template("user/user_management.html", users=user)
def get_auto_scaler_policy(): try: db_conn = database.get_conn() cursor = db_conn.cursor() cursor.execute("SELECT expand_ratio, shrink_ratio, cpu_util_grow_threshold, cpu_util_shrink_threshold FROM policy") policy = cursor.fetchone() policy = policy if policy else constants.DEFAULT_POLICY db_conn.commit() return list(policy) except Exception as e: return constants.DEFAULT_POLICY
def password_recovery(): if request.method == "POST": username = request.form.get("username") security_answer = request.form.get("securityanswer") password = request.form.get("password") if not username or not password or not security_answer: flash( "Please provide all the required fields to recover your passwords", constants.ERROR) return redirect(request.url) # make queries to the SQL DB to modify the user record try: db_conn = get_conn() cursor = db_conn.cursor() sql_stmt = "SELECT * FROM user WHERE username='******'".format( username) cursor.execute(sql_stmt) user = cursor.fetchone() if not user: db_conn.commit() flash("No user with username {} exists".format(username), constants.ERROR) return redirect(request.url) # verify the answer if not default if user[constants.MODIFIED_ANSWER] != 0: if not verify_password(user[constants.SECURITY_ANSWER], security_answer): db_conn.commit() flash("Incorrect security answer", constants.ERROR) return redirect(request.url) # change password to one provided new_pwd = encrypt_credentials(password) sql_stmt = "UPDATE user SET password='******' WHERE username='******'".format( new_pwd, username) cursor.execute(sql_stmt) db_conn.commit() except Exception as e: flash("Unexpected error {}".format(e), constants.ERROR) return redirect(request.url) else: flash("Password is reset successfully", constants.INFO) return redirect(url_for("login.login")) return render_template("login/password_recovery.html")
def get_sensor_types(): """Get a list of different types of sensors""" sql = """ --Get the labels and underlying values for the dropdown menu "children" SELECT distinct type as label, type as value FROM sensors; """ conn = get_conn() with conn.cursor(cursor_factory=RealDictCursor) as cursor: cursor.execute(sql) # types is a list of dictionaries that looks like this, for example: # [{'label': 'a', 'value': 'a'}] types = cursor.fetchall() return types
def history(username): try: # query the images for user db_conn = get_conn() cursor = db_conn.cursor() query = '''SELECT user.username, image.category, image.thumbnail_image_path, image.image_id , image.created_at FROM user JOIN image ON user.username = image.username WHERE user.username = "******" Order by image.created_at DESC '''.format(username) cursor.execute(query) images = cursor.fetchall() db_conn.commit() # separate the user images based on the category no_faces_detected = [] all_faces_wear_masks = [] no_faces_wear_masks = [] partial_faces_wear_masks = [] for image in images: if image[1] == constants.NO_FACES_DETECTED: no_faces_detected.append(image) elif image[1] == constants.ALL_FACES_WEAR_MASKS: all_faces_wear_masks.append(image) elif image[1] == constants.NO_FACES_WEAR_MASKS: no_faces_wear_masks.append(image) elif image[1] == constants.PARTIAL_FACES_WEAR_MASKS: partial_faces_wear_masks.append(image) category_map = { "No face detected in image": no_faces_detected, "All faces from image are wearing masks": all_faces_wear_masks, "No faces from image are wearing masks": no_faces_wear_masks, "Only some faces from image are wearing masks": partial_faces_wear_masks } # pass in the image lists to the view return render_template("history/history.html", category_map=category_map, is_remote=constants.IS_REMOTE) except Exception as e: flash("Unexpected error {}".format(e), constants.ERROR) return redirect(request.url)
def get_sensor_locations(type_): """Get a list of different locations of sensors""" sql = f""" --Get the labels and underlying values for the dropdown menu "children" SELECT distinct location as label, location as value FROM sensors WHERE type = '{type_}'; """ conn = get_conn() with conn.cursor(cursor_factory=RealDictCursor) as cursor: cursor.execute(sql) # locations is a list of dictionaries that looks like this, for example: # [{'label': 'floor', 'value': 'floor'}] locations = cursor.fetchall() return locations
def change_password(username): old_password = request.form.get("old_password") new_password = request.form.get("new_password") new_password_confirm = request.form.get("new_password_confirm") if not old_password or not new_password or not new_password_confirm: flash( "Please provide old password, new password and confirm new password", constants.ERROR) return redirect(request.url) if new_password != new_password_confirm: flash( "Please make sure the new password and confirm new password are the same", constants.ERROR) return redirect(request.url) elif new_password == old_password: flash("New password is the same as old password, please change", constants.ERROR) return redirect(request.url) # make queries to the SQL DB to modify the user record try: db_conn = get_conn() cursor = db_conn.cursor() # hash_pwd = generate_hashed_password(old_password) sql_stmt = "SELECT * FROM user WHERE username='******'".format(username) cursor.execute(sql_stmt) user = cursor.fetchone() if not verify_password(user[constants.PASSWORD], old_password): db_conn.commit() flash("Incorrect password", constants.ERROR) return redirect(request.url) new_hash_pwd = encrypt_credentials(new_password) sql_stmt = "UPDATE user SET password='******' WHERE username='******'".format( new_hash_pwd, username) cursor.execute(sql_stmt) db_conn.commit() except Exception as e: flash("Unexpected error {}".format(e), constants.ERROR) return redirect(request.url) else: flash("Password is updated successfully", constants.INFO) return render_template("user/profile.html", username=username)
def remove_app_data(): try: s3 = aws_helper.session.resource('s3') bucket = s3.Bucket(constants.BUCKET_NAME) bucket.objects.all().delete() db_conn = database.get_conn() cursor = db_conn.cursor() sql_script = open("app/static/schema.sql") sql_commands = sql_script.read().split(";") for command in sql_commands: command = command.replace("\n", "") if command: cursor.execute(command) db_conn.commit() except Exception as e: flash("Failed to remove application data, please try again", constants.ERROR) else: flash("Successfully removed application data", constants.INFO) return redirect(url_for("manager.display_main_page"))
def change_security_answer(username): # confirm the input are the same new_securityanswer = request.form.get("new_securityAnswer") new_securityanswer_confirm = request.form.get("new_securityAnswer_confirm") if not new_securityanswer or not new_securityanswer_confirm: flash( "Please provide new security answer and confirm new security answer when making changes", constants.ERROR) return redirect(request.url) if new_securityanswer != new_securityanswer_confirm: flash( "Please make sure the new security answer and confirm new security answer are the same", constants.ERROR) return redirect(request.url) try: new_hash_pwd = encrypt_credentials(new_securityanswer) db_conn = get_conn() cursor = db_conn.cursor() if g.user[constants.MODIFIED_ANSWER]: old_securityanswer = request.form.get("old_securityAnswer") if not old_securityanswer: flash("Please provide old security answer", constants.ERROR) if not verify_password(g.user[constants.SECURITY_ANSWER], old_securityanswer): db_conn.commit() flash("Incorrect security answer", constants.ERROR) return redirect(request.url) sql_stmt = "UPDATE user SET security_answer='{}' WHERE username='******'".format( new_hash_pwd, username) cursor.execute(sql_stmt) sql_stmt = "UPDATE user SET modified_answer='1' WHERE username='******'".format( username) cursor.execute(sql_stmt) db_conn.commit() except Exception as e: flash("Unexpected error {}".format(e), constants.ERROR) return redirect(request.url) else: flash("Security answer is updated successfully", constants.INFO) return redirect(url_for("user.user_profile", username=username))
def load_logged_in_user(): # keep track of requests on CloudWatch with aws_helper.lock: aws_helper.requests_count += 1 # for the image request, we just skip the user info retrieval to avoid overloading DB if request.path.startswith("/static"): return # for normal request, we need to ensure that we have proper user credentials # store username only as we want to hide user credentials from client username = session.get("username") if username is None: g.user = None else: db_conn = get_conn() cursor = db_conn.cursor() cursor.execute( "SELECT * FROM user WHERE username='******'".format(username)) user = cursor.fetchone() g.user = user db_conn.commit()
def delete_user(): db_conn = get_conn() cursor = db_conn.cursor() username = request.form.get("username") try: sql_stmt = "SELECT * FROM user WHERE username='******'".format(username) cursor.execute(sql_stmt) if not cursor.fetchone(): db_conn.commit() flash("No user exist in the database", constants.ERROR) return redirect(url_for("user.user_management")) sql_stmt = "DELETE FROM user WHERE username='******'".format(username) cursor.execute(sql_stmt) # remove all user uploaded images if constants.IS_REMOTE: # remove the images stored in S3 as well s3_client = session.client("s3") response = delete_user_images_s3(s3_client, username) # if there's still something to delete while response.get("IsTruncated"): response = delete_user_images_s3(s3_client, username) else: user_image_folder = constants.USER_FOLDER.format(username) if os.path.exists(user_image_folder): shutil.rmtree(user_image_folder) except ClientError as ce: db_conn.rollback() flash("Failed to delete images in S3", constants.ERROR) return redirect(url_for("user.user_management")) except Exception as e: db_conn.rollback() flash("Unexpected error {}".format(e), constants.ERROR) return redirect(url_for("user.user_management")) else: db_conn.commit() flash("Successfully deleted user with username {}".format(username), constants.INFO) return redirect(url_for("user.user_management"))
def get_sensors(type_, location): """ Get a list of sensor dictionaries from our TimescaleDB database, along with lists of distinct sensor types and locations """ sql = f""" --Get the labels and underlying values for the dropdown menu "children" SELECT location || ' - ' || type as label, id as value FROM sensors WHERE type = '{type_}' and location = '{location}'; """ conn = get_conn() with conn.cursor(cursor_factory=RealDictCursor) as cursor: cursor.execute(sql) # sensors is a list of dictionaries that looks like this, for example: # [{'label': 'floor - a', 'value': 1}] sensors = cursor.fetchall() return sensors
def authenticate(username, password): try: db_conn = get_conn() cursor = db_conn.cursor() # hash_pwd = generate_hashed_password(password) sql_stmt = "SELECT * FROM user WHERE username='******'".format(username) cursor.execute(sql_stmt) user = cursor.fetchone() db_conn.commit() except Exception as e: error = "Unexpected error {}".format(e) else: if user: verified = verify_password(user[constants.PASSWORD], password) error = None if verified else "Incorrect username or password" if not error and verified: session.clear() session["username"] = user[constants.USERNAME] # load logged in user for api case, normally this will be loaded before every request load_logged_in_user() else: error = "User doesn't exist" return error
def work(): response = {"success": False} status_code = HTTPStatus.BAD_REQUEST username = request.form.get("username") password = request.form.get("password") # request validation before doing actual work if not username: response["error"] = { "code": "MissingParameter", "message": "Please provide username in request" } return response, status_code elif not password: response["error"] = { "code": "MissingParameter", "message": "Please provide password in request" } return response, status_code elif username in constants.RESERVED_NAMES: response["error"] = { "code": "ReservedUsername", "message": "The username provided is reserved" } return response, status_code try: # check if the user is registered or not db_conn = get_conn() cursor = db_conn.cursor() sql_stmt = "SELECT * FROM user WHERE username='******' ".format(username) cursor.execute(sql_stmt) if cursor.fetchone() is not None: response["error"] = { "code": "UserAlreadyExists", "message": "Username is already registered" } db_conn.commit() return response, status_code # create new user and insert into DB hashed_pwd = encrypt_credentials(password) hashed_ans = encrypt_credentials("default") insert_stmt = "INSERT INTO user (username, password,role,security_answer) VALUES ('{}', '{}', '{}','{}')".format( username, hashed_pwd, constants.USER, hashed_ans) cursor.execute(insert_stmt) db_conn.commit() # in case of error, report error except Exception as e: status_code = HTTPStatus.INTERNAL_SERVER_ERROR response["error"] = { "code": "ServerError", "message": "Unexpected Server Error {}".format(e) } # otherwise return success message else: status_code = HTTPStatus.OK response["success"] = True # returns response body with the corresponding HTTP status code return response, status_code
def upload_file(file_data): # file directory processing output_info = None output_file_name, image_id = generate_file_name() username = g.user[constants.USERNAME] processed_path = os.path.join(constants.PROCESSED_FOLDER.format(username), output_file_name) original_path = os.path.join(constants.UNPROCESSED_FOLDER.format(username), output_file_name) thumbnail_path = os.path.join(constants.THUMBNAIL_FOLDER.format(username), output_file_name) # make directory if not exist to prevent issue if not os.path.exists(constants.PROCESSED_FOLDER.format(username)): os.makedirs(constants.PROCESSED_FOLDER.format(username)) if not os.path.exists(constants.UNPROCESSED_FOLDER.format(username)): os.makedirs(constants.UNPROCESSED_FOLDER.format(username)) if not os.path.exists(constants.THUMBNAIL_FOLDER.format(username)): os.makedirs(constants.THUMBNAIL_FOLDER.format(username)) try: # store the original file and do the detection open(original_path, "wb").write(file_data) output_info = pytorch_infer.main(original_path, processed_path) image = Image.open(processed_path) image.thumbnail((80, 80)) image.save(thumbnail_path) # for easier switch between local dev and prod usage if constants.IS_REMOTE: paths = { "processed": processed_path, "original": original_path, "thumbnail": thumbnail_path } paths = store_image_s3(paths) processed_path = paths["processed"] original_path = paths["original"] thumbnail_path = paths["thumbnail"] else: processed_path = processed_path[len(constants.STATIC_PREFIX):] original_path = original_path[len(constants.STATIC_PREFIX):] thumbnail_path = thumbnail_path[len(constants.STATIC_PREFIX):] # insert the record into the SQL DB mask_info = extract_mask_info(output_info) sql_stmt = ''' INSERT INTO image (image_id, processed_image_path, unprocessed_image_path, thumbnail_image_path, category, num_faces, num_masked, num_unmasked, username) VALUES ("{}", "{}", "{}", "{}", {}, {}, {}, {}, "{}") '''.format(image_id, processed_path, original_path, thumbnail_path, classify_image_category(mask_info), mask_info.get("num_faces", 0), mask_info.get("num_masked", 0), mask_info.get("num_unmasked", 0), g.user[constants.USERNAME]) db_conn = get_conn() cursor = db_conn.cursor() cursor.execute(sql_stmt) db_conn.commit() except ClientError as ce: error = "Failed to upload file to S3" return error, output_info, None except Exception as e: error = "Unexpected error {}".format(e) return error, output_info, None else: return None, output_info, image_id