From a0c785ac1d572b82cb214a61e62d8443b3927e7c Mon Sep 17 00:00:00 2001 From: Mitchell Pomery Date: Thu, 2 Apr 2015 21:55:16 +0800 Subject: [PATCH] Fix up dispense abstraction --- VendServer/DispenseInterface.py | 39 ++++--- VendServer/OpenDispense.py | 176 ++++++++++++++++++-------------- 2 files changed, 127 insertions(+), 88 deletions(-) diff --git a/VendServer/DispenseInterface.py b/VendServer/DispenseInterface.py index 7af3653..94b2367 100644 --- a/VendServer/DispenseInterface.py +++ b/VendServer/DispenseInterface.py @@ -10,67 +10,82 @@ class DispenseInterface(object): """ Create a new dispense object. + @param username The username to connect to dispense with + @param secret The secret to use for Auth """ - def __init__(self, username=None, loggedIn=False, disabled=False): + def __init__(self, username=None, secret=None): pass """ Create a new dispense interface as the supplied user. + @param username The userid of the person authing to dispense + @param pin Thier pin """ - @staticmethod - def authUsernamePin(username, pin): + def authUsernamePin(self, userId, pin): pass """ Create a new dispense interface as the supplied user. + @param cardId The card that someone is connecting to Dispense with """ - @staticmethod - def authMifare(cardId): + def authMifare(self, cardId): pass """ Add a MIFARE card for this user + @param cardId Card to add to a user account + @return 1 if added successfully, anything else otherwise """ def addCard(self, cardId): pass """ Check if creating the user worked correctly. + @return True if currently logged in as a user, false otherwise """ def isLoggedIn(self): pass """ - Get the users username. + Get the current users username. + @return The username of the current user. An empty string if not currently logged in. """ - def getUsername(self, user): + def getUsername(self): pass """ - Get the users current balance. + Get the current users balance. + @return the users balance. None if not logged in. """ - def getBalance(self, user): + def getBalance(self): pass """ Get the name and price of an item. - itemId is the number entered into the vending machine + @param itemId The number entered into the vending machine + @return (itemname, price) """ - @staticmethod def getItemInfo(itemId): pass """ Check if the user is disabled. + @return True if the user is disabled """ def isDisabled(self): pass """ Dispense an item for the current user. - itemId is the number entered into the vending machine + @param itemId The number entered into the vending machine """ def dispenseItem(self, itemId): pass + """ + Log the current user out + """ + def logOut(self): + pass + diff --git a/VendServer/OpenDispense.py b/VendServer/OpenDispense.py index f8cee0d..b4f481c 100644 --- a/VendServer/OpenDispense.py +++ b/VendServer/OpenDispense.py @@ -1,10 +1,3 @@ -from DispenseInterface import DispenseInterface -import os -import re -import pwd -from subprocess import Popen, PIPE -from LDAPConnector import get_uid,get_uname, set_card_id - """ Author: Mitchell Pomery (bobgeorge33) @@ -13,97 +6,128 @@ Most of this code has been copied out of VendServer.py, then had variables updat This is so VendServer can easily operate regardless of the current accounting backend. Documentation for this code can be found inder Dispence.DispenceInterface """ + +from DispenseInterface import DispenseInterface +import os +import re +import pwd +from subprocess import Popen, PIPE +from LDAPConnector import get_uid,get_uname, set_card_id + class OpenDispense(DispenseInterface): - _username = None - _disabled = True - _loggedIn = False + _username = "" + _disabled = True + _loggedIn = False _userId = None - def __init__(self, userId=None, username=None, loggedIn=False): - self._username = username - self._loggedIn = loggedIn - self._userId = userId - - acct, unused = Popen(['dispense', 'acct', self._username], close_fds=True, stdout=PIPE).communicate() - # this is fucking appalling - flags = acct[acct.find("(")+1:acct.find(")")].strip() - if 'disabled' in flags: - self._disabled = True - if 'internal' in flags: - self._disabled = True - self._disabled = False + def __init__(self, username=None, secret=False): + pass - @staticmethod - def authUserIdPin(userId, pin): + def authUserIdPin(self, userId, pin): try: # Get info from - info = pwd.getpwuid(userId) - except KeyError: - logging.info('getting pin for uid %d: user not in password file'%uid) - return None - - if info.pw_dir == None: return False - pinfile = os.path.join(info.pw_dir, '.pin') - try: - s = os.stat(pinfile) - except OSError: - logging.info('getting pin for uid %d: .pin not found in home directory'%uid) - return None - if s.st_mode & 077: - logging.info('getting pin for uid %d: .pin has wrong permissions. Fixing.'%uid) - os.chmod(pinfile, 0600) - try: - f = file(pinfile) - except IOError: - logging.info('getting pin for uid %d: I cannot read pin file'%uid) - return None - pinstr = f.readline().strip() - f.close() - if not re.search('^[0-9]{4}$', pinstr): - logging.info('getting pin for uid %d: %s not a good pin'%(uid,repr(pinstr))) - return None - return OpenDispense(userId, info.pw_name, (int(pin)==int(pinstr))) + info = pwd.getpwuid(userId) + except KeyError: + logging.info('getting pin for uid %d: user not in password file'%userId) + return False - @staticmethod - def authMifareCard(cardId): - return OpenDispense(get_uid(cardId), get_uname(get_uid(cardId)), True) + if info.pw_dir == None: return False + pinfile = os.path.join(info.pw_dir, '.pin') + try: + s = os.stat(pinfile) + except OSError: + logging.info('getting pin for uid %d: .pin not found in home directory'%userId) + return False + if s.st_mode & 077: + logging.info('getting pin for uid %d: .pin has wrong permissions. Fixing.'%userId) + os.chmod(pinfile, 0600) + try: + f = file(pinfile) + except IOError: + logging.info('getting pin for uid %d: I cannot read pin file'%userId) + return False + pinstr = f.readline().strip() + f.close() + if not re.search('^[0-9]{4}$', pinstr): + logging.info('getting pin for uid %d: %s not a good pin'%(userId,repr(pinstr))) + return False + + if pinstr == str(pin): + #Login Successful + self._userid = userId + self._loggedIn = True + self._disabled = False + self._username = info.pw_name + return True + + # Login Unsuccessful + return False + + def authMifareCard(self, cardId): + # Get the users ID + self._userid = get_uid(cardId) + + # Check for thier username + try: + # Get info from + info = pwd.getpwuid(userId) + except KeyError: + logging.info('getting pin for uid %d: user not in password file'%uid) + return False + + # If we get this far all is good + self._loggedIn = True + self._disabled = False + self._username = info.pw_name + return True def addCard(self, cardId): - set_card_id(self._userId, cardId) + if self.isLoggedIn(): + set_card_id(self._userId, cardId) + return True - def isLoggedIn(self): - return self._loggedIn + def isLoggedIn(self): + return self._loggedIn - def getUsername(self): - return self._username + def getUsername(self): + return self._username - def getBalance(self): + def getBalance(self): # Balance checking - acct, unused = Popen(['dispense', 'acct', self._username], close_fds=True, stdout=PIPE).communicate() - # this is fucking appalling - balance = acct[acct.find("$")+1:acct.find("(")].strip() - return balance + if self.isLoggedIn(): + acct, unused = Popen(['dispense', 'acct', self._username], close_fds=True, stdout=PIPE).communicate() + else: + return None + balance = acct[acct.find("$")+1:acct.find("(")].strip() + return balance - def getItemInfo(itemId): + def getItemInfo(self, itemId): itemId = OpenDispenseMapping.vendingMachineToOpenDispense(itemId) args = ('dispense', 'iteminfo', itemId) - info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate() - m = re.match("\s*[a-z]+:\d+\s+(\d+)\.(\d\d)\s+([^\n]+)", info) - cents = int(m.group(1))*100 + int(m.group(2)) + info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate() + m = re.match("\s*[a-z]+:\d+\s+(\d+)\.(\d\d)\s+([^\n]+)", info) + if m == None: + return("dead", 0) + cents = int(m.group(1))*100 + int(m.group(2)) # return (name, price in cents) - return (m.group(3), cents) + return (m.group(3), cents) - def isDisabled(self): - return False + def isDisabled(self): + return self._disabled - def dispenseItem(self, itemId): - itemId = OpenDispenseMapping.vendingMachineToOpenDispense(itemId) - if itemId == "": + def dispenseItem(self, itemId): + if not self.isLoggedIn() or self.getItemInfo(itemId)[0] == "dead": return False else: print('dispense -u "%s" %s'%(self._username, itemId)) - os.system('dispense -u "%s" %s'%(self._username, itemId)) - return True + #os.system('dispense -u "%s" %s'%(self._username, itemId)) + return True + + def logOut(self): + self._username = "" + self._disabled = True + self._loggedIn = False + self._userId = None """ This class abstracts the idea of item numbers. -- 2.20.1