from PySide2 import QtCore import keyring import json import pyotp SERVICE = "otpclient" class OTPModel(QtCore.QObject): _name="" _OTPType="" _secret="" _icon="" _timeout=30 _algo="SHA1" def __init__(self,name="",OTPType="",secret="",icon="",timeout=30,algo="SHA1"): QtCore.QObject.__init__(self) self._name=name self._OTPType=OTPType self._secret=secret self._icon=icon self._timeout=timeout self._algo=algo nameChanged = QtCore.Signal() @QtCore.Property(str,notify=nameChanged) def name(self): return self._name; @name.setter def setName(self, name): self._name = name OTPTypeChanged = QtCore.Signal() @QtCore.Property(str,notify=OTPTypeChanged) def OTPType(self): return self._OTPType @OTPType.setter def setOTPType(self, OTPType): self._OTPType = OTPType secretChanged = QtCore.Signal() @QtCore.Property(str,notify=secretChanged) def secret(self): return self._secret @secret.setter def setSecret(self, secret): self._secret = secret iconChanged = QtCore.Signal() @QtCore.Property(str,notify=iconChanged) def icon(self): return self._icon @icon.setter def setIcon(self,icon): self._icon = icon timeoutChanged = QtCore.Signal() @QtCore.Property(int,notify=timeoutChanged) def timeout(self): return self._timeout @timeout.setter def setTimeout(self,timeout): self._timeout = timeout algoChanged = QtCore.Signal() @QtCore.Property(str,notify=algoChanged) def algo(self): return self._algo @algo.setter def setAlgo(self,algo): self._algo = algo @QtCore.Slot(result=str) def getOTPCode(self): if self._OTPType == "TOTP": return pyotp.TOTP(self._secret).now() elif self._OTPType == "HOTP": return pyotp.HOTP(self._secret).now() else: return None class OPTListModel(QtCore.QAbstractListModel): _items=[] def __init__(self,parent = None): QtCore.QAbstractListModel.__init__(self, parent) def setup(self, list): self._items = list def load(self): config = keyring.get_password(SERVICE,"__config") if(config == None): return jsonDict = json.loads(config) size = len(self._items) self._items = [] if(jsonDict != None): for item in jsonDict: self._items.append(OTPModel(item["name"],item["OTPType"],keyring.get_password(SERVICE,item["name"]),item["icon"],item["timeout"],item["algo"])) self.modelReset.emit() def save(self): dict=[] for item in self._items: dItem = {} dItem["name"] = item.name dItem["OTPType"] = item.OTPType dItem["icon"] = item.icon dItem["timeout"] = item.timeout dItem["algo"] = item.algo keyring.set_password(SERVICE,item.name,item.secret) dict.append(dItem) keyring.set_password(SERVICE,"__config",json.dumps(dict)) @QtCore.Slot(str,str,str) def addItem(self, name="",OTPType="",secret=""): self._items.append(OTPModel(name,OTPType,secret)) self.modelReset.emit() self.save() @QtCore.Slot(object) def removeItem(self, model): self._items.remove(model) self.modelReset.emit() keyring.delete_password(SERVICE,model.name) self.save() @QtCore.Slot(int,result=object) def getItem(self,index): return self._items[index] def rowCount(self, parent=QtCore.QModelIndex()): return len(self._items) def setData(self, index, value, role): self._items[index.row()] = value self.dataChanged.emit(index, index) return True def flags(self, index): return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable def data(self, index, role=QtCore.Qt.DisplayRole): if role == QtCore.Qt.DisplayRole: return self._items[index.row()] else: return None