minor içindeki 3 işleme master ile birleştirdi
| @@ -11,6 +11,8 @@ CREATE TABLE users ( | |||
| state VARCHAR(50), | |||
| postal_code VARCHAR(50), | |||
| country VARCHAR(50), | |||
| login_attempts INT UNSIGNED, | |||
| last_login_attempt INT UNSIGNED, | |||
| PRIMARY KEY (userid) | |||
| ); | |||
| @@ -84,7 +86,7 @@ CREATE TABLE task_files ( | |||
| * Initial data | |||
| */ | |||
| insert into users values (NULL, "admin", "$2b$12$iKbYZ0MFwWWxoYUXKRhFiOPo7itaQO2DIRnLgXbECsj8XKVzkNCSi", "Admin Modsen", "ntnu", 'mail@ntnu.no', "street", "trondheim", "trondheim", "1234", "norway"); | |||
| insert into users values (NULL, "admin", "$2b$12$iKbYZ0MFwWWxoYUXKRhFiOPo7itaQO2DIRnLgXbECsj8XKVzkNCSi", "Admin Modsen", "ntnu", 'mail@ntnu.no', "street", "trondheim", "trondheim", "1234", "norway", 0, 0); | |||
| insert into project_category values (NULL, "Gardening"); | |||
| insert into project_category values (NULL, "Programming"); | |||
| @@ -28,7 +28,7 @@ def set_user(username, password, full_name, company, email, | |||
| """ | |||
| db.connect() | |||
| cursor = db.cursor() | |||
| query = ("INSERT INTO users VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)") | |||
| query = ("INSERT INTO users VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 0, 0)") | |||
| try: | |||
| cursor.execute(query, (username, password, full_name, company, email, street_address, | |||
| city, state, postal_code, country)) | |||
| @@ -12,7 +12,7 @@ def get_user(username): | |||
| """ | |||
| db.connect() | |||
| cursor = db.cursor() | |||
| query = ("SELECT userid, username, password from users where username = %s") | |||
| query = ("SELECT userid, username, password, login_attempts, last_login_attempt from users where username = %s") | |||
| user = None | |||
| try: | |||
| cursor.execute(query, (username,)) | |||
| @@ -51,6 +51,25 @@ def get_users(): | |||
| return users | |||
| def set_login_attempts(userid, num, timestamp): | |||
| """ | |||
| Set the number and timestamp of the failed login attempts for the given user. | |||
| """ | |||
| db.connect() | |||
| cursor = db.cursor() | |||
| query = ("UPDATE users SET login_attempts = %s, last_login_attempt = %s WHERE userid = %s") | |||
| try: | |||
| cursor.execute(query, (num, timestamp, userid)) | |||
| db.commit() | |||
| except mysql.connector.Error as err: | |||
| print("Failed executing query: {}".format(err)) | |||
| cursor.fetchall() | |||
| exit(1) | |||
| finally: | |||
| cursor.close() | |||
| db.close() | |||
| def get_user_id_by_name(username): | |||
| """ | |||
| Get the id of the unique username | |||
| @@ -14,6 +14,10 @@ render = web.template.render('templates/') | |||
| # The remember cookie should be valid for a week | |||
| remember_timeout = 3600*24*7 | |||
| # The timeout between login attempts, after the 3rd incorrect one | |||
| login_timeout = 60 | |||
| login_attempts_threshold = 2 | |||
| class Login(): | |||
| @@ -47,11 +51,24 @@ class Login(): | |||
| # Validate login credential with database query | |||
| user = models.user.get_user(data.username) | |||
| if bcrypt.checkpw(data.password.encode('UTF-8'), user[2].encode('UTF-8')): | |||
| self.login(user[1], user[0], data.remember) | |||
| if user is None: | |||
| return render.login(nav, login_form, "- User authentication failed") | |||
| userid, username, password_hash, login_attempts, last_login_attempt = user | |||
| if login_attempts > login_attempts_threshold and last_login_attempt + login_timeout > time.time(): | |||
| return render.login(nav, login_form, "- There have been too many incorrect login attempts for your account. You have to wait a minute before you can log in.") | |||
| if bcrypt.checkpw(data.password.encode('UTF-8'), password_hash.encode('UTF-8')): | |||
| models.user.set_login_attempts(userid, 0, time.time()) | |||
| self.login(username, userid, data.remember) | |||
| raise web.seeother("/") | |||
| else: | |||
| return render.login(nav, login_form, "- User authentication failed") | |||
| models.user.set_login_attempts(userid, login_attempts+1, time.time()) | |||
| if login_attempts == login_attempts_threshold: | |||
| return render.login(nav, login_form, "- Too many incorrect login attempts. You have to wait a minute before trying again.") | |||
| else: | |||
| return render.login(nav, login_form, "- User authentication failed") | |||
| def login(self, username, userid, remember): | |||
| """ | |||