Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0008 save more data #12

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions AppConfig/Consts.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import os

class Consts:
APP_NAME = "PassManager"
encoding = 'utf-8'
Expand All @@ -10,3 +8,4 @@ class Consts:
_DebugMode = 'Debug_Mode'
Gibberish_Len = 1024
Gibberish_Template = '{G1}{data}{G2}'
UserMetaDataFolderName = 'UsersMetaData'
8 changes: 7 additions & 1 deletion Authentication/AuthenticationService.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def __init__(self,
self._fileEncryptionService = fileEncryptionService
self.mfaManager = None
self.gpasswordKey: bytes = bytearray()
self.userEmail = None

def isAuthnticated(self) -> bool:
return self._mfaManagerService.IsMfaActive() and self.__isPasswordActive()
Expand All @@ -38,13 +39,15 @@ def login(self, email, password, mfa) -> LogInReturnStatus:
if mfaLoginResult.IsSucceded():
hashedMfaKey = PasswordService.HashifyPassword(mfaKeyDecrebtedKey)
self.__setPassword(hashedMfaKey)
self.__setEmai(email)

mfaKeyDecrebtedKey = None
password = None

return mfaLoginResult

def logout(self):
self.userEmail = None
self.gpasswordKey = bytearray()
self._mfaManagerService.logOut()

Expand Down Expand Up @@ -75,4 +78,7 @@ def getPassowrdKey(self) -> bytes:
return self.gpasswordKey

def __setPassword(self, password:bytes):
self.gpasswordKey = password
self.gpasswordKey = password

def __setEmai(self, email:str):
self.userEmail = email
4 changes: 4 additions & 0 deletions Model/IAmUnique.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class IAmUnique:

def getUniqueId(self):
pass
16 changes: 16 additions & 0 deletions Model/ISerilizable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pickle

from AppConfig.Consts import Consts


class ISerilizable:

def serializeJson(self)->str:
return str(pickle.dumps(self), encoding=Consts.encoding_byte_array)

@staticmethod
def deserilizeJson(str):
try:
return pickle.loads(bytes(str, encoding=Consts.encoding_byte_array))
except:
return None
25 changes: 25 additions & 0 deletions Model/SavedPasswordData.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from Model.IAmUnique import IAmUnique
from Model.ISerilizable import ISerilizable


class SavedPasswordData(ISerilizable, IAmUnique):

def __init__(self, serviceName, password, email, website=None, metaData={}):
self.serviceName = serviceName
self.email = email
self.password = password
self.website = website
self.metaData = metaData

def setEmail(self, email):
self.email = email

def getUniqueId(self):
return self.email + self.serviceName

def __str__(self):
return f'Email = {self.email}\n' \
f'Service Name = {self.serviceName}\n' \
f'Password = {self.password}\n' \
f'websiteUrl = {self.website}\n' \
f'more Info = {self.metaData}.'
22 changes: 14 additions & 8 deletions PasswordManager/MainPasswordManager.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import gc

from AppConfig.IConfiguration import IConfiguration
from Model.SavedPasswordData import SavedPasswordData
from PasswordManager.FileEncryptionManager import FileEncryptionManager
from Service.FileManagement import FileManagement

Expand All @@ -13,14 +14,17 @@ def __init__(self,
self._fileEncryptionManager = fileEncryptionManager
self._defaultDir = configuration.SavedPasswordDirPath

def addPassword(self, serviceName, password):
def addPassword(self, dataToSave:SavedPasswordData):
'Throw exception'
self.initSavedPasswordDir()
fileFullPath = ''

try:
fileFullPath = FileManagement.createFilePath(serviceName, self._defaultDir)
FileManagement.WriteInFile(fileFullPath, password)
fileFullPath = FileManagement.createFilePath(
dataToSave.getUniqueId(),
self._defaultDir
)
FileManagement.WriteInFile(fileFullPath, dataToSave.serializeJson())
except FileExistsError as ex:
raise
except Exception:
Expand All @@ -39,20 +43,22 @@ def addPassword(self, serviceName, password):
key = None
collected = gc.collect()

def getPassword(self, serviceName):
def getPassword(self, dataToSave:SavedPasswordData) -> SavedPasswordData:
'Throw exception'
self.initSavedPasswordDir()
fileFullPath = FileManagement.createFilePath(serviceName, self._defaultDir, FileManagement.Encryption)
# need to add the email to the path
fileFullPath = FileManagement.createFilePath(dataToSave.getUniqueId(), self._defaultDir, FileManagement.Encryption)
if not FileManagement.DoesPathExist(fileFullPath):
raise Exception(f'No matching passwrod for this service found :{serviceName}.')
raise Exception(f'No matching passwrod for this service found :{dataToSave.serviceName}.')

decPassword = self._fileEncryptionManager.read_encrypted_file(fileFullPath)
defFile = self._fileEncryptionManager.read_encrypted_file(fileFullPath)
savedData = SavedPasswordData.deserilizeJson(defFile)

# Clean-up
key = None
collected = gc.collect()

return decPassword
return savedData

def initSavedPasswordDir(self):
FileManagement.CreateDir(self._defaultDir)
6 changes: 1 addition & 5 deletions Service/FileEncryptionService.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,7 @@ def create_decrypted_file(self, filePath, key:bytes, delete=True) -> str:
dec = self.decryptFileContent(filePath, key)
decFilePath = FileManagement.ChangeFileType(filePath, FileManagement.Txt)

try:
FileManagement.WriteInFile(decFilePath, dec)
except FileExistsError as ex:
os.remove(decFilePath)
raise ex
FileManagement.WriteInFileWithErrorHandling(decFilePath, dec)

if delete:
os.remove(filePath)
Expand Down
12 changes: 10 additions & 2 deletions Service/FileManagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,24 @@ def WriteJsonObject(filePath, data, newFile=True):


@staticmethod
def WriteInFile(filePath, data, inBytes=False,newFile=True):
def WriteInFile(filePath, data, inBytes=False, newFile=True, overiteFile=False):
FileManagement.__CheckFileCreation(filePath, newFile)

if not newFile:
if not newFile and not overiteFile:
FileManagement.AppendToFile(filePath, data)

writeMode = 'wb' if inBytes else 'w'
with open(filePath, writeMode) as file:
file.write(data)

@staticmethod
def WriteInFileWithErrorHandling(filePath, data, inBytes=False, newFile=True, overiteFile=False):
try:
FileManagement.WriteInFile(filePath, data, inBytes, newFile, overiteFile)
except FileExistsError as ex:
os.remove(filePath)
raise ex

@staticmethod
def __CheckFileCreation(filePath:str, newFile:bool):
if newFile and FileManagement.DoesPathExist(filePath):
Expand Down
17 changes: 17 additions & 0 deletions Service/Model/UserMetaData.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from Model.IAmUnique import IAmUnique
from Model.ISerilizable import ISerilizable


class UserMetaData(ISerilizable, IAmUnique):

def __init__(self, userEmail, servicesNamesList, lastLoginAt, accountCreatedAt):
self.userEmail = userEmail
self.servicesNamesList = servicesNamesList
self.lastLoginAt = lastLoginAt
self.accountCreatedAt = accountCreatedAt

def getUniqueId(self):
return self.userEmail

def addService(self, serviceName):
self.servicesNamesList.append(serviceName)
Empty file added Service/Model/__init__.py
Empty file.
45 changes: 45 additions & 0 deletions Service/UserMetaDataService.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from AppConfig.Consts import Consts
from AppConfig.IConfiguration import IConfiguration
from PasswordManager.FileEncryptionManager import FileEncryptionManager
from Service.FileManagement import FileManagement
from Service.Model.UserMetaData import UserMetaData

import os

class UserMetaDataService:

def __init__(self,
fileEncryptionManager:FileEncryptionManager,
configuration:IConfiguration):
self._fileEncryptionManager = fileEncryptionManager
self._configuration = configuration

def ReadUserMetaData(self, userMetaData:UserMetaData) -> UserMetaData:
filePath = self.GetFilePath(userMetaData)
FileManagement.DoesPathExist(filePath, raiseException=True)
fileContent = self._fileEncryptionManager.read_encrypted_file(filePath)
return UserMetaData.deserilizeJson(fileContent)

def WriteUserMetaData(self, userMetaData:UserMetaData):
# write assumes that the enc file doesn't exist
filePath = self.GetFilePath(userMetaData)
FileManagement.WriteInFileWithErrorHandling(filePath, userMetaData.serializeJson(), newFile=False, overiteFile=True)
self._fileEncryptionManager.encryptFile(filePath)

def UpdateUserMetaData(self, userMetaData:UserMetaData):
# change fileName then create new file then delte it
pass

def CreateUserMetaDataFolder(self):
dirPath = self.GetMetaDataDirPath()
FileManagement.CreateDir(dirPath)

def GetFilePath(self, userMetaData:UserMetaData) -> str:
dirPath = self.GetMetaDataDirPath()
filePath = FileManagement.createFilePath(userMetaData.getUniqueId(), dirPath)
return filePath

def GetMetaDataDirPath(self) -> str:
folderName = Consts.UserMetaDataFolderName
savedPasswordsDirPath = self._configuration.GetValueOrDefault(Consts._Saved_Password_Dir_Path)
return os.path.join(savedPasswordsDirPath, folderName)
30 changes: 27 additions & 3 deletions UserInput/PromptUserInputHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from Service.FileManagement import FileManagement
from UserInput.BasePromptUserInputHandler import BasePromptUserInputHandler
import re
import validators


class PromptUserInputHandler(BasePromptUserInputHandler):
Expand Down Expand Up @@ -73,9 +74,32 @@ def getValidEmail(self) -> str:
# return email


def getWebSiteServiceName(self) -> str:
WebSiteServiceName = self.getUserInput('Please Enter Website/Service Name:')
return WebSiteServiceName
def getServiceName(self) -> str:
serviceName = self.getUserInput('Please Enter Service Name:')
return serviceName

def getValidWebsiteUrl(self) -> str:
while True:
websiteUrl = self.getUserInput('Please Enter website url (To skip press enter):')
if websiteUrl == '\n':
return None
if validators.url(websiteUrl):
break
return websiteUrl

def getAddetionalInfo(self) -> {}:
keyValuesMetaData = {}
while True:
key = self.getUserInput('Please Enter name to store a value (To finish press enter):')
if key == '\n':
return keyValuesMetaData
if key in keyValuesMetaData:
print("name already exists.")
continue

value = self.getUserInput('Please Enter the name value:')
keyValuesMetaData[key] = value
return keyValuesMetaData

def getFilePath(self, toMsg='') -> str:
to = '' if len(toMsg) == 0 else f' to {toMsg}'
Expand Down
Loading