@@ -1,118 +1,200 @@
'''Inteface between all modules and allows command line inteface in test mode'''

from sys import platform
import threading

import communication as comm
import data_management as dm
import crypto_manager as crypto

_killEvent = threading.Event()

def init(**kwargs):
'''Initiate the interface'''

threading.Thread(target=comm.init, name='communication', daemon=True).start()

if kwargs['cmdListening'] is True:
threading.Thread(target=cmd_listener, name='CMD listener', args=(_killEvent,)).start()

print('started interface')

def cmd_listener(event):
'''Allows testing commands through the command line'''

while not event.is_set():
# get input from command line
data = input('Enter command>>')

# shuts down the program if the input was exit
if data == "exit":
shutdown()
break

caller(data)

def init():
if platform == 'linux' or platform == 'linux2':
comm.init()

t = threading.Thread(target=cmdListener)
t.start()

print('start interface')

def cmdListener():
import password_manager as pm

while pm.getIsRunning:# is True: #Debug
data = input().split(' ')
if len(data) > 1:
commandName = data.pop(0)
args = {}
try:
for arg in data:
key, value = arg.split('=')
args[key.upper] = value
except:
print('one or more arguments did not have any value')
args = None
else:
commandName = data[0]
args = {}

if commandName == "exit":
pm.setIsRunning(False)
def split_args(data, sep):
'''Split a single string to key value pair dict by separator'''

args = {}
for arg in data:
pair = arg.split(sep)
if len(pair) == 1:
print('key:{0} did not have any value'.format(pair[0]))
elif pair[0] == '' or pair[0] == ' ':
print('no key for value:{0}'.format(pair[1]))
else:
command = None
try:
command = _commandsDict[commandName]
except:
print("no command named {}".format(commandName))
if command is not None and args is not None:
threading.Thread(target=command, kwargs=args).start()

def getPassword(**kwargs):
args = {'ID':None}
isRun = True

for argName in args:
try:
args[argName] = kwargs[argName.upper]
except:
isRun = False
print('the argument {} is missing'.format(argName))
args[pair[0].upper] = pair[1]

if isRun is True:
return dm.getPassFromDatabase(args['ID'])
return args

def setPassword(**kwargs):
args = {
'NAME':None,
'PASSWORD':None
}
isRun = True
def caller(raw_data):
'''Calles commands to run'''

for argName in args:
args = split_args(raw_data.split(' '), '=')

commandName = _pop_value(args, 'COMMAND')
if commandName is None:
print('no command was supplied')
else:
try:
args[argName] = kwargs[argName]
command = _commandsDict[commandName]
except:
isRun = False
print('the argument {} is missing'.format(argName))
print("no command named {}".format(commandName))

if isRun is True:
dm.addToDatabase(args['NAME'], args['PASSWORD'])
threading.Thread(target=command, kwargs=args).start()

def updatePassword(**kwargs):
args = {
'ID':None,
'NAME':None,
'PASSWORD':None
}
isRun = True
def get_password(**kwargs):
'''DOC'''

for argName in args:
try:
args[argName] = kwargs[argName]
except:
isRun = False
print('the argument {} is missing'.format(argName))
pID = _pop_value(kwargs, 'ID')
reqID = _pop_value(kwargs, "REQ_ID")

if isRun is True:
dm.addToDatabase(args['ID'], args['NAME'], args['PASSWORD'])
if reqID is None:
print('no requestor ID supplied')
return

def deletePassword(**kwargs):
args = {'ID':None}
isRun = True
if pID is None:
print('no ID was supplied')
return

for argName in args:
try:
args[argName] = kwargs[argName]
except:
isRun = False
print('the argument {} is missing'.format(argName))
encPass = dm.getPassFromDatabase(pID)

if encPass is None:
print('error retriving password, ID={0}'.format(pID))
return

auth_password = _pop_value(kwargs, 'AUTH_PASSWORD')
if auth_password is None:
print('no authorization password was supplied')
return

decPass = crypto.decrypt(auth_password, encPass)

if isRun is True:
dm.addToDatabase(args['ID'])
if decPass is None:
print('error retriving password, ID={0}'.format(pID))
return

def getDataList(**kwargs):
return list(map(lambda x: (x[0], x[1]), dm.getAllFromTable()))
#TODO comm send password or error

def set_password(**kwargs):
'''DOC'''

name = _pop_value(kwargs, 'NAME')
password = _pop_value(kwargs, 'PASSWORD')
pID = _pop_value(kwargs, 'ID')
reqID = _pop_value(kwargs, "REQ_ID")
auth_password = _pop_value(kwargs, 'AUTH_PASSWORD')

if reqID is None:
print('no requestor ID supplied')
return
if pID is None:
print('no ID was supplied')
return
if name is None:
print('no name was supplied')
return
if password is None:
print('no password was supplied')
return
if auth_password is None:
print('no authorization password was supplied')
return

encName = crypto.encrypt(auth_password, name)
encPass = crypto.encrypt(auth_password, password)

if crypto.authorize(auth_password) is True:
dm.setInDatabase(pID, encName, encPass)

#TODO comm send OK or error

def delete_password(**kwargs):
'''DOC'''

pID = _pop_value(kwargs, 'ID')
reqID = _pop_value(kwargs, "REQ_ID")
auth_password = _pop_value(kwargs, 'AUTH_PASSWORD')

