# -*- coding: utf-8 -*- import MySQLdb.cursors import bcrypt import random import string class User(object): @classmethod def genpass(cls, length=12): return ''.join(random.choices(string.ascii_letters + string.digits, k=length)) def __init__(self, dbconn, user_id=None): self.conn = dbconn self.cur = dbconn.cursor(MySQLdb.cursors.DictCursor) if user_id is not None: self.user_id = int(user_id) self.load() else: self.login = None self.displayname = None self.language = 'en' self.role = 'undef' self.flags = [] def load(self, user_id=0): sql = ( "SELECT login, displayname, language, role, flags " "FROM user " "WHERE userid=%s") self.cur.execute(sql, (self.user_id, )) row = self.cur.fetchone() if row: self.data = row self.login = row['login'] self.displayname = row['displayname'] self.language = row['language'] self.role = row['role'] self.flags = row['flags'].split(',') if row['flags'] else [] else: self.data = None def save(self): fields = ('login', 'displayname', 'language', 'role') sqlfield = [] values = [] for field in fields: newdata = getattr(self, field) if self.data[field] != newdata: sqlfield.append(f"{field}=%s") values.append(newdata) self.data[field] = newdata # flags set handled separately newflags = ','.join(self.flags) if self.flags else None if self.data['flags'] != newflags: sqlfield.append(f"flags=%s") values.append(newflags) self.data['flags'] = newflags if values: # only save if changed values exist sql = "UPDATE user SET " + ",".join(sqlfield) + " WHERE userid=%s" values.append(self.user_id) self.cur.execute(sql, values) self.conn.commit() """ unused at the moment def mark_login(self): sql = "UPDATE user SET last_login=NOW() WHERE username=%s" self.cur.execute(sql, (self.username, )) self.conn.commit() def mark_logout(self): sql = "UPDATE user SET last_logout=NOW() WHERE username=%s" self.cur.execute(sql, (self.username, )) self.conn.commit() """ def create(self): """ Creates a new user with the first free id > 0 The role is the lowest possible one """ sql = ( "SELECT MIN(u1.userid+1) AS newid " "FROM user AS u1 LEFT JOIN user AS u2 ON u2.userid=u1.userid+1 " "WHERE u1.userid>=0 AND u2.userid IS NULL") self.cur.execute(sql) newid = self.cur.fetchone()['newid'] self.user_id = newid # TODO check if login is unused else create other name # add function for that feature self.login = f"user{newid}" self.displayname = f"User #{newid}" self.language = 'en' self.role = 'sailor' self.flags = None sql = ( "INSERT INTO user (userid, login, pass, displayname, role, flags, language) " "VALUES (%s,%s,%s,%s,%s,%s,%s)" ) cryptpass = bcrypt.hashpw(self.genpass().encode(), bcrypt.gensalt()) self.cur.execute(sql, (newid, self.login, cryptpass, self.displayname, self.role, self.flags, self.language)) # create mandatory settings sql = "INSERT INTO settings (userid, sno, valint) VALUES (%s, 1, 0)" self.cur.execute(sql, (newid,)) self.conn.commit() return newid def delete(self): sql = "DELETE FROM settings WHERE userid=%s" self.cur.execute(sql, (self.user_id,)) sql = "DELETE FROM user WHERE userid=%s" self.cur.execute(sql, (self.user_id,)) self.conn.commit() def setpass(self, newpass): sql = "UPDATE user SET pass=%s WHERE userid=%s" cryptpass = bcrypt.hashpw(newpass.encode(), bcrypt.gensalt()) print(cryptpass, self.user_id) self.cur.execute(sql, (cryptpass, self.user_id)) self.conn.commit() def __repr__(self): # Unique description out = "User(%d)" % self.user_id return out def __str__(self): # Prettyprint out = "User(%d) - %s\n" % (self.user_id, self.displayname) out += " F: %s\n" % self.flags out += " R: %s\n" % self.role out += " L: %s\n" % self.language return out