b4f481c54dd80b677a3212961363c94bf7c01da5
[uccvend-vendserver.git] / VendServer / OpenDispense.py
1 """
2 Author: Mitchell Pomery (bobgeorge33)
3
4 System to connect to OpenDispense2.
5 Most of this code has been copied out of VendServer.py, then had variables updated so that it runs.
6 This is so VendServer can easily operate regardless of the current accounting backend.
7 Documentation for this code can be found inder Dispence.DispenceInterface
8 """
9
10 from DispenseInterface import DispenseInterface
11 import os
12 import re
13 import pwd
14 from subprocess import Popen, PIPE
15 from LDAPConnector import get_uid,get_uname, set_card_id
16
17 class OpenDispense(DispenseInterface):
18         _username = ""
19         _disabled = True
20         _loggedIn = False
21         _userId = None
22
23         def __init__(self, username=None, secret=False):
24                 pass
25
26         def authUserIdPin(self, userId, pin):
27                 try:
28                         # Get info from 
29                         info = pwd.getpwuid(userId)
30                 except KeyError:
31                         logging.info('getting pin for uid %d: user not in password file'%userId)
32                         return False
33
34                 if info.pw_dir == None: return False
35                 pinfile = os.path.join(info.pw_dir, '.pin')
36                 try:
37                         s = os.stat(pinfile)
38                 except OSError:
39                         logging.info('getting pin for uid %d: .pin not found in home directory'%userId)
40                         return False
41                 if s.st_mode & 077:
42                         logging.info('getting pin for uid %d: .pin has wrong permissions. Fixing.'%userId)
43                         os.chmod(pinfile, 0600)
44                 try:
45                         f = file(pinfile)
46                 except IOError:
47                         logging.info('getting pin for uid %d: I cannot read pin file'%userId)
48                         return False
49                 pinstr = f.readline().strip()
50                 f.close()
51                 if not re.search('^[0-9]{4}$', pinstr):
52                         logging.info('getting pin for uid %d: %s not a good pin'%(userId,repr(pinstr)))
53                         return False
54
55                 if pinstr == str(pin):
56                         #Login Successful
57                         self._userid = userId
58                         self._loggedIn = True
59                         self._disabled = False
60                         self._username = info.pw_name
61                         return True
62                 
63                 # Login Unsuccessful
64                 return False
65
66         def authMifareCard(self, cardId):
67                 # Get the users ID
68                 self._userid = get_uid(cardId)
69
70                 # Check for thier username
71                 try:
72                         # Get info from 
73                         info = pwd.getpwuid(userId)
74                 except KeyError:
75                         logging.info('getting pin for uid %d: user not in password file'%uid)
76                         return False
77
78                 # If we get this far all is good
79                 self._loggedIn = True
80                 self._disabled = False
81                 self._username = info.pw_name
82                 return True
83
84         def addCard(self, cardId):
85                 if self.isLoggedIn():
86                         set_card_id(self._userId, cardId)
87                 return True
88
89         def isLoggedIn(self):
90                 return self._loggedIn
91
92         def getUsername(self):
93                 return self._username
94
95         def getBalance(self):
96                 # Balance checking
97                 if self.isLoggedIn():
98                         acct, unused = Popen(['dispense', 'acct', self._username], close_fds=True, stdout=PIPE).communicate()
99                 else:
100                         return None
101                 balance = acct[acct.find("$")+1:acct.find("(")].strip()
102                 return balance
103
104         def getItemInfo(self, itemId):
105                 itemId = OpenDispenseMapping.vendingMachineToOpenDispense(itemId)
106                 args = ('dispense', 'iteminfo', itemId)
107                 info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate()
108                 m = re.match("\s*[a-z]+:\d+\s+(\d+)\.(\d\d)\s+([^\n]+)", info)
109                 if m == None:
110                         return("dead", 0)
111                 cents = int(m.group(1))*100 + int(m.group(2))
112                 # return (name, price in cents)
113                 return (m.group(3), cents)
114
115         def isDisabled(self):
116                 return self._disabled
117
118         def dispenseItem(self, itemId):
119                 if not self.isLoggedIn() or self.getItemInfo(itemId)[0] == "dead":
120                         return False
121                 else:
122                         print('dispense -u "%s" %s'%(self._username, itemId))
123                         #os.system('dispense -u "%s" %s'%(self._username, itemId))
124                         return True
125
126         def logOut(self):
127                 self._username = ""
128                 self._disabled = True
129                 self._loggedIn = False
130                 self._userId = None
131
132 """
133 This class abstracts the idea of item numbers.
134 It removes the need for VendServer to know the mappings between inputted numbers
135 and the equivalent itemId in OpenDispense.
136 """
137 class OpenDispenseMapping():
138
139         @staticmethod
140         def vendingMachineToOpenDispense(itemId):
141                 _mappingFile = "OpenDispenseMappings.conf"
142                 fh = open(_mappingFile)
143                 map = ""
144                 for line in fh:
145                         #line = line.strip()
146                         if line.startswith(str(itemId) + " "):
147                                 map = line[len(str(itemId)) + 1:].strip()
148                                 print(map)
149                 return map
150

UCC git Repository :: git.ucc.asn.au