def __init__(self, is_test=False): if is_test: super().__init__("accounts_test") else: super().__init__("accounts") self.active_sessions = sessions() # Just using a delay between attempt, not super reliable, # but fit for low-risk data, and drastically slows down brute force self.login_attempts = {'name': 'last_attempt'} cmd = "CREATE TABLE IF NOT EXISTS accounts " cmd += "(name TEXT PRIMARY KEY NOT NULL)" self.queue_command(queue_item(queue_cmd(cmd))) self.add_col("accounts", "pwhash", "BLOB") self.add_col("accounts", "pwsalt", "BLOB") cmd = "CREATE TABLE IF NOT EXISTS data " cmd += "(name TEXT, FOREIGN KEY(name) REFERENCES accounts(name))" self.queue_command(queue_item(queue_cmd(cmd))) # Add whatever cols have been specified in constants for col in constants.db_col_names: self.add_col("data", col, "TEXT")
def add_account(self, name, password): # Lowercase the name/username - case must not matter name = simple_sqlsafe_str(name.lower()) cmd = "SELECT * FROM accounts WHERE name = ?" qi = queue_item(queue_cmd(cmd, [name]), queue_item.return_type_single) account = self.queue_command(qi) if account is None: # Salt with 24 bytes of random data pwsalt = os.urandom(24) pwhash = password_hash(password, pwsalt) cmd = "INSERT INTO accounts (name, pwhash, pwsalt) VALUES (?,?,?)" qi = queue_item(queue_cmd(cmd, [name, pwhash, pwsalt])) self.queue_command(qi) cmd = "INSERT INTO data (name) VALUES (?)" qi = queue_item(queue_cmd(cmd, [name])) self.queue_command(qi)
def set_data(self, name, session_uuid, data, value): # Lowercase the name/username - case must not matter name = name.lower() if self.active_sessions.check_session(name, session_uuid): # Can't parameterise a column name. Have to do it manually cmd = "UPDATE data SET {} = ? WHERE name = ?".format( simple_sqlsafe_str(data)) qi = queue_item(queue_cmd(cmd, [value, name])) self.queue_command(qi) return True else: return None
def get_data(self, name, session_uuid, data): # Lowercase the name/username - case must not matter name = name.lower() # print("get_data: ", name, session_uuid) # print(self.active_sessions.session_list) if self.active_sessions.check_session(name, session_uuid): cmd = "SELECT {} FROM data WHERE name = ?".format( simple_sqlsafe_str(data)) qi = queue_item(queue_cmd(cmd, [name]), queue_item.return_type_single) return self.queue_command(qi) else: return "No active session"
def get_account(self, name, password): # Lowercase the name/username - case must not matter name = simple_sqlsafe_str(name.lower()) cmd = "SELECT * FROM accounts WHERE name = ?" qi = queue_item(queue_cmd(cmd, [name]), queue_item.return_type_raw) account = self.queue_command(qi) if len(account) == 0: return None if len(account) == 1: account = account[0] # Main check here if password is correct if password_check(account['pwhash'], account['pwsalt'], password): return account else: return False if len(account) > 1: raise Exception("Multiple accounts with the same name?")