diff --git a/app.py b/app.py index 6a7478b..87c59d5 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,6 @@ from flask import Flask, session, url_for, redirect, render_template, request, abort, flash from database import list_users, verify, delete_user_from_db, add_user +from database import read_note_from_db, write_note_into_db, delete_note_from_db, match_user_id_with_note_id app = Flask(__name__) app.config.from_object('config') @@ -10,6 +11,10 @@ app.config.from_object('config') def FUN_401(error): return render_template("page_401.html"), 401 +@app.errorhandler(403) +def FUN_403(error): + return render_template("page_403.html"), 403 + @app.errorhandler(404) def FUN_404(error): return render_template("page_404.html"), 404 @@ -33,7 +38,12 @@ def FUN_public(): @app.route("/private/") def FUN_private(): if "current_user" in session.keys(): - return render_template("private_page.html") + notes_list = read_note_from_db(session['current_user']) + notes_table = zip([x[0] for x in notes_list],\ + [x[1] for x in notes_list],\ + [x[2] for x in notes_list],\ + ["/delete_note/" + x[0] for x in notes_list]) + return render_template("private_page.html", notes = notes_table) else: return abort(401) @@ -53,6 +63,26 @@ def FUN_admin(): +@app.route("/write_note", methods = ["POST"]) +def FUN_write_note(): + text_to_write = request.form.get("text_note_to_take") + write_note_into_db(session['current_user'], text_to_write) + + return(redirect(url_for("FUN_private"))) + +@app.route("/delete_note/", methods = ["GET"]) +def FUN_delete_note(note_id): + if session.get("current_user", None) == match_user_id_with_note_id(note_id): # Ensure the current user is NOT operating on other users' note. + delete_note_from_db(note_id) + else: + return abort(401) + + return(redirect(url_for("FUN_private"))) + + + + + @app.route("/login", methods = ["POST"]) def FUN_login(): id_submitted = request.form.get("id").upper() diff --git a/database.py b/database.py index 55c50a4..c0966ef 100644 --- a/database.py +++ b/database.py @@ -1,10 +1,12 @@ import sqlite3 import hashlib +import datetime -db_file_location = "database_file/users.db" +user_db_file_location = "database_file/users.db" +note_db_file_location = "database_file/notes.db" def list_users(): - _conn = sqlite3.connect(db_file_location) + _conn = sqlite3.connect(user_db_file_location) _c = _conn.cursor() _c.execute("select id from users;") @@ -15,7 +17,7 @@ def list_users(): return result def verify(id, pw): - _conn = sqlite3.connect(db_file_location) + _conn = sqlite3.connect(user_db_file_location) _c = _conn.cursor() _c.execute("select pw from users where id = '" + id + "';") @@ -26,20 +28,75 @@ def verify(id, pw): return result def delete_user_from_db(id): - _conn = sqlite3.connect(db_file_location) + _conn = sqlite3.connect(user_db_file_location) _c = _conn.cursor() - _c.execute("delete from users where id = '" + id + "';") + _conn.commit() + _conn.close() + # when we delete a user from database USERS, we also need to delete all his or her notes data from database NOTES + _conn = sqlite3.connect(note_db_file_location) + _c = _conn.cursor() + _c.execute("delete from notes where user = '" + id + "';") _conn.commit() _conn.close() def add_user(id, pw): - _conn = sqlite3.connect(db_file_location) + _conn = sqlite3.connect(user_db_file_location) _c = _conn.cursor() command = "insert into users values('" + id.upper() + "', '" + hashlib.sha256(pw).hexdigest() + "');" _c.execute(command) + + _conn.commit() + _conn.close() + +def read_note_from_db(id): + _conn = sqlite3.connect(note_db_file_location) + _c = _conn.cursor() + + command = "select note_id, timestamp, note from notes where user = '" + id.upper() + "';" + _c.execute(command) + result = _c.fetchall() + + _conn.commit() + _conn.close() + + return result + +def match_user_id_with_note_id(note_id): + # Given the note id, confirm if the current user is the owner of the note which is being operated. + _conn = sqlite3.connect(note_db_file_location) + _c = _conn.cursor() + + command = "select user from notes where note_id = '" + note_id + "';" + _c.execute(command) + result = _c.fetchone()[0] + + _conn.commit() + _conn.close() + + return result + +def write_note_into_db(id, note_to_write): + _conn = sqlite3.connect(note_db_file_location) + _c = _conn.cursor() + + current_timestamp = str(datetime.datetime.now()) + command = "insert into notes values('" + id.upper() + "', '" + \ + current_timestamp + "', '" + note_to_write + \ + "', '" + hashlib.sha1(id.upper() + current_timestamp + note_to_write).hexdigest() + "');" + _c.execute(command) + + _conn.commit() + _conn.close() + +def delete_note_from_db(note_id): + _conn = sqlite3.connect(note_db_file_location) + _c = _conn.cursor() + + command = "delete from notes where note_id = '" + note_id + "';" + _c.execute(command) _conn.commit() _conn.close() @@ -47,5 +104,7 @@ def add_user(id, pw): + + if __name__ == "__main__": print list_users() \ No newline at end of file diff --git a/database_file/notes.db b/database_file/notes.db new file mode 100644 index 0000000..4bd9ed2 Binary files /dev/null and b/database_file/notes.db differ diff --git a/database_file/users.db b/database_file/users.db index c5f84de..eecd029 100644 Binary files a/database_file/users.db and b/database_file/users.db differ diff --git a/static/img/private.jpg b/static/img/private.jpg deleted file mode 100644 index e666718..0000000 Binary files a/static/img/private.jpg and /dev/null differ diff --git a/templates/admin.html b/templates/admin.html index 55ec2a1..d16b335 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -5,16 +5,18 @@ {# only invoked when failed adding new ID due to duplication #} {% if id_to_add_is_duplicated %} -
- Warning! The account name already exists. -
+
+ + Warning! The account name already exists. +
{% endif %} {# only invoked when failed adding new ID due to invalid character #} {% if id_to_add_is_invalid %} -
- Warning! The account name is invalid. -
+
+ + Warning! The account name is invalid. +
{% endif %}
@@ -63,10 +65,4 @@
- - - - - - {% endblock %} diff --git a/templates/page_403.html b/templates/page_403.html new file mode 100644 index 0000000..2fecf7f --- /dev/null +++ b/templates/page_403.html @@ -0,0 +1,6 @@ +{% extends "layout.html" %} +{% block page_title %}Forbidden(403){% endblock %} +{% block body %} + {{ super() }} + This operation is forbidden. +{% endblock %} \ No newline at end of file diff --git a/templates/private_page.html b/templates/private_page.html index f1b71c0..7059c95 100644 --- a/templates/private_page.html +++ b/templates/private_page.html @@ -2,6 +2,44 @@ {% block page_title %}Private Page{% endblock %} {% block body %} {{ super() }} - Cinque Terre - Only logged-in users, like you, can access this page. + +

You can take notes here. Only yourself can access them. They will be removed when your account is removed.

+ +
+ +
+ +
+
+ + +
+
+
+ +
+ + {% if notes %} +

Your Notes

+ + + + + + + + + + {% for note_id, timestamp, note, act in notes %} + + + + + + + + {% endfor %} +
Note IDTimestampNoteAction
{{ note_id }} {{ timestamp }} {{ note }} Delete
+ {% endif %} + {% endblock %} \ No newline at end of file