if reqID is None:
print('no requestor ID supplied')
return
if pID is None:
print('no ID was supplied')
return
if auth_password is None:
print('no authorization password was supplied')
return

if crypto.authorize(auth_password) is True:
dm.deleteFromDatabase(pID)

#TODO comm send OK or error

def get_data_list(**kwargs):
'''DOC'''

nameDict = {}

reqID = _pop_value(kwargs, "REQ_ID")
auth_password = _pop_value(kwargs, 'AUTH_PASSWORD')

if reqID is None:
print('no requestor ID supplied')
return
if auth_password is None:
print('no authorization password was supplied')
return

if crypto.authorize(auth_password) is True:
table = dm.getAllFromTable()
else:
return

for pID, name, password in table:
nameDict[pID] = crypto.decrypt(auth_password, name)

#TODO comm send nameDict or error

_commandsDict = {
"GET":getPassword,
"INSERT":setPassword,
"CHANGE":updatePassword,
"DELETE":deletePassword,
"GET-ALL":getDataList
"GET":get_password,
"SET":set_password,
"DELETE":delete_password,
"GET-ALL":get_data_list
}

def shutdown():
'''Shuts down the program'''

dm.closeConnection()
_killEvent.set()

def _pop_value(dict, key):
'''Return the value from the given key and the delete the entry'''

try:
return dict.pop(key)
except:
return None
@@ -1,59 +1,101 @@
'''Implementation of the methods that start the program and its requirements'''

import logging
import time
import sys
import os
import json
import atexit
import threading

import data_management as dm
import interface

RUNNING = True
runningLock = threading.Lock()

def getIsRunning():
value = False

runningLock.acquire()
try:
value = RUNNING
finally:
runningLock.release()

return value

def setIsRunning(value):
global RUNNING

runningLock.acquire()
try:
RUNNING = value
finally:
runningLock.release()
config = {}
logger = None

def bootstrap(options):
'''Setup needed requirements'''

# place to save logging data
if not os.path.exists('log'):
os.makedirs('log')

# place to save temporary data
if not os.path.exists('tmp'):
os.makedirs('tmp')

# place to save database
if not os.path.exists('data'):
os.makedirs('data')

create_pid()
init_config(options)
init_logger()

logger.info('Starting app on pid: {0}'.format(os.getpid()))
logger.debug('With config:')
logger.debug(config)

# add commands to activate at program shutdown
atexit.register(interface.shutdown)
atexit.register(delete_pid)
atexit.register(dm.closeConnection)

if options['test'] is True and os.path.isfile(dm.PASSWORDS_DATA_PATH):
os.remove(dm.PASSWORDS_DATA_PATH)
dm.DATABASE_PATH = config['database_path']

# delete existent database if in reset arg was given
if config['reset'] is True and os.path.isfile(dm.DATABASE_PATH):
os.remove(dm.DATABASE_PATH)

dm.initDatabase()

def create_pid():
'''Save the pid number of the proccess in "tmp/pid"'''

f = open('tmp/tracks.pid', 'w')
f.write("{0}".format(os.getpid()))
f.close()

def delete_pid():
'''Delete the proccess pid at program shutdown'''

os.remove('tmp/tracks.pid')

def startApp():
interface.init()
def init_config(options):
path = None

with open('config/config.json') as data_file:
cfg = json.load(data_file)
global config

config = dict(cfg['default'], **options)

def init_logger():
'''Start a logger'''

logging.basicConfig(
filename='log/{month}.{day}.{year}.{hour}.{minute}.log'.format(
day=time.strftime('%d'),
month=time.strftime('%h'),
year=time.strftime('%y'),
hour=time.strftime('%H'),
minute=time.strftime('%M')
),
level=logging.DEBUG,
format='%(asctime)s [%(levelname)s] %(message)s'
)
logging.captureWarnings(True)
root = logging.getLogger()

handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')
handler.setFormatter(formatter)
root.addHandler(handler)

global logger
logger = logging

def start_app():
'''Start the interface of the program'''

interface.init(cmdListening=config['test'])
@@ -1,28 +1,32 @@
#!/usr/bin/env python
"""Start of the project"""
#!/usr/bin/env python3
"""The start of the project"""

import sys
import argparse

import os.path as path

# adds the app modules to the system path
APP_PATH = path.abspath(path.join(path.dirname(__file__), path.pardir, 'app'))
sys.path.append(APP_PATH)
import password_manager as pm

def start():
"starts up the program and its requirements"

# allowes to run the program with spacial arguments
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--test", action="store_true",help='test mode')
parser.add_argument("-t", "--test", action="store_true", help='test mode')
parser.add_argument("-r", "--reset", action="store_true", help='reset database')

options = vars(parser.parse_args())

empty_keys = [k for k,v in options.items() if v==None]
empty_keys = [k for k, v in options.items() if v is None]
for k in empty_keys:
del options[k]

"""Start the program"""
pm.bootstrap(options)
pm.startApp()
pm.start_app()

if __name__ == '__main__':
start()
@@ -0,0 +1,5 @@
{
"default":{
"database_path":"data/passwords.db"
}
}
@@ -1 +1,2 @@
PyBluez==0.22
pycryptodome==3.4.6