Fixes #14session-cookie
| @@ -17,6 +17,7 @@ CREATE TABLE users ( | |||||
| CREATE TABLE cookies ( | CREATE TABLE cookies ( | ||||
| token VARCHAR(100) UNIQUE NOT NULL, | token VARCHAR(100) UNIQUE NOT NULL, | ||||
| userid INT UNSIGNED NOT NULL, | userid INT UNSIGNED NOT NULL, | ||||
| expiry INT NOT NULL, | |||||
| PRIMARY KEY (token), | PRIMARY KEY (token), | ||||
| FOREIGN KEY (userid) REFERENCES users(userid) | FOREIGN KEY (userid) REFERENCES users(userid) | ||||
| ); | ); | ||||
| @@ -2,7 +2,7 @@ from models.database import db | |||||
| import mysql.connector | import mysql.connector | ||||
| def set_cookie(userid, token): | |||||
| def set_cookie(userid, token, expiry): | |||||
| """ | """ | ||||
| Register a persistant login token for an user | Register a persistant login token for an user | ||||
| :param userid: The ID of the user | :param userid: The ID of the user | ||||
| @@ -10,10 +10,10 @@ def set_cookie(userid, token): | |||||
| """ | """ | ||||
| db.connect() | db.connect() | ||||
| cursor = db.cursor() | cursor = db.cursor() | ||||
| query = ("INSERT INTO cookies (userid, token) VALUES (%s, %s)") | |||||
| query = ("INSERT INTO cookies (userid, token, expiry) VALUES (%s, %s, %s)") | |||||
| try: | try: | ||||
| cursor.execute(query, (userid, token)) | |||||
| cursor.execute(query, (userid, token, expiry)) | |||||
| db.commit() | db.commit() | ||||
| except mysql.connector.Error as err: | except mysql.connector.Error as err: | ||||
| print("Failed executing query: {}".format(err)) | print("Failed executing query: {}".format(err)) | ||||
| @@ -31,14 +31,16 @@ def get_cookie(token): | |||||
| """ | """ | ||||
| db.connect() | db.connect() | ||||
| cursor = db.cursor() | cursor = db.cursor() | ||||
| query = ("SELECT userid FROM cookies WHERE token = %s") | |||||
| query = ("SELECT userid, expiry FROM cookies WHERE token = %s") | |||||
| userid = None | userid = None | ||||
| expiry = None | |||||
| try: | try: | ||||
| cursor.execute(query, (token,)) | cursor.execute(query, (token,)) | ||||
| users = cursor.fetchall() | users = cursor.fetchall() | ||||
| if len(users): | if len(users): | ||||
| userid = users[0][0] | userid = users[0][0] | ||||
| expiry = users[0][1] | |||||
| except mysql.connector.Error as err: | except mysql.connector.Error as err: | ||||
| print("Failed executing query: {}".format(err)) | print("Failed executing query: {}".format(err)) | ||||
| cursor.fetchall() | cursor.fetchall() | ||||
| @@ -47,7 +49,7 @@ def get_cookie(token): | |||||
| cursor.close() | cursor.close() | ||||
| db.close() | db.close() | ||||
| return userid | |||||
| return userid, expiry | |||||
| def delete_cookie(token): | def delete_cookie(token): | ||||
| @@ -6,10 +6,14 @@ from views.utils import get_nav_bar | |||||
| import random | import random | ||||
| import string | import string | ||||
| import hashlib | import hashlib | ||||
| import time | |||||
| # Get html templates | # Get html templates | ||||
| render = web.template.render('templates/') | render = web.template.render('templates/') | ||||
| # The remember cookie should be valid for a week | |||||
| remember_timeout = 3600*24*7 | |||||
| class Login(): | class Login(): | ||||
| @@ -58,8 +62,8 @@ class Login(): | |||||
| session.username = username | session.username = username | ||||
| session.userid = userid | session.userid = userid | ||||
| if remember: | if remember: | ||||
| rememberme = self.rememberme() | |||||
| web.setcookie('remember', rememberme , 300000000) | |||||
| rememberme = self.rememberme(remember_timeout) | |||||
| web.setcookie('remember', rememberme , remember_timeout) | |||||
| def check_rememberme(self): | def check_rememberme(self): | ||||
| """ | """ | ||||
| @@ -72,17 +76,17 @@ class Login(): | |||||
| cookies = web.cookies() | cookies = web.cookies() | ||||
| # Fetch the remember cookie and convert from string to bytes | # Fetch the remember cookie and convert from string to bytes | ||||
| remember_token = cookies.remember | remember_token = cookies.remember | ||||
| userid = models.session.get_cookie(remember_token) | |||||
| except AttributeError as e: | |||||
| userid, expiry = models.session.get_cookie(remember_token) | |||||
| except AttributeError: | |||||
| # The user did not have the stored remember me cookie | # The user did not have the stored remember me cookie | ||||
| pass | pass | ||||
| # If the users signed cookie matches the host signature then log in | # If the users signed cookie matches the host signature then log in | ||||
| if userid is not None: | |||||
| if userid is not None and expiry > time.time(): | |||||
| username = models.user.get_user_name_by_id(userid) | username = models.user.get_user_name_by_id(userid) | ||||
| self.login(username, userid, False) | self.login(username, userid, False) | ||||
| def rememberme(self): | |||||
| def rememberme(self, timeout): | |||||
| """ | """ | ||||
| Generate a random token for the user, and store it in the database. | Generate a random token for the user, and store it in the database. | ||||
| """ | """ | ||||
| @@ -91,8 +95,8 @@ class Login(): | |||||
| while True: | while True: | ||||
| token = ''.join(random.SystemRandom().choice(alphabet) for _ in range(20)) | token = ''.join(random.SystemRandom().choice(alphabet) for _ in range(20)) | ||||
| if models.session.get_cookie(token) is None: | |||||
| if models.session.get_cookie(token)[0] is None: | |||||
| break | break | ||||
| models.session.set_cookie(session.userid, token) | |||||
| models.session.set_cookie(session.userid, token, int(time.time() + timeout)) | |||||
| return token | return token | ||||
| @@ -13,8 +13,12 @@ class Logout: | |||||
| Log out of the application (kill session and reset variables) | Log out of the application (kill session and reset variables) | ||||
| :return: Redirect to main page | :return: Redirect to main page | ||||
| """ | """ | ||||
| remember_token = web.cookies().remember | |||||
| models.session.delete_cookie(remember_token) | |||||
| try: | |||||
| remember_token = web.cookies().remember | |||||
| models.session.delete_cookie(remember_token) | |||||
| except AttributeError: | |||||
| # The user did not have the stored remember me cookie | |||||
| pass | |||||
| session = web.ctx.session | session = web.ctx.session | ||||
| session.username = None | session.username = None | ||||