diff --git a/data/boards.csv b/data/boards.csv deleted file mode 100644 index b8d2ca77..00000000 --- a/data/boards.csv +++ /dev/null @@ -1,3 +0,0 @@ -id,title -1,"Board 1" -2,"Board 2" diff --git a/data/cards.csv b/data/cards.csv deleted file mode 100644 index 02d8e81f..00000000 --- a/data/cards.csv +++ /dev/null @@ -1,13 +0,0 @@ -id,board_id,title,status_id,order -1,1,"new card 1",0,0 -2,1,"new card 2",0,1 -3,1,"in progress card",1,0 -4,1,"planning",2,0 -5,1,"done card 1",3,0 -6,1,"done card 1",3,1 -7,2,"new card 1",0,0 -8,2,"new card 2",0,1 -9,2,"in progress card",1,0 -10,2,"planning",2,0 -11,2,"done card 1",3,0 -12,2,"done card 1",3,1 diff --git a/data/statuses.csv b/data/statuses.csv deleted file mode 100644 index d027decd..00000000 --- a/data/statuses.csv +++ /dev/null @@ -1,5 +0,0 @@ -id,title -0,new -1,"in progress" -2,testing -3,done diff --git a/data_manager/__init__.py b/data_manager/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/data_manager/data_manager_operations.py b/data_manager/data_manager_operations.py new file mode 100644 index 00000000..8986e7ee --- /dev/null +++ b/data_manager/data_manager_operations.py @@ -0,0 +1,58 @@ +import db_connection +import bcrypt + + +def register(data): + credentials = (data["username"], data["email"], hash_password(data['password'])) + sql_query = """INSERT INTO credentials(user_login, user_email, user_password) + VALUES (%s, %s, %s);""" + db_connection.sql_data(sql_query, "write", credentials) + + +def verify_login(data): + sql_query = """SELECT user_login, user_password FROM credentials WHERE user_login = %s""" + login_and_password = db_connection.sql_data(sql_query, "read", (data["username"],)) + if login_and_password: + if verify_password(data["password"], login_and_password[0]["user_password"]): + return 0 + return 1 + return 1 + + + sql_query = """SELECT user_id FROM credentials WHERE user_login = %s""" + user_id = db_connection.sql_data(sql_query, "read", (username, )) + return user_id + + +def hash_password(plain_text_password): + # By using bcrypt, the salt is saved into the hash itself + hashed_bytes = bcrypt.hashpw(plain_text_password.encode('utf-8'), bcrypt.gensalt()) + return hashed_bytes.decode('utf-8') + + +def verify_password(plain_text_password, hashed_password): + hashed_bytes_password = hashed_password.encode('utf-8') + return bcrypt.checkpw(plain_text_password.encode('utf-8'), hashed_bytes_password) + + +def verify_credentials(data): + if verify_username(data["username"]): + return "username taken" + if verify_email(data["email"]): + return "email taken" + + +def verify_username(data): + sql_query = """SELECT user_id FROM credentials WHERE user_login = %s""" + login_check = db_connection.sql_data(sql_query, "read", (data,)) + if login_check: + return "login taken" + return None + + +def verify_email(data): + sql_query = """SELECT user_id FROM credentials WHERE user_email = %s""" + email_check = db_connection.sql_data(sql_query, "read", (data,)) + if email_check: + return "email taken" + return None \ No newline at end of file diff --git a/data_manager/data_manager_user_operations.py b/data_manager/data_manager_user_operations.py new file mode 100644 index 00000000..8986e7ee --- /dev/null +++ b/data_manager/data_manager_user_operations.py @@ -0,0 +1,58 @@ +import db_connection +import bcrypt + + +def register(data): + credentials = (data["username"], data["email"], hash_password(data['password'])) + sql_query = """INSERT INTO credentials(user_login, user_email, user_password) + VALUES (%s, %s, %s);""" + db_connection.sql_data(sql_query, "write", credentials) + + +def verify_login(data): + sql_query = """SELECT user_login, user_password FROM credentials WHERE user_login = %s""" + login_and_password = db_connection.sql_data(sql_query, "read", (data["username"],)) + if login_and_password: + if verify_password(data["password"], login_and_password[0]["user_password"]): + return 0 + return 1 + return 1 + + + sql_query = """SELECT user_id FROM credentials WHERE user_login = %s""" + user_id = db_connection.sql_data(sql_query, "read", (username, )) + return user_id + + +def hash_password(plain_text_password): + # By using bcrypt, the salt is saved into the hash itself + hashed_bytes = bcrypt.hashpw(plain_text_password.encode('utf-8'), bcrypt.gensalt()) + return hashed_bytes.decode('utf-8') + + +def verify_password(plain_text_password, hashed_password): + hashed_bytes_password = hashed_password.encode('utf-8') + return bcrypt.checkpw(plain_text_password.encode('utf-8'), hashed_bytes_password) + + +def verify_credentials(data): + if verify_username(data["username"]): + return "username taken" + if verify_email(data["email"]): + return "email taken" + + +def verify_username(data): + sql_query = """SELECT user_id FROM credentials WHERE user_login = %s""" + login_check = db_connection.sql_data(sql_query, "read", (data,)) + if login_check: + return "login taken" + return None + + +def verify_email(data): + sql_query = """SELECT user_id FROM credentials WHERE user_email = %s""" + email_check = db_connection.sql_data(sql_query, "read", (data,)) + if email_check: + return "email taken" + return None \ No newline at end of file diff --git a/db_connection.py b/db_connection.py new file mode 100644 index 00000000..7f4a01b1 --- /dev/null +++ b/db_connection.py @@ -0,0 +1,46 @@ +import psycopg2 +import psycopg2.extras + + +def sql_data(sql_query, operation_type, data=None): + try: + user_name = "flupers" + password = "123" + host = "localhost" + database_name = "db_proman" + + connect_str = "postgresql://{user_name}:{password}@{host}/{database_name}".format( + user_name=user_name, + password=password, + host=host, + database_name=database_name + ) + print("Connection string: " + connect_str) + + connection = psycopg2.connect(connect_str) + + connection.autocommit = True + + cursor = connection.cursor() + + if operation_type == "read": + cursor = connection.cursor(cursor_factory=psycopg2.extras.RealDictCursor) + cursor.execute(sql_query, data) + data = cursor.fetchall() + return data + + elif operation_type == "write": + cursor.execute(sql_query, data) + + else: + cursor.execute(sql_query, data) + + cursor.close() + + except psycopg2.DatabaseError as exception: + print(exception) + + finally: + # checks first whether the connection has been created successfully + if 'connection' in locals(): + connection.close() \ No newline at end of file diff --git a/main.py b/main.py index 9e25a1ac..8a705c49 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,15 @@ -from flask import Flask, render_template, url_for +from flask import Flask, render_template, request, redirect, session, escape, url_for +import flask_login +from data_manager import data_manager_user_operations from util import json_response - import data_handler app = Flask(__name__) +app.secret_key = 'xxs' +login_manager = flask_login.LoginManager() +login_manager.init_app(app) + + @app.route("/") @@ -18,7 +24,7 @@ def index(): @json_response def get_boards(): """ - All the boards + All the names boards """ return data_handler.get_boards() @@ -33,6 +39,42 @@ def get_cards_for_board(board_id: int): return data_handler.get_cards_for_board(board_id) +@app.route('/login', methods=['POST', 'GET']) +def login(): + if 'username' in session: + return redirect('/my_page') + else: + if request.method == 'POST': + data = request.form + if data_manager_user_operations.verify_login(data): + return render_template("login.html", message="Oops login or password is not correct") + else: + session['username'] = request.form['username'] + return redirect('/my_page') + return render_template("login.html") + + +@app.route('/logout') +def logout(): + # remove the username from the session if it's there + session.pop('username') + return redirect('/login') + + +@app.route('/register', methods=['POST', 'GET']) +def register(): + data = request.form + if request.method == 'POST': + if data_manager_user_operations.verify_credentials(data): + return render_template("register.html", message=data_manager_user_operations.verify_credentials(data)) + else: + data_manager_user_operations.register(data) + session['username'] = request.form['username'] + session['email'] = request.form['email'] + return redirect('/my_page') + return render_template("register.html") + + def main(): app.run(debug=True) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql new file mode 100644 index 00000000..6dd3f9f5 --- /dev/null +++ b/sample_data/askmatepart2-sample-data.sql @@ -0,0 +1,72 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 9.5.6 +-- Dumped by pg_dump version 9.5.6 + +DROP TABLE IF EXISTS public.boards; +DROP SEQUENCE IF EXISTS public.boards_id_seq; +CREATE TABLE boards ( + id serial NOT NULL, + title text +); + +DROP TABLE IF EXISTS public.cards; +DROP SEQUENCE IF EXISTS public.cards_id_seq; +CREATE TABLE cards ( + id serial NOT NULL, + board_id integer, + title text, + status_id integer, + "order" integer +); + +DROP TABLE IF EXISTS public.credentials; +DROP SEQUENCE IF EXISTS public.credentials_id_seq; +CREATE TABLE credentials ( + id serial NOT NULL, + user_id integer, + user_login text, + user_email text, + user_password text +); + +DROP TABLE IF EXISTS public.statuses; +DROP SEQUENCE IF EXISTS public.statuses_id_seq; +CREATE TABLE statuses ( + id serial NOT NULL, + title text +); + +-- ALTER TABLE ONLY answer +-- ADD CONSTRAINT pk_answer_id PRIMARY KEY (id); +-- +-- ALTER TABLE ONLY question_tag +-- ADD CONSTRAINT pk_question_tag_id PRIMARY KEY (question_id, tag_id); +-- +-- ALTER TABLE ONLY comment +-- ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id); + +INSERT INTO boards VALUES (1, 'Board 1'); +INSERT INTO boards VALUES (2, 'Board 2'); + + +INSERT INTO cards VALUES (1, 1, 'new card 1', 0, 0); +INSERT INTO cards VALUES (2,1,'new card 2',0,1); +INSERT INTO cards VALUES (3,1,'in progress card',1,0); +INSERT INTO cards VALUES (4,1,'planning',2,0); +INSERT INTO cards VALUES (5,1,'done card 1',3,0); +INSERT INTO cards VALUES (6,1,'done card 1',3,1); +INSERT INTO cards VALUES (7,2,'new card 1',0,0); +INSERT INTO cards VALUES (8,2,'new card 2',0,1); +INSERT INTO cards VALUES (9,2,'in progress card',1,0); +INSERT INTO cards VALUES (10,2,'planning',2,0); +INSERT INTO cards VALUES (11,2,'done card 1',3,0); +INSERT INTO cards VALUES (12,2,'done card 1',3,1); + + +INSERT INTO statuses VALUES (0, 'new'); +INSERT INTO statuses VALUES (1, 'in progress'); +INSERT INTO statuses VALUES (2, 'testing'); +INSERT INTO statuses VALUES (3, 'done'); diff --git a/templates/index.html b/templates/index.html index 6f42f26e..0f955855 100644 --- a/templates/index.html +++ b/templates/index.html @@ -4,7 +4,7 @@ -