Changeset 1041 for pykota/trunk/pykota
- Timestamp:
- 06/25/03 16:10:01 (21 years ago)
- Location:
- pykota/trunk/pykota
- Files:
-
- 8 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/pykota/accounters/external.py
r1000 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.4 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.3 2003/05/27 23:00:21 jalet 24 27 # Big rewrite of external accounting methods. … … 41 44 42 45 class Accounter(AccounterBase) : 43 def doAccounting(self, printer id, userid) :46 def doAccounting(self, printer, user) : 44 47 """Deletgates the computation of the job size to an external command. 45 48 … … 50 53 51 54 # get last job information for this printer 52 pgc = self.filter.storage.getPrinterPageCounter(printerid) 53 if pgc is None : 55 if not printer.LastJob.Exists : 54 56 # The printer hasn't been used yet, from PyKota's point of view 55 57 counterbeforejob = 0 … … 58 60 # Last lifetime page counter before actual job is 59 61 # last page counter + last job size 60 counterbeforejob = (pgc["pagecounter"] or 0) + (pgc["jobsize"]or 0)62 counterbeforejob = int(printer.LastJob.PrinterPageCounter or 0) + int(printer.LastJob.JobSize or 0) 61 63 62 64 # Is the current user allowed to print at all ? 63 action = self.filter.warnUserPQuota(self.filter.username, self.filter.printername) 65 userpquota = self.filter.storage.getUserPQuota(user, printer) 66 action = self.filter.warnUserPQuota(userpquota) 64 67 65 68 # update the quota for the current user on this printer, if allowed to print … … 67 70 jobsize = 0 68 71 else : 69 self.filter.storage.updateUserPQuota(userid, printerid,jobsize)72 userpquota.increasePagesUsage(jobsize) 70 73 71 74 # adds the current job to history 72 self.filter.storage.addJobToHistory(self.filter.jobid, self.filter.storage.getUserId(self.filter.username), printerid, counterbeforejob, action, jobsize)75 printer.addJobToHistory(self.filter.jobid, user, counterbeforejob, action, jobsize) 73 76 74 77 return action … … 102 105 # launches child process 103 106 command = "%s <%s >%s 2>%s" % (self.arguments, infilename, outfilename, errfilename) 104 o = open("/tmp/comm", "w")105 o.write("%s\n" % command)106 o.close()107 107 retcode = os.system(command) 108 108 -
pykota/trunk/pykota/accounters/querying.py
r988 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.4 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.3 2003/05/06 14:55:47 jalet 24 27 # Missing import ! … … 38 41 from pykota.requester import openRequester, PyKotaRequesterError 39 42 40 MAXTRIES = 6# maximum number of tries to get the printer's internal page counter43 MAXTRIES = 12 # maximum number of tries to get the printer's internal page counter 41 44 TIMETOSLEEP = 10 # number of seconds to sleep between two tries to get the printer's internal page counter 42 45 43 46 class Accounter(AccounterBase) : 44 def doAccounting(self, printer id, userid) :47 def doAccounting(self, printer, user) : 45 48 """Does print accounting and returns if the job status is ALLOW or DENY.""" 46 49 # Get the page counter directly from the printer itself … … 65 68 66 69 # get last job information for this printer 67 pgc = self.filter.storage.getPrinterPageCounter(printerid) 68 if pgc is None : 70 if not printer.LastJob.Exists : 69 71 # The printer hasn't been used yet, from PyKota's point of view 70 lasthistoryid = None 71 lastjobid = self.filter.jobid 72 lastuserid = userid 73 lastusername = self.filter.username 72 lastjob = None 73 lastuser = user 74 74 lastpagecounter = counterbeforejob 75 75 else : 76 76 # get last values from Quota Storage 77 (lasthistoryid, lastjobid, lastuserid, lastusername, lastpagecounter) = (pgc["id"], pgc["jobid"], pgc["userid"], pgc["username"], pgc["pagecounter"]) 77 lastjob = printer.LastJob 78 lastuser = printer.LastJob.User 79 lastpagecounter = printer.LastJob.PrinterPageCounter 78 80 79 81 # if printer is off then we assume the correct counter value is the last one … … 107 109 # For more accurate accounting, don't switch off your HP printers ! 108 110 # explanation at : http://web.mit.edu/source/third/lprng/doc/LPRng-HOWTO-15.html 109 self.filter.logger.log_message(_("Error in page count value %i for user %s on printer %s") % (jobsize, lastuser name, self.filter.printername), "error")111 self.filter.logger.log_message(_("Error in page count value %i for user %s on printer %s") % (jobsize, lastuser.Name, self.filter.printername), "error") 110 112 jobsize = abs(int((10 - abs(jobsize)) / 2)) # Workaround for HP printers' feature ! 111 113 112 114 # update the quota for the previous user on this printer 113 self.filter.storage.updateUserPQuota(lastuserid, printerid, jobsize) 115 lastuserquota = self.filter.storage.getUserPQuota(lastuser, printer) 116 if lastuserquota.Exists : 117 lastuserquota.increasePagesUsage(jobsize) 114 118 115 119 # update the last job size in the history 116 self.filter.storage.updateJobSizeInHistory(lasthistoryid, jobsize) 120 if printer.LastJob.Exists : 121 printer.LastJob.setSize(jobsize) 117 122 118 123 # warns the last user if he is over quota 119 self.filter.warnUserPQuota(lastusername, self.filter.printername) 124 if lastuserquota.Exists : 125 self.filter.warnUserPQuota(lastuserquota) 120 126 121 127 # Is the current user allowed to print at all ? 122 action = self.filter.warnUserPQuota(self.filter. username, self.filter.printername)128 action = self.filter.warnUserPQuota(self.filter.storage.getUserPQuota(user, printer)) 123 129 124 130 # adds the current job to history 125 self.filter.storage.addJobToHistory(self.filter.jobid, self.filter.storage.getUserId(self.filter.username), printerid, counterbeforejob, action)131 printer.addJobToHistory(self.filter.jobid, user, counterbeforejob, action) 126 132 127 133 return action -
pykota/trunk/pykota/accounters/stupid.py
r1000 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.4 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.3 2003/05/27 23:00:21 jalet 24 27 # Big rewrite of external accounting methods. … … 39 42 40 43 class Accounter(AccounterBase) : 41 def doAccounting(self, printer id, userid) :44 def doAccounting(self, printer, user) : 42 45 """Does print accounting by stupidly counting the 'showpage' postscript instructions in the document. 43 46 … … 51 54 52 55 # get last job information for this printer 53 pgc = self.filter.storage.getPrinterPageCounter(printerid) 54 if pgc is None : 56 if not printer.LastJob.Exists : 55 57 # The printer hasn't been used yet, from PyKota's point of view 56 58 counterbeforejob = 0 … … 59 61 # Last lifetime page counter before actual job is 60 62 # last page counter + last job size 61 counterbeforejob = (pgc["pagecounter"] or 0) + (pgc["jobsize"]or 0)63 counterbeforejob = int(printer.LastJob.PrinterPageCounter or 0) + int(printer.LastJob.JobSize or 0) 62 64 63 65 # Is the current user allowed to print at all ? 64 action = self.filter.warnUserPQuota(self.filter.username, self.filter.printername) 66 userpquota = self.filter.storage.getUserPQuota(user, printer) 67 action = self.filter.warnUserPQuota(userpquota) 65 68 66 69 # update the quota for the current user on this printer, if allowed to print … … 68 71 jobsize = 0 69 72 else : 70 self.filter.storage.updateUserPQuota(userid, printerid,jobsize)73 userpquota.increasePagesUsage(jobsize) 71 74 72 75 # adds the current job to history 73 self.filter.storage.addJobToHistory(self.filter.jobid, self.filter.storage.getUserId(self.filter.username), printerid, counterbeforejob, action, jobsize)76 printer.addJobToHistory(self.filter.jobid, user, counterbeforejob, action, jobsize) 74 77 75 78 return action -
pykota/trunk/pykota/config.py
r1029 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.30 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.29 2003/06/14 22:44:21 jalet 24 27 # More work on LDAP storage backend. … … 201 204 ldapinfo = {} 202 205 for option in [ "userbase", "userrdn", \ 206 "balancebase", "balancerdn", \ 203 207 "groupbase", "grouprdn", "groupmembers", \ 204 208 "printerbase", "printerrdn", \ -
pykota/trunk/pykota/storage.py
r1021 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.14 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.13 2003/06/10 16:37:54 jalet 24 27 # Deletion of the second user which is not needed anymore. … … 84 87 __str__ = __repr__ 85 88 89 class StorageObject : 90 """Object present in the Quota Storage.""" 91 def __init__(self, parent) : 92 "Initialize minimal data.""" 93 self.parent = parent 94 self.ident = None 95 self.Exists = 0 96 97 class StorageUser(StorageObject) : 98 """User class.""" 99 def __init__(self, parent, name) : 100 StorageObject.__init__(self, parent) 101 self.Name = name 102 self.LimitBy = None 103 self.AccountBalance = None 104 self.LifeTimePaid = None 105 106 def consumeAccountBalance(self, amount) : 107 """Consumes an amount of money from the user's account balance.""" 108 newbalance = float(self.AccountBalance or 0.0) - amount 109 self.parent.writeUserAccountBalance(self, newbalance) 110 self.AccountBalance = newbalance 111 112 def setAccountBalance(self, balance, lifetimepaid) : 113 """Sets the user's account balance in case he pays more money.""" 114 115 def setLimitBy(self, limitby) : 116 """Sets the user's limiting factor.""" 117 limitby = limitby.lower() 118 if limitby in ["quota", "balance"] : 119 self.parent.writeUserLimitBy(self, limitby) 120 self.LimitBy = limitby 121 122 def delete(self) : 123 """Deletes an user from the Quota Storage.""" 124 self.parent.beginTransaction() 125 try : 126 self.parent.deleteUser(self) 127 except PyKotaStorageError, msg : 128 self.parent.rollbackTransaction() 129 raise PyKotaStorageError, msg 130 else : 131 self.parent.commitTransaction() 132 133 class StorageGroup(StorageObject) : 134 """User class.""" 135 def __init__(self, parent, name) : 136 StorageObject.__init__(self, parent) 137 self.Name = name 138 self.LimitBy = None 139 self.AccountBalance = None 140 self.LifeTimePaid = None 141 142 def setLimitBy(self, limitby) : 143 """Sets the user's limiting factor.""" 144 limitby = limitby.lower() 145 if limitby in ["quota", "balance"] : 146 self.parent.writeGroupLimitBy(self, limitby) 147 self.LimitBy = limitby 148 149 def delete(self) : 150 """Deletes a group from the Quota Storage.""" 151 self.parent.beginTransaction() 152 try : 153 self.parent.deleteGroup(self) 154 except PyKotaStorageError, msg : 155 self.parent.rollbackTransaction() 156 raise PyKotaStorageError, msg 157 else : 158 self.parent.commitTransaction() 159 160 class StoragePrinter(StorageObject) : 161 """Printer class.""" 162 def __init__(self, parent, name) : 163 StorageObject.__init__(self, parent) 164 self.Name = name 165 self.PricePerPage = None 166 self.PricePerJob = None 167 self.LastJob = None 168 169 def addJobToHistory(self, jobid, user, pagecounter, action, jobsize=None) : 170 """Adds a job to the printer's history.""" 171 self.parent.writeJobNew(self, user, jobid, pagecounter, action, jobsize) 172 # TODO : update LastJob object ? Probably not needed. 173 174 def setPrices(self, priceperpage = None, priceperjob = None) : 175 """Sets the printer's prices.""" 176 if priceperpage is None : 177 priceperpage = self.PricePerPage 178 else : 179 self.PricePerPage = float(priceperpage) 180 if priceperjob is None : 181 priceperjob = self.PricePerJob 182 else : 183 self.PricePerJob = float(priceperjob) 184 self.parent.writePrinterPrices(self) 185 186 class StorageUserPQuota(StorageObject) : 187 """User Print Quota class.""" 188 def __init__(self, parent, user, printer) : 189 StorageObject.__init__(self, parent) 190 self.User = user 191 self.Printer = printer 192 self.PageCounter = None 193 self.LifePageCounter = None 194 self.SoftLimit = None 195 self.HardLimit = None 196 self.DateLimit = None 197 198 def setDateLimit(self, datelimit) : 199 """Sets the date limit for this quota.""" 200 date = "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second) 201 self.parent.writeUserPQuotaDateLimit(self, date) 202 self.DateLimit = date 203 204 def setLimits(self, softlimit, hardlimit) : 205 """Sets the soft and hard limit for this quota.""" 206 self.parent.writeUserPQuotaLimits(self, softlimit, hardlimit) 207 self.SoftLimit = softlimit 208 self.HardLimit = hardlimit 209 210 def reset(self) : 211 """Resets page counter to 0.""" 212 self.parent.writeUserPQuotaPagesCounters(self, 0, int(self.LifePageCounter or 0)) 213 self.PageCounter = 0 214 215 def increasePagesUsage(self, nbpages) : 216 """Increase the value of used pages and money.""" 217 if nbpages : 218 jobprice = (float(self.Printer.PricePerPage or 0.0) * nbpages) + float(self.Printer.PricePerJob or 0.0) 219 newpagecounter = int(self.PageCounter or 0) + nbpages 220 newlifepagecounter = int(self.LifePageCounter or 0) + nbpages 221 self.parent.beginTransaction() 222 try : 223 if jobprice : # optimization : don't access the database if unneeded. 224 self.User.consumeAccountBalance(jobprice) 225 self.parent.writeUserPQuotaPagesCounters(self, newpagecounter, newlifepagecounter) 226 except PyKotaStorageError, msg : 227 self.parent.rollbackTransaction() 228 raise PyKotaStorageError, msg 229 else : 230 self.parent.commitTransaction() 231 self.PageCounter = newpagecounter 232 self.LifePageCounter = newlifepagecounter 233 234 class StorageGroupPQuota(StorageObject) : 235 """Group Print Quota class.""" 236 def __init__(self, parent, group, printer) : 237 StorageObject.__init__(self, parent) 238 self.Group = group 239 self.Printer = printer 240 self.PageCounter = None 241 self.LifePageCounter = None 242 self.SoftLimit = None 243 self.HardLimit = None 244 self.DateLimit = None 245 246 def setDateLimit(self, datelimit) : 247 """Sets the date limit for this quota.""" 248 date = "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second) 249 self.parent.writeGroupPQuotaDateLimit(self, date) 250 self.DateLimit = date 251 252 def setLimits(self, softlimit, hardlimit) : 253 """Sets the soft and hard limit for this quota.""" 254 self.parent.writeGroupPQuotaLimits(self, softlimit, hardlimit) 255 self.SoftLimit = softlimit 256 self.HardLimit = hardlimit 257 258 class StorageLastJob(StorageObject) : 259 """Printer's Last Job class.""" 260 def __init__(self, parent, printer) : 261 StorageObject.__init__(self, parent) 262 self.Printer = printer 263 self.JobId = None 264 self.User = None 265 self.PrinterPageCounter = None 266 self.JobSize = None 267 self.JobAction = None 268 self.JobDate = None 269 270 def setSize(self, jobsize) : 271 """Sets the last job's size.""" 272 self.parent.writeLastJobSize(self, jobsize) 273 self.JobSize = jobsize 274 86 275 def openConnection(pykotatool) : 87 276 """Returns a connection handle to the appropriate Quota Storage Database.""" -
pykota/trunk/pykota/storages/ldapstorage.py
r1032 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.11 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.10 2003/06/16 21:55:15 jalet 24 27 # More work on LDAP, again. Problem detected. … … 66 69 import time 67 70 import md5 68 import fnmatch69 71 70 72 from pykota.storage import PyKotaStorageError 73 from pykota.storage import StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 71 74 72 75 try : … … 114 117 return md5.md5("%s" % time.time()).hexdigest() 115 118 119 def beginTransaction(self) : 120 """Starts a transaction.""" 121 if self.debug : 122 self.tool.logger.log_message("Transaction begins... WARNING : No transactions in LDAP !", "debug") 123 124 def commitTransaction(self) : 125 """Commits a transaction.""" 126 if self.debug : 127 self.tool.logger.log_message("Transaction committed. WARNING : No transactions in LDAP !", "debug") 128 129 def rollbackTransaction(self) : 130 """Rollbacks a transaction.""" 131 if self.debug : 132 self.tool.logger.log_message("Transaction aborted. WARNING : No transaction in LDAP !", "debug") 133 116 134 def doSearch(self, key, fields=None, base="", scope=ldap.SCOPE_SUBTREE) : 117 135 """Does an LDAP search query.""" … … 119 137 base = base or self.basedn 120 138 if self.debug : 121 self.tool.logger.log_message("QUERY : BaseDN : %s, Scope : %s, Filter : %s, Attributes : %s" % (base, scope, key, fields), "debug")139 self.tool.logger.log_message("QUERY : Filter : %s, BaseDN : %s, Scope : %s, Attributes : %s" % (key, base, scope, fields), "debug") 122 140 result = self.database.search_s(base or self.basedn, scope, key, fields) 123 141 except ldap.LDAPError : … … 139 157 return dn 140 158 141 def doModify(self, dn, fields) : 159 def doDelete(self, dn) : 160 """Deletes an entry from the LDAP directory.""" 161 try : 162 if self.debug : 163 self.tool.logger.log_message("QUERY : Delete(%s)" % dn, "debug") 164 self.database.delete_s(dn) 165 except ldap.LDAPError : 166 raise PyKotaStorageError, _("Problem deleting LDAP entry (%s)") % dn 167 168 def doModify(self, dn, fields, ignoreold=1) : 142 169 """Modifies an entry in the LDAP directory.""" 143 170 try : … … 145 172 if self.debug : 146 173 self.tool.logger.log_message("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry[0][1], fields), "debug") 147 self.database.modify_s(dn, modlist.modifyModlist(oldentry[0][1], fields, ignore_oldexistent= 1))174 self.database.modify_s(dn, modlist.modifyModlist(oldentry[0][1], fields, ignore_oldexistent=ignoreold)) 148 175 except ldap.LDAPError : 149 176 raise PyKotaStorageError, _("Problem modifying LDAP entry (%s, %s)") % (dn, fields) 150 177 else : 151 178 return dn 179 180 def getUser(self, username) : 181 """Extracts user information given its name.""" 182 user = StorageUser(self, username) 183 result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaLimitBy"], base=self.info["userbase"]) 184 if result : 185 fields = result[0][1] 186 user.ident = result[0][0] 187 user.LimitBy = fields.get("pykotaLimitBy")[0] 188 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["balancerdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"], base=self.info["balancebase"]) 189 if result : 190 fields = result[0][1] 191 user.idbalance = result[0][0] 192 user.AccountBalance = fields.get("pykotaBalance") 193 if user.AccountBalance is not None : 194 if user.AccountBalance[0].upper() == "NONE" : 195 user.AccountBalance = None 196 else : 197 user.AccountBalance = float(user.AccountBalance[0]) 198 user.AccountBalance = user.AccountBalance or 0.0 199 user.LifeTimePaid = fields.get("pykotaLifeTimePaid") 200 if user.LifeTimePaid is not None : 201 if user.LifeTimePaid[0].upper() == "NONE" : 202 user.LifeTimePaid = None 203 else : 204 user.LifeTimePaid = float(user.LifeTimePaid[0]) 205 user.LifeTimePaid = user.LifeTimePaid or 0.0 206 user.Exists = 1 207 return user 208 209 def getGroup(self, groupname) : 210 """Extracts group information given its name.""" 211 group = StorageGroup(self, groupname) 212 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), ["pykotaLimitBy"], base=self.info["groupbase"]) 213 if result : 214 fields = result[0][1] 215 group.ident = result[0][0] 216 group.LimitBy = fields.get("pykotaLimitBy")[0] 217 group.AccountBalance = 0.0 218 group.LifeTimePaid = 0.0 219 group.Members = self.getGroupMembers(group) 220 for member in group.Members : 221 group.AccountBalance += member.AccountBalance 222 group.LifeTimePaid += member.LifeTimePaid 223 group.Exists = 1 224 return group 225 226 def getPrinter(self, printername) : 227 """Extracts printer information given its name.""" 228 printer = StoragePrinter(self, printername) 229 result = self.doSearch("(&(objectClass=pykotaPrinter)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaPricePerPage", "pykotaPricePerJob"], base=self.info["printerbase"]) 230 if result : 231 fields = result[0][1] 232 printer.ident = result[0][0] 233 printer.PricePerJob = float(fields.get("pykotaPricePerJob")[0] or 0.0) 234 printer.PricePerPage = float(fields.get("pykotaPricePerPage")[0] or 0.0) 235 printer.LastJob = self.getPrinterLastJob(printer) 236 printer.Exists = 1 237 return printer 238 239 def getUserGroups(self, user) : 240 """Returns the user's groups list.""" 241 groups = [] 242 result = self.doSearch("(&(objectClass=pykotaGroup)(%s=%s))" % (self.info["groupmembers"], user.Name), [self.info["grouprdn"]], base=self.info["groupbase"]) 243 if result : 244 for (groupid, fields) in result : 245 groups.append(self.getGroup(fields.get(self.info["grouprdn"])[0])) 246 return groups 247 248 def getGroupMembers(self, group) : 249 """Returns the group's members list.""" 250 groupmembers = [] 251 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (group.Name, self.info["grouprdn"], group.Name), [self.info["groupmembers"]], base=self.info["groupbase"]) 252 if result : 253 for username in result[0][1].get(self.info["groupmembers"], []) : 254 groupmembers.append(self.getUser(username)) 255 return groupmembers 256 257 def getUserPQuota(self, user, printer) : 258 """Extracts a user print quota.""" 259 userpquota = StorageUserPQuota(self, user, printer) 260 if user.Exists : 261 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaUserName=%s)(pykotaPrinterName=%s))" % (user.Name, printer.Name), ["pykotaPageCounter", "pykotaLifePageCounter", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=self.info["userquotabase"]) 262 if result : 263 fields = result[0][1] 264 userpquota.ident = result[0][0] 265 userpquota.PageCounter = int(fields.get("pykotaPageCounter")[0] or 0) 266 userpquota.LifePageCounter = int(fields.get("pykotaLifePageCounter")[0] or 0) 267 userpquota.SoftLimit = fields.get("pykotaSoftLimit") 268 if userpquota.SoftLimit is not None : 269 if userpquota.SoftLimit[0].upper() == "NONE" : 270 userpquota.SoftLimit = None 271 else : 272 userpquota.SoftLimit = int(userpquota.SoftLimit[0]) 273 userpquota.HardLimit = fields.get("pykotaHardLimit") 274 if userpquota.HardLimit is not None : 275 if userpquota.HardLimit[0].upper() == "NONE" : 276 userpquota.HardLimit = None 277 elif userpquota.HardLimit is not None : 278 userpquota.HardLimit = int(userpquota.HardLimit[0]) 279 userpquota.DateLimit = fields.get("pykotaDateLimit") 280 if userpquota.DateLimit is not None : 281 if userpquota.DateLimit[0].upper() == "NONE" : 282 userpquota.DateLimit = None 283 else : 284 userpquota.DateLimit = userpquota.DateLimit[0] 285 userpquota.Exists = 1 286 return userpquota 287 288 def getGroupPQuota(self, group, printer) : 289 """Extracts a group print quota.""" 290 grouppquota = StorageGroupPQuota(self, group, printer) 291 if group.Exists : 292 result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaGroupName=%s)(pykotaPrinterName=%s))" % (group.Name, printer.Name), ["pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=self.info["groupquotabase"]) 293 if result : 294 fields = result[0][1] 295 grouppquota.ident = result[0][0] 296 grouppquota.SoftLimit = fields.get("pykotaSoftLimit") 297 if grouppquota.SoftLimit is not None : 298 if grouppquota.SoftLimit[0].upper() == "NONE" : 299 grouppquota.SoftLimit = None 300 else : 301 grouppquota.SoftLimit = int(grouppquota.SoftLimit[0]) 302 grouppquota.HardLimit = fields.get("pykotaHardLimit") 303 if grouppquota.HardLimit is not None : 304 if grouppquota.HardLimit[0].upper() == "NONE" : 305 grouppquota.HardLimit = None 306 else : 307 grouppquota.HardLimit = int(grouppquota.HardLimit[0]) 308 grouppquota.DateLimit = fields.get("pykotaDateLimit") 309 if grouppquota.DateLimit is not None : 310 if grouppquota.DateLimit[0].upper() == "NONE" : 311 grouppquota.DateLimit = None 312 else : 313 grouppquota.DateLimit = grouppquota.DateLimit[0] 314 grouppquota.PageCounter = 0 315 grouppquota.LifePageCounter = 0 316 if (not hasattr(group, "Members")) or (group.Members is None) : 317 group.Members = self.getGroupMembers(group) 318 usernamesfilter = "".join(["(pykotaUserName=%s)" % member.Name for member in group.Members]) 319 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaPrinterName=%s)(|%s))" % (printer.Name, usernamesfilter), ["pykotaPageCounter", "pykotaLifePageCounter"], base=self.info["userquotabase"]) 320 if result : 321 for userpquota in result : 322 grouppquota.PageCounter += int(userpquota[1].get("pykotaPageCounter")[0] or 0) 323 grouppquota.LifePageCounter += int(userpquota[1].get("pykotaLifePageCounter")[0] or 0) 324 grouppquota.Exists = 1 325 return grouppquota 326 327 def getPrinterLastJob(self, printer) : 328 """Extracts a printer's last job information.""" 329 lastjob = StorageLastJob(self, printer) 330 result = self.doSearch("(&(objectClass=pykotaLastjob)(|(pykotaPrinterName=%s)(%s=%s)))" % (printer.Name, self.info["printerrdn"], printer.Name), ["pykotaLastJobIdent"], base=self.info["lastjobbase"]) 331 if result : 332 lastjob.lastjobident = result[0][0] 333 lastjobident = result[0][1]["pykotaLastJobIdent"][0] 334 result = self.doSearch("objectClass=pykotaJob", ["pykotaUserName", "pykotaJobId", "pykotaPrinterPageCounter", "pykotaJobSize", "pykotaAction", "createTimestamp"], base="cn=%s,%s" % (lastjobident, self.info["jobbase"]), scope=ldap.SCOPE_BASE) 335 if result : 336 fields = result[0][1] 337 lastjob.ident = result[0][0] 338 lastjob.JobId = fields.get("pykotaJobId")[0] 339 lastjob.User = self.getUser(fields.get("pykotaUserName")[0]) 340 lastjob.PrinterPageCounter = int(fields.get("pykotaPrinterPageCounter")[0] or 0) 341 lastjob.JobSize = int(fields.get("pykotaJobSize", [0])[0]) 342 lastjob.JobAction = fields.get("pykotaAction")[0] 343 date = fields.get("createTimestamp")[0] 344 year = int(date[:4]) 345 month = int(date[4:6]) 346 day = int(date[6:8]) 347 hour = int(date[8:10]) 348 minute = int(date[10:12]) 349 second = int(date[12:14]) 350 lastjob.JobDate = "%04i-%02i-%02i %02i:%02i:%02i" % (year, month, day, hour, minute, second) 351 lastjob.Exists = 1 352 return lastjob 152 353 153 354 def getMatchingPrinters(self, printerpattern) : 154 """Returns the list of all printers as tuples (id, name) for printer names which match a certain pattern.""" 155 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName"], base=self.info["printerbase"]) 156 if result : 157 return [(printerid, printer["pykotaPrinterName"][0]) for (printerid, printer) in result if fnmatch.fnmatchcase(printer["pykotaPrinterName"][0], printerpattern)] 158 159 def getPrinterId(self, printername) : 160 """Returns a printerid given a printername.""" 161 result = self.doSearch("(&(objectClass=pykotaPrinter)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaPrinterName"], base=self.info["printerbase"]) 162 if result : 163 return result[0][0] 164 165 def getPrinterName(self, printerid) : 166 """Returns a printerid given a printer id.""" 167 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName"], base=printerid, scope=ldap.SCOPE_BASE) 168 if result : 169 return result[0][1]["pykotaPrinterName"][0] 170 171 def getPrinterPrices(self, printerid) : 172 """Returns a printer prices per page and per job given a printerid.""" 173 result = self.doSearch("(|(pykotaPrinterName=*)(%s=*))" % self.info["printerrdn"], ["pykotaPricePerPage", "pykotaPricePerJob"], base=printerid, scope=ldap.SCOPE_BASE) 174 if result : 175 return (float(result[0][1]["pykotaPricePerPage"][0]), float(result[0][1]["pykotaPricePerJob"][0])) 176 177 def setPrinterPrices(self, printerid, perpage, perjob) : 178 """Sets prices per job and per page for a given printer.""" 179 fields = { 180 "pykotaPricePerPage" : str(perpage), 181 "pykotaPricePerJob" : str(perjob), 182 } 183 return self.doModify(printerid, fields) 184 185 def getUserId(self, username) : 186 """Returns a userid given a username.""" 187 result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), [self.info["userrdn"]], base=self.info["userbase"]) 188 if result : 189 return result[0][0] 190 191 def getUserName(self, userid) : 192 """Returns a username given a userid.""" 193 result = self.doSearch("objectClass=pykotaAccount", ["pykotaUserName"], base=userid, scope=ldap.SCOPE_BASE) 194 if result : 195 return result[0][1]["pykotaUserName"][0] 196 197 def getGroupId(self, groupname) : 198 """Returns a groupid given a grupname.""" 199 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), [self.info["grouprdn"]], base=self.info["groupbase"]) 200 if result is not None : 201 (groupid, dummy) = result[0] 202 return groupid 203 204 def getJobHistoryId(self, jobid, userid, printerid) : 205 """Returns the history line's id given a (jobid, userid, printerid). 206 207 TODO : delete because shouldn't be needed by the LDAP backend 208 """ 209 raise PyKotaStorageError, "Not implemented !" 210 211 def getPrinterUsers(self, printerid) : 212 """Returns the list of userids and usernames which uses a given printer.""" 213 # first get the printer's name from the id 214 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE) 215 if result : 216 fields = result[0][1] 217 printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0] 218 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaPrinterName=%s))" % printername, ["pykotaUserName"], base=self.info["userquotabase"]) 219 if result : 220 return [(pquotauserid, fields["pykotaUserName"][0]) for (pquotauserid, fields) in result] 221 222 def getPrinterGroups(self, printerid) : 223 """Returns the list of groups which uses a given printer.""" 224 # first get the printer's name from the id 225 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE) 226 if result : 227 fields = result[0][1] 228 printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0] 229 result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaPrinterName=%s))" % printername, ["pykotaGroupName"], base=self.info["groupquotabase"]) 230 if result : 231 return [(pquotagroupid, fields["pykotaGroupName"][0]) for (pquotagroupid, fields) in result] 232 233 def getGroupMembersNames(self, groupname) : 234 """Returns the list of user's names which are member of this group.""" 235 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), [self.info["groupmembers"]]) 236 if result : 237 fields = result[0][1] 238 return fields.get(self.info["groupmembers"]) 239 240 def getUserGroupsNames(self, userid) : 241 """Returns the list of groups' names the user is a member of.""" 242 username = self.getUserName(userid) 243 if username : 244 result = self.doSearch("(&(objectClass=pykotaGroup)(%s=%s))" % (self.info["groupmembers"], username), [self.info["grouprdn"]], base=self.info["groupbase"]) 245 if result : 246 return [v[self.info["grouprdn"]][0] for (k, v) in result] 247 return [] 355 """Returns the list of all printers for which name matches a certain pattern.""" 356 printers = [] 357 # see comment at the same place in pgstorage.py 358 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", "pykotaPricePerPage", "pykotaPricePerJob"], base=self.info["printerbase"]) 359 if result : 360 for (printerid, fields) in result : 361 printername = fields["pykotaPrinterName"][0] 362 if self.tool.matchString(printername, [ printerpattern ]) : 363 printer = StoragePrinter(self, printername) 364 printer.ident = printerid 365 printer.PricePerJob = float(fields.get("pykotaPricePerJob")[0] or 0.0) 366 printer.PricePerPage = float(fields.get("pykotaPricePerPage")[0] or 0.0) 367 printer.LastJob = self.getPrinterLastJob(printer) 368 printer.Exists = 1 369 printers.append(printer) 370 return printers 371 372 def getPrinterUsersAndQuotas(self, printer, names=None) : 373 """Returns the list of users who uses a given printer, along with their quotas.""" 374 usersandquotas = [] 375 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaPrinterName=%s))" % printer.Name, ["pykotaUserName", "pykotaPageCounter", "pykotaLifePageCounter", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=self.info["userquotabase"]) 376 if result : 377 for (userquotaid, fields) in result : 378 user = self.getUser(fields["pykotaUserName"][0]) 379 if (names is None) or self.tool.matchString(user.Name, names) : 380 userpquota = StorageUserPQuota(self, user, printer) 381 userpquota.ident = userquotaid 382 userpquota.PageCounter = int(fields.get("pykotaPageCounter")[0] or 0) 383 userpquota.LifePageCounter = int(fields.get("pykotaLifePageCounter")[0] or 0) 384 userpquota.SoftLimit = fields.get("pykotaSoftLimit") 385 if userpquota.SoftLimit is not None : 386 if userpquota.SoftLimit[0].upper() == "NONE" : 387 userpquota.SoftLimit = None 388 else : 389 userpquota.SoftLimit = int(userpquota.SoftLimit[0]) 390 userpquota.HardLimit = fields.get("pykotaHardLimit") 391 if userpquota.HardLimit is not None : 392 if userpquota.HardLimit[0].upper() == "NONE" : 393 userpquota.HardLimit = None 394 elif userpquota.HardLimit is not None : 395 userpquota.HardLimit = int(userpquota.HardLimit[0]) 396 userpquota.DateLimit = fields.get("pykotaDateLimit") 397 if userpquota.DateLimit is not None : 398 if userpquota.DateLimit[0].upper() == "NONE" : 399 userpquota.DateLimit = None 400 else : 401 userpquota.DateLimit = userpquota.DateLimit[0] 402 userpquota.Exists = 1 403 usersandquotas.append((user, userpquota)) 404 return usersandquotas 405 406 def getPrinterGroupsAndQuotas(self, printer, names=None) : 407 """Returns the list of groups which uses a given printer, along with their quotas.""" 408 groupsandquotas = [] 409 result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaPrinterName=%s))" % printer.Name, ["pykotaGroupName"], base=self.info["groupquotabase"]) 410 if result : 411 for (groupquotaid, fields) in result : 412 group = self.getGroup(fields.get("pykotaGroupName")[0]) 413 if (names is None) or self.tool.matchString(user.Name, names) : 414 grouppquota = self.getGroupPQuota(group, printer) 415 groupsandquotas.append((group, grouppquota)) 416 return groupsandquotas 248 417 249 418 def addPrinter(self, printername) : 250 """Adds a printer to the quota storage, returns it s id."""419 """Adds a printer to the quota storage, returns it.""" 251 420 fields = { self.info["printerrdn"] : printername, 252 421 "objectClass" : ["pykotaObject", "pykotaPrinter"], 422 "cn" : printername, 253 423 "pykotaPrinterName" : printername, 254 424 "pykotaPricePerPage" : "0.0", … … 256 426 } 257 427 dn = "%s=%s,%s" % (self.info["printerrdn"], printername, self.info["printerbase"]) 258 returnself.doAdd(dn, fields)259 260 def addUser(self, username) :261 """Adds a user to the quota storage, returns its id."""262 fields = { self.info["userrdn"] : username,263 "objectClass" : ["pykotaObject", "pykotaAccount", "pykotaAccountBalance"],264 " pykotaUserName" : username,265 " pykotaLimitBy" : "quota",266 "pykota Balance" : "0.0",267 "pykotaLi feTimePaid" : "0.0",428 self.doAdd(dn, fields) 429 return self.getPrinter(printername) 430 431 def addUser(self, user) : 432 """Adds a user to the quota storage, returns it.""" 433 fields = { self.info["userrdn"] : user.Name, 434 "objectClass" : ["pykotaObject", "pykotaAccount"], 435 "cn" : user.Name, 436 "pykotaUserName" : user.Name, 437 "pykotaLimitBY" : (user.LimitBy or "quota"), 268 438 } 269 dn = "%s=%s,%s" % (self.info["userrdn"], username, self.info["userbase"]) 270 return self.doAdd(dn, fields) 271 272 def addGroup(self, groupname) : 273 """Adds a group to the quota storage, returns its id.""" 274 fields = { self.info["grouprdn"] : groupname, 439 dn = "%s=%s,%s" % (self.info["userrdn"], user.Name, self.info["userbase"]) 440 self.doAdd(dn, fields) 441 fields = { 442 "objectClass" : ["pykotaObject", "pykotaAccountBalance"], 443 "cn" : user.Name, 444 "pykotaUserName" : user.Name, 445 "pykotaBalance" : str(user.AccountBalance or 0.0), 446 "pykotaLifeTimePaid" : str(user.LifeTimePaid or 0.0), 447 } 448 dn = "cn=%s,%s" % (user.Name, self.info["balancebase"]) 449 self.doAdd(dn, fields) 450 return self.getUser(user.Name) 451 452 def addGroup(self, group) : 453 """Adds a group to the quota storage, returns it.""" 454 fields = { self.info["grouprdn"] : group.Name, 275 455 "objectClass" : ["pykotaObject", "pykotaGroup"], 276 "pykotaGroupName" : groupname, 277 "pykotaLimitBy" : "quota", 456 "cn" : group.Name, 457 "pykotaGroupName" : group.Name, 458 "pykotaLimitBY" : (group.LimitBy or "quota"), 278 459 } 279 dn = "%s=%s,%s" % (self.info["grouprdn"], groupname, self.info["groupbase"]) 280 return self.doAdd(dn, fields) 281 282 def addUserPQuota(self, username, printerid) : 283 """Initializes a user print quota on a printer, adds the user to the quota storage if needed.""" 460 dn = "%s=%s,%s" % (self.info["grouprdn"], group.Name, self.info["groupbase"]) 461 self.doAdd(dn, fields) 462 return self.getGroup(group.Name) 463 464 def addUserToGroup(self, user, group) : 465 """Adds an user to a group.""" 466 if user.Name not in [u.Name for u in group.Members] : 467 result = self.doSearch("objectClass=pykotaGroup", None, base=group.ident, scope=ldap.SCOPE_BASE) 468 if result : 469 fields = result[0][1] 470 fields[self.info["groupmembers"]].append(user.Name) 471 self.doModify(group.ident, fields) 472 group.Members.append(user) 473 474 def addUserPQuota(self, user, printer) : 475 """Initializes a user print quota on a printer.""" 284 476 uuid = self.genUUID() 285 fields = { "objectClass" : ["pykotaObject", "pykotaUserPQuota"], 286 "cn" : uuid, 287 "pykotaUserName" : username, 288 "pykotaPrinterName" : self.getPrinterName(printerid), 477 fields = { "cn" : uuid, 478 "objectClass" : ["pykotaObject", "pykotaUserPQuota"], 479 "pykotaUserName" : user.Name, 480 "pykotaPrinterName" : printer.Name, 481 "pykotaDateLimit" : "None", 289 482 "pykotaPageCounter" : "0", 290 483 "pykotaLifePageCounter" : "0", 291 "pykotaSoftLimit" : "0",292 "pykotaHardLimit" : "0",293 "pykotaDateLimit" : "None",294 484 } 295 485 dn = "cn=%s,%s" % (uuid, self.info["userquotabase"]) 296 486 self.doAdd(dn, fields) 297 return (dn, printerid)298 299 def addGroupPQuota(self, group name, printerid) :300 """Initializes a group print quota on a printer , adds the group to the quota storage if needed."""487 return self.getUserPQuota(user, printer) 488 489 def addGroupPQuota(self, group, printer) : 490 """Initializes a group print quota on a printer.""" 301 491 uuid = self.genUUID() 302 fields = { "objectClass" : ["pykotaObject", "pykotaGroupPQuota"], 303 "cn" : uuid, 304 "pykotaGroupName" : groupname, 305 "pykotaPrinterName" : self.getPrinterName(printerid), 306 "pykotaSoftLimit" : "0", 307 "pykotaHardLimit" : "0", 492 fields = { "cn" : uuid, 493 "objectClass" : ["pykotaObject", "pykotaGroupPQuota"], 494 "pykotaGroupName" : group.Name, 495 "pykotaPrinterName" : printer.Name, 308 496 "pykotaDateLimit" : "None", 309 497 } 310 498 dn = "cn=%s,%s" % (uuid, self.info["groupquotabase"]) 311 499 self.doAdd(dn, fields) 312 return (dn, printerid) 313 314 def increaseUserBalance(self, userquotaid, amount) : 315 """Increases (or decreases) an user's account balance by a given amount.""" 316 balance = self.getUserBalance(userquotaid) 317 if balance : 318 (newbal, newpaid) = [(float(v) + float(amount)) for v in balance] 319 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE) 320 if result : 321 username = result[0][1]["pykotaUserName"][0] 322 if username : 323 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(pykotaUserName=%s))" % username , [ "pykotaBalance", "pykotaLifeTimePaid"]) 324 fields = { 325 "pykotaBalance" : str(newbal), 326 "pykotaLifeTimePaid" : str(newpaid), 327 } 328 return self.doModify(result[0][0], fields) 329 330 def getUserBalance(self, userquotaid) : 331 """Returns the current account balance for a given user quota identifier.""" 332 # first get the user's name from the user quota id 333 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE) 334 if result : 335 username = result[0][1]["pykotaUserName"][0] 336 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"]) 337 if result : 338 fields = result[0][1] 339 return (float(fields["pykotaBalance"][0]), float(fields["pykotaLifeTimePaid"][0])) 340 341 def getUserBalanceFromUserId(self, userid) : 342 """Returns the current account balance for a given user id.""" 343 # first get the user's name from the user id 344 result = self.doSearch("objectClass=pykotaAccount", ["pykotaUserName", self.info["userrdn"]], base=userid, scope=ldap.SCOPE_BASE) 345 if result : 346 fields = result[0][1] 347 username = (fields.get("pykotaUserName") or fields.get(self.info["userrdn"]))[0] 348 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"]) 349 if result : 350 fields = result[0][1] 351 return (float(fields["pykotaBalance"][0]), float(fields["pykotaLifeTimePaid"][0])) 352 353 def getGroupBalance(self, groupquotaid) : 354 """Returns the current account balance for a given group, as the sum of each of its users' account balance.""" 355 # first get the group's name from the group quota id 356 result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE) 357 if result : 358 groupname = result[0][1]["pykotaGroupName"][0] 359 members = self.getGroupMembersNames(groupname) or [] 360 balance = lifetimepaid = 0.0 361 for member in members : 362 userid = self.getUserId(member) 363 if userid : 364 userbal = self.getUserBalanceFromUserId(userid) 365 if userbal : 366 (bal, paid) = userbal 367 balance += bal 368 lifetimepaid += paid 369 return (balance, lifetimepaid) 370 371 def getUserLimitBy(self, userquotaid) : 372 """Returns the way in which user printing is limited.""" 373 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE) 374 if result : 375 username = result[0][1]["pykotaUserName"][0] 376 result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaLimitBy"]) 377 if result : 378 return result[0][1]["pykotaLimitBy"][0] 379 380 def getGroupLimitBy(self, groupquotaid) : 381 """Returns the way in which group printing is limited.""" 382 # first get the group's name from the group quota id 383 result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE) 384 if result : 385 groupname = result[0][1]["pykotaGroupName"][0] 386 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), ["pykotaLimitBy"]) 387 if result : 388 return result[0][1]["pykotaLimitBy"][0] 389 390 def setUserBalance(self, userquotaid, balance) : 391 """Sets the account balance for a given user to a fixed value.""" 392 oldbalance = self.getUserBalance(userquotaid) 393 if oldbalance : 394 (oldbal, oldpaid) = oldbalance 395 difference = balance - oldbal 396 return self.increaseUserBalance(userquotaid, difference) 397 398 def limitUserBy(self, userquotaid, limitby) : 399 """Limits a given user based either on print quota or on account balance.""" 400 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE) 401 if result : 402 username = result[0][1]["pykotaUserName"][0] 403 fields = { 404 "pykotaLimitBy" : limitby, 405 } 406 self.doModify(self.getUserId(username), fields) 407 408 def limitGroupBy(self, groupquotaid, limitby) : 409 """Limits a given group based either on print quota or on sum of its users' account balances.""" 410 result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE) 411 if result : 412 groupname = result[0][1]["pykotaGroupName"][0] 413 fields = { 414 "pykotaLimitBy" : limitby, 415 } 416 self.doModify(self.getGroupId(groupname), fields) 417 418 def setUserPQuota(self, userquotaid, printerid, softlimit, hardlimit) : 419 """Sets soft and hard limits for a user quota on a specific printer given (userid, printerid).""" 420 fields = { 421 "pykotaSoftLimit" : str(softlimit), 422 "pykotaHardLimit" : str(hardlimit), 423 "pykotaDateLimit" : "None", 424 } 425 return self.doModify(userquotaid, fields) 426 427 def setGroupPQuota(self, groupquotaid, printerid, softlimit, hardlimit) : 428 """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid).""" 429 fields = { 430 "pykotaSoftLimit" : str(softlimit), 431 "pykotaHardLimit" : str(hardlimit), 432 "pykotaDateLimit" : "None", 433 } 434 return self.doModify(groupquotaid, fields) 435 436 def resetUserPQuota(self, userquotaid, printerid) : 437 """Resets the page counter to zero for a user on a printer. Life time page counter is kept unchanged.""" 438 fields = { 439 "pykotaPageCounter" : "0", 440 "pykotaDateLimit" : "None", 441 } 442 return self.doModify(userquotaid, fields) 443 444 def resetGroupPQuota(self, groupquotaid, printerid) : 445 """Resets the page counter to zero for a group on a printer. Life time page counter is kept unchanged.""" 446 fields = { 447 "pykotaPageCounter" : "0", 448 "pykotaDateLimit" : "None", 449 } 450 return self.doModify(groupquotaid, fields) 451 452 def updateUserPQuota(self, userquotaid, printerid, pagecount) : 453 """Updates the used user Quota information given (userid, printerid) and a job size in pages.""" 454 jobprice = self.computePrinterJobPrice(printerid, pagecount) 455 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaPageCounter", "pykotaLifePageCounter"], base=userquotaid, scope=ldap.SCOPE_BASE) 456 if result : 457 oldfields = result[0][1] 458 fields = { 459 "pykotaPageCounter" : str(pagecount + int(oldfields["pykotaPageCounter"][0])), 460 "pykotaLifePageCounter" : str(pagecount + int(oldfields["pykotaLifePageCounter"][0])), 461 } 462 return self.doModify(userquotaid, fields) 463 464 def getUserPQuota(self, userquotaid, printerid) : 465 """Returns the Print Quota information for a given (userquotaid, printerid).""" 466 # first get the user's name from the id 467 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName", "pykotaPageCounter", "pykotaLifePageCounter", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=userquotaid, scope=ldap.SCOPE_BASE) 468 if result : 469 fields = result[0][1] 470 datelimit = fields["pykotaDateLimit"][0].strip() 471 if (not datelimit) or (datelimit.upper() == "NONE") : 472 datelimit = None 473 return { "lifepagecounter" : int(fields["pykotaLifePageCounter"][0]), 474 "pagecounter" : int(fields["pykotaPageCounter"][0]), 475 "softlimit" : int(fields["pykotaSoftLimit"][0]), 476 "hardlimit" : int(fields["pykotaHardLimit"][0]), 477 "datelimit" : datelimit 478 } 479 480 def getGroupPQuota(self, grouppquotaid, printerid) : 481 """Returns the Print Quota information for a given (grouppquotaid, printerid).""" 482 result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=grouppquotaid, scope=ldap.SCOPE_BASE) 483 if result : 484 fields = result[0][1] 485 groupname = fields["pykotaGroupName"][0] 486 datelimit = fields["pykotaDateLimit"][0].strip() 487 if (not datelimit) or (datelimit.upper() == "NONE") : 488 datelimit = None 489 quota = { 490 "softlimit" : int(fields["pykotaSoftLimit"][0]), 491 "hardlimit" : int(fields["pykotaHardLimit"][0]), 492 "datelimit" : datelimit 493 } 494 members = self.getGroupMembersNames(groupname) or [] 495 pagecounter = lifepagecounter = 0 496 printerusers = self.getPrinterUsers(printerid) 497 if printerusers : 498 for (userid, username) in printerusers : 499 if username in members : 500 userpquota = self.getUserPQuota(userid, printerid) 501 if userpquota : 502 pagecounter += userpquota["pagecounter"] 503 lifepagecounter += userpquota["lifepagecounter"] 504 quota.update({"pagecounter": pagecounter, "lifepagecounter": lifepagecounter}) 505 return quota 506 507 def setUserDateLimit(self, userquotaid, printerid, datelimit) : 508 """Sets the limit date for a soft limit to become an hard one given (userid, printerid).""" 500 return self.getGroupPQuota(group, printer) 501 502 def writePrinterPrices(self, printer) : 503 """Write the printer's prices back into the storage.""" 504 fields = { 505 "pykotaPricePerPage" : str(printer.PricePerPage), 506 "pykotaPricePerJob" : str(printer.PricePerJob), 507 } 508 self.doModify(printer.ident, fields) 509 510 def writeUserLimitBy(self, user, limitby) : 511 """Sets the user's limiting factor.""" 512 fields = { 513 "pykotaLimitBy" : limitby, 514 } 515 self.doModify(user.ident, fields) 516 517 def writeGroupLimitBy(self, group, limitby) : 518 """Sets the group's limiting factor.""" 519 fields = { 520 "pykotaLimitBy" : limitby, 521 } 522 self.doModify(group.ident, fields) 523 524 def writeUserPQuotaDateLimit(self, userpquota, datelimit) : 525 """Sets the date limit permanently for a user print quota.""" 509 526 fields = { 510 527 "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second), 511 528 } 512 return self.doModify(user quotaid, fields)513 514 def setGroupDateLimit(self, groupquotaid, printerid, datelimit) :515 """Sets the limit date for a soft limit to become an hard one given (groupid, printerid)."""529 return self.doModify(userpquota.ident, fields) 530 531 def writeGroupPQuotaDateLimit(self, grouppquota, datelimit) : 532 """Sets the date limit permanently for a group print quota.""" 516 533 fields = { 517 534 "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second), 518 535 } 519 return self.doModify(groupquotaid, fields) 520 521 def addJobToHistory(self, jobid, userid, printerid, pagecounter, action, jobsize=None) : 522 """Adds a job to the history: (jobid, userid, printerid, last page counter taken from requester).""" 536 return self.doModify(grouppquota.ident, fields) 537 538 def writeUserPQuotaPagesCounters(self, userpquota, newpagecounter, newlifepagecounter) : 539 """Sets the new page counters permanently for a user print quota.""" 540 fields = { 541 "pykotaPageCounter" : str(newpagecounter), 542 "pykotaLifePageCounter" : str(newlifepagecounter), 543 } 544 return self.doModify(userpquota.ident, fields) 545 546 def writeUserAccountBalance(self, user, newbalance, newlifetimepaid=None) : 547 """Sets the new account balance and eventually new lifetime paid.""" 548 fields = { 549 "pykotaBalance" : str(newbalance), 550 } 551 if newlifetimepaid is not None : 552 fields.update({ "pykotaLifeTimePaid" : str(newlifetimepaid) }) 553 return self.doModify(user.idbalance, fields) 554 555 def writeLastJobSize(self, lastjob, jobsize) : 556 """Sets the last job's size permanently.""" 557 fields = { 558 "pykotaJobSize" : str(jobsize), 559 } 560 self.doModify(lastjob.ident, fields) 561 562 def writeJobNew(self, printer, user, jobid, pagecounter, action, jobsize=None) : 563 """Adds a job in a printer's history.""" 523 564 uuid = self.genUUID() 524 printername = self.getPrinterName(printerid)525 565 fields = { 526 566 "objectClass" : ["pykotaObject", "pykotaJob"], 527 567 "cn" : uuid, 528 "pykotaUserName" : self.getUserName(userid),529 "pykotaPrinterName" : printer name,568 "pykotaUserName" : user.Name, 569 "pykotaPrinterName" : printer.Name, 530 570 "pykotaJobId" : jobid, 531 571 "pykotaPrinterPageCounter" : str(pagecounter), … … 536 576 dn = "cn=%s,%s" % (uuid, self.info["jobbase"]) 537 577 self.doAdd(dn, fields) 538 result = self.doSearch("(&(objectClass=pykotaLastJob)(pykotaPrinterName=%s))" % printername, None, base=self.info["lastjobbase"]) 539 if result : 540 lastjdn = result[0][0] 578 if printer.LastJob.Exists : 541 579 fields = { 542 580 "pykotaLastJobIdent" : uuid, 543 581 } 544 self.doModify( lastjdn, fields)582 self.doModify(printer.LastJob.lastjobident, fields) 545 583 else : 546 584 lastjuuid = self.genUUID() … … 549 587 "objectClass" : ["pykotaObject", "pykotaLastJob"], 550 588 "cn" : lastjuuid, 551 "pykotaPrinterName" : printer name,589 "pykotaPrinterName" : printer.Name, 552 590 "pykotaLastJobIdent" : uuid, 553 591 } 554 592 self.doAdd(lastjdn, fields) 555 556 def updateJobSizeInHistory(self, historyid, jobsize) : 557 """Updates a job size in the history given the history line's id.""" 558 result = self.doSearch("(&(objectClass=pykotaJob)(cn=%s))" % historyid, ["cn"], base=self.info["jobbase"]) 559 if result : 560 fields = { 561 "pykotaJobSize" : str(jobsize), 562 } 563 self.doModify(result[0][0], fields) 564 565 def getPrinterPageCounter(self, printerid) : 566 """Returns the last page counter value for a printer given its id, also returns last username, last jobid and history line id.""" 567 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE) 593 594 def writeUserPQuotaLimits(self, userpquota, softlimit, hardlimit) : 595 """Sets soft and hard limits for a user quota.""" 596 fields = { 597 "pykotaSoftLimit" : str(softlimit), 598 "pykotaHardLimit" : str(hardlimit), 599 } 600 self.doModify(userpquota.ident, fields) 601 602 def writeGroupPQuotaLimits(self, grouppquota, softlimit, hardlimit) : 603 """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid).""" 604 fields = { 605 "pykotaSoftLimit" : str(softlimit), 606 "pykotaHardLimit" : str(hardlimit), 607 } 608 self.doModify(grouppquota.ident, fields) 609 610 def deleteUser(self, user) : 611 """Completely deletes an user from the Quota Storage.""" 612 # TODO : What should we do if we delete the last person who used a given printer ? 613 # TODO : we can't reassign the last job to the previous one, because next user would be 614 # TODO : incorrectly charged (overcharged). 615 result = self.doSearch("(&(objectClass=pykotaLastJob)(pykotaUserName=%s))" % user.Name, base=self.info["lastjobbase"]) 616 for (ident, fields) in result : 617 self.doDelete(ident) 618 result = self.doSearch("(&(objectClass=pykotaJob)(pykotaUserName=%s))" % user.Name, base=self.info["jobbase"]) 619 for (ident, fields) in result : 620 self.doDelete(ident) 621 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaUserName=%s))" % user.Name, ["pykotaUserName"], base=self.info["userquotabase"]) 622 for (ident, fields) in result : 623 self.doDelete(ident) 624 result = self.doSearch("objectClass=pykotaAccount", None, base=user.ident, scope=ldap.SCOPE_BASE) 568 625 if result : 569 626 fields = result[0][1] 570 printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0] 571 result = self.doSearch("(&(objectClass=pykotaLastjob)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaLastJobIdent"], base=self.info["lastjobbase"]) 572 if result : 573 lastjobident = result[0][1]["pykotaLastJobIdent"][0] 574 result = self.doSearch("(&(objectClass=pykotaJob)(cn=%s))" % lastjobident, ["pykotaUserName", "pykotaPrinterName", "pykotaJobId", "pykotaPrinterPageCounter", "pykotaJobSize", "pykotaAction", "createTimestamp"], base=self.info["jobbase"]) 575 if result : 576 fields = result[0][1] 577 return { "id": lastjobident, 578 "jobid" : fields.get("pykotaJobId")[0], 579 "userid" : self.getUserId(fields.get("pykotaUserName")[0]), 580 "username" : fields.get("pykotaUserName")[0], 581 "pagecounter" : int(fields.get("pykotaPrinterPageCounter")[0]), 582 "jobsize" : int(fields.get("pykotaJobSize")[0]), 583 } 584 585 def addUserToGroup(self, userid, groupid) : 586 """Adds an user to a group.""" 587 raise PyKotaStorageError, "Not implemented !" 588 589 def deleteUser(self, userid) : 590 """Completely deletes an user from the Quota Storage.""" 591 raise PyKotaStorageError, "Not implemented !" 592 593 def deleteGroup(self, groupid) : 594 """Completely deletes an user from the Quota Storage.""" 595 raise PyKotaStorageError, "Not implemented !" 596 597 def computePrinterJobPrice(self, printerid, jobsize) : 598 """Returns the price for a job on a given printer.""" 599 # TODO : create a base class with things like this 600 prices = self.getPrinterPrices(printerid) 601 if prices is None : 602 perpage = perjob = 0.0 603 else : 604 (perpage, perjob) = prices 605 return perjob + (perpage * jobsize) 627 for k in fields.keys() : 628 if k.startswith("pykota") : 629 del fields[k] 630 elif k.lower() == "objectclass" : 631 todelete = [] 632 for i in range(len(fields[k])) : 633 if fields[k][i].startswith("pykota") : 634 todelete.append(i) 635 todelete.sort() 636 todelete.reverse() 637 for i in todelete : 638 del fields[k][i] 639 if fields.get("objectclass") : 640 self.doModify(user.ident, fields, ignoreold=0) 641 else : 642 self.doDelete(user.ident) 643 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(pykotaUserName=%s))" % user.Name, ["pykotaUserName"], base=self.info["balancebase"]) 644 for (ident, fields) in result : 645 self.doDelete(ident) 646 647 def deleteGroup(self, group) : 648 """Completely deletes a group from the Quota Storage.""" 649 result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaGroupName=%s))" % group.Name, ["pykotaGroupName"], base=self.info["groupquotabase"]) 650 for (ident, fields) in result : 651 self.doDelete(ident) 652 result = self.doSearch("objectClass=pykotaGroup", None, base=group.ident, scope=ldap.SCOPE_BASE) 653 if result : 654 fields = result[0][1] 655 for k in fields.keys() : 656 if k.startswith("pykota") : 657 del fields[k] 658 elif k.lower() == "objectclass" : 659 todelete = [] 660 for i in range(len(fields[k])) : 661 if fields[k][i].startswith("pykota") : 662 todelete.append(i) 663 todelete.sort() 664 todelete.reverse() 665 for i in todelete : 666 del fields[k][i] 667 if fields.get("objectclass") : 668 self.doModify(group.ident, fields, ignoreold=0) 669 else : 670 self.doDelete(group.ident) 671 -
pykota/trunk/pykota/storages/pgstorage.py
r1024 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.3 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.2 2003/06/12 21:09:57 jalet 24 27 # wrongly placed code. … … 34 37 # 35 38 36 import fnmatch37 38 39 from pykota.storage import PyKotaStorageError 40 from pykota.storage import StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 39 41 40 42 try : … … 74 76 self.tool.logger.log_message("Database closed.", "debug") 75 77 76 def doQuery(self, query) : 77 """Does a query.""" 78 if type(query) in (type([]), type(())) : 79 query = ";".join(query) 78 def beginTransaction(self) : 79 """Starts a transaction.""" 80 self.database.query("BEGIN;") 81 if self.debug : 82 self.tool.logger.log_message("Transaction begins...", "debug") 83 84 def commitTransaction(self) : 85 """Commits a transaction.""" 86 self.database.query("COMMIT;") 87 if self.debug : 88 self.tool.logger.log_message("Transaction committed.", "debug") 89 90 def rollbackTransaction(self) : 91 """Rollbacks a transaction.""" 92 self.database.query("ROLLBACK;") 93 if self.debug : 94 self.tool.logger.log_message("Transaction aborted.", "debug") 95 96 def doSearch(self, query) : 97 """Does a search query.""" 80 98 query = query.strip() 81 99 if not query.endswith(';') : 82 100 query += ';' 83 self.database.query("BEGIN;")84 if self.debug :85 self.tool.logger.log_message("Transaction began.", "debug")86 101 try : 87 102 if self.debug : … … 89 104 result = self.database.query(query) 90 105 except pg.error, msg : 91 self.database.query("ROLLBACK;")92 if self.debug :93 self.tool.logger.log_message("Transaction aborted.", "debug")94 106 raise PyKotaStorageError, msg 95 107 else : 96 self.database.query("COMMIT;") 108 if (result is not None) and (result.ntuples() > 0) : 109 return result.dictresult() 110 111 def doModify(self, query) : 112 """Does a (possibly multiple) modify query.""" 113 query = query.strip() 114 if not query.endswith(';') : 115 query += ';' 116 try : 97 117 if self.debug : 98 self.tool.logger.log_message("Transaction committed.", "debug") 99 return result 100 118 self.tool.logger.log_message("QUERY : %s" % query, "debug") 119 result = self.database.query(query) 120 except pg.error, msg : 121 raise PyKotaStorageError, msg 122 101 123 def doQuote(self, field) : 102 124 """Quotes a field for use as a string in SQL queries.""" … … 109 131 return pg._quote(field, typ) 110 132 111 def doParseResult(self, result) : 112 """Returns the result as a list of Python mappings.""" 113 if (result is not None) and (result.ntuples() > 0) : 114 return result.dictresult() 115 133 def getUser(self, username) : 134 """Extracts user information given its name.""" 135 user = StorageUser(self, username) 136 result = self.doSearch("SELECT * FROM users WHERE username=%s LIMIT 1" % self.doQuote(username)) 137 if result : 138 fields = result[0] 139 user.ident = fields.get("id") 140 user.LimitBy = fields.get("limitby") 141 user.AccountBalance = fields.get("balance") 142 user.LifeTimePaid = fields.get("lifetimepaid") 143 user.Exists = 1 144 return user 145 146 def getGroup(self, groupname) : 147 """Extracts group information given its name.""" 148 group = StorageGroup(self, groupname) 149 result = self.doSearch("SELECT * FROM groups WHERE groupname=%s LIMIT 1" % self.doQuote(groupname)) 150 if result : 151 fields = result[0] 152 group.ident = fields.get("id") 153 group.LimitBy = fields.get("limitby") 154 result = self.doSearch("SELECT SUM(balance) AS balance, SUM(lifetimepaid) AS lifetimepaid FROM users WHERE id IN (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(group.ident)) 155 if result : 156 fields = result[0] 157 group.AccountBalance = fields.get("balance") 158 group.LifeTimePaid = fields.get("lifetimepaid") 159 group.Exists = 1 160 return group 161 162 def getPrinter(self, printername) : 163 """Extracts printer information given its name.""" 164 printer = StoragePrinter(self, printername) 165 result = self.doSearch("SELECT * FROM printers WHERE printername=%s LIMIT 1" % self.doQuote(printername)) 166 if result : 167 fields = result[0] 168 printer.ident = fields.get("id") 169 printer.PricePerJob = fields.get("priceperjob") 170 printer.PricePerPage = fields.get("priceperpage") 171 printer.LastJob = self.getPrinterLastJob(printer) 172 printer.Exists = 1 173 return printer 174 175 def getUserGroups(self, user) : 176 """Returns the user's groups list.""" 177 groups = [] 178 result = self.doSearch("SELECT groupname FROM groupsmembers JOIN groups ON groupsmembers.groupid=groups.id WHERE userid=%s" % self.doQuote(user.ident)) 179 if result : 180 for record in result : 181 groups.append(self.getGroup(record.get("groupname"))) 182 return groups 183 184 def getGroupMembers(self, group) : 185 """Returns the group's members list.""" 186 groupmembers = [] 187 result = self.doSearch("SELECT * FROM groupsmembers JOIN users ON groupsmembers.userid=users.id WHERE groupid=%s" % self.doQuote(group.ident)) 188 if result : 189 for record in result : 190 user = StorageUser(self, record.get("username")) 191 user.ident = record.get("userid") 192 user.LimitBy = record.get("limitby") 193 user.AccountBalance = record.get("balance") 194 user.LifeTimePaid = record.get("lifetimepaid") 195 user.Exists = 1 196 groupmembers.append(user) 197 return groupmembers 198 199 def getUserPQuota(self, user, printer) : 200 """Extracts a user print quota.""" 201 userpquota = StorageUserPQuota(self, user, printer) 202 if user.Exists : 203 result = self.doSearch("SELECT id, lifepagecounter, pagecounter, softlimit, hardlimit, datelimit FROM userpquota WHERE userid=%s AND printerid=%s" % (self.doQuote(user.ident), self.doQuote(printer.ident))) 204 if result : 205 fields = result[0] 206 userpquota.ident = fields.get("id") 207 userpquota.PageCounter = fields.get("pagecounter") 208 userpquota.LifePageCounter = fields.get("lifepagecounter") 209 userpquota.SoftLimit = fields.get("softlimit") 210 userpquota.HardLimit = fields.get("hardlimit") 211 userpquota.DateLimit = fields.get("datelimit") 212 userpquota.Exists = 1 213 return userpquota 214 215 def getGroupPQuota(self, group, printer) : 216 """Extracts a group print quota.""" 217 grouppquota = StorageGroupPQuota(self, group, printer) 218 if group.Exists : 219 result = self.doSearch("SELECT id, softlimit, hardlimit, datelimit FROM grouppquota WHERE groupid=%s AND printerid=%s" % (self.doQuote(group.ident), self.doQuote(printer.ident))) 220 if result : 221 fields = result[0] 222 grouppquota.ident = fields.get("id") 223 grouppquota.SoftLimit = fields.get("softlimit") 224 grouppquota.HardLimit = fields.get("hardlimit") 225 grouppquota.DateLimit = fields.get("datelimit") 226 result = self.doSearch("SELECT SUM(lifepagecounter) AS lifepagecounter, SUM(pagecounter) AS pagecounter FROM userpquota WHERE printerid=%s AND userid IN (SELECT userid FROM groupsmembers WHERE groupid=%s)" % (self.doQuote(printer.ident), self.doQuote(group.ident))) 227 if result : 228 fields = result[0] 229 grouppquota.PageCounter = fields.get("pagecounter") 230 grouppquota.LifePageCounter = fields.get("lifepagecounter") 231 grouppquota.Exists = 1 232 return grouppquota 233 234 def getPrinterLastJob(self, printer) : 235 """Extracts a printer's last job information.""" 236 lastjob = StorageLastJob(self, printer) 237 result = self.doSearch("SELECT jobhistory.id, jobid, userid, username, pagecounter, jobsize, jobdate FROM jobhistory, users WHERE printerid=%s AND userid=users.id ORDER BY jobdate DESC LIMIT 1" % self.doQuote(printer.ident)) 238 if result : 239 fields = result[0] 240 lastjob.ident = fields.get("id") 241 lastjob.JobId = fields.get("jobid") 242 lastjob.User = self.getUser(fields.get("username")) 243 lastjob.PrinterPageCounter = fields.get("pagecounter") 244 lastjob.JobSize = fields.get("jobsize") 245 lastjob.JobAction = fields.get("action") 246 lastjob.JobDate = fields.get("jobdate") 247 lastjob.Exists = 1 248 return lastjob 249 116 250 def getMatchingPrinters(self, printerpattern) : 117 """Returns the list of all printers as tuples (id, name) for printer names which matcha certain pattern."""118 printers list= []251 """Returns the list of all printers for which name matches a certain pattern.""" 252 printers = [] 119 253 # We 'could' do a SELECT printername FROM printers WHERE printername LIKE ... 120 254 # but we don't because other storages semantics may be different, so every 121 255 # storage should use fnmatch to match patterns and be storage agnostic 122 result = self.doQuery("SELECT id, printername FROM printers") 123 result = self.doParseResult(result) 124 if result is not None : 125 for printer in result : 126 if fnmatch.fnmatchcase(printer["printername"], printerpattern) : 127 printerslist.append((printer["id"], printer["printername"])) 128 return printerslist 129 130 def getPrinterId(self, printername) : 131 """Returns a printerid given a printername.""" 132 result = self.doQuery("SELECT id FROM printers WHERE printername=%s" % self.doQuote(printername)) 133 try : 134 return self.doParseResult(result)[0]["id"] 135 except TypeError : # Not found 136 return 137 138 def getPrinterPrices(self, printerid) : 139 """Returns a printer prices per page and per job given a printerid.""" 140 result = self.doQuery("SELECT priceperpage, priceperjob FROM printers WHERE id=%s" % self.doQuote(printerid)) 141 try : 142 printerprices = self.doParseResult(result)[0] 143 return (printerprices["priceperpage"], printerprices["priceperjob"]) 144 except TypeError : # Not found 145 return 146 147 def setPrinterPrices(self, printerid, perpage, perjob) : 148 """Sets prices per job and per page for a given printer.""" 149 self.doQuery("UPDATE printers SET priceperpage=%s, priceperjob=%s WHERE id=%s" % (self.doQuote(perpage), self.doQuote(perjob), self.doQuote(printerid))) 150 151 def getUserId(self, username) : 152 """Returns a userid given a username.""" 153 result = self.doQuery("SELECT id FROM users WHERE username=%s" % self.doQuote(username)) 154 try : 155 return self.doParseResult(result)[0]["id"] 156 except TypeError : # Not found 157 return 158 159 def getGroupId(self, groupname) : 160 """Returns a groupid given a grupname.""" 161 result = self.doQuery("SELECT id FROM groups WHERE groupname=%s" % self.doQuote(groupname)) 162 try : 163 return self.doParseResult(result)[0]["id"] 164 except TypeError : # Not found 165 return 166 167 def getJobHistoryId(self, jobid, userid, printerid) : 168 """Returns the history line's id given a (jobid, userid, printerid).""" 169 result = self.doQuery("SELECT id FROM jobhistory WHERE jobid=%s AND userid=%s AND printerid=%s" % (self.doQuote(jobid), self.doQuote(userid), self.doQuote(printerid))) 170 try : 171 return self.doParseResult(result)[0]["id"] 172 except TypeError : # Not found 173 return 174 175 def getPrinterUsers(self, printerid) : 176 """Returns the list of userids and usernames which uses a given printer.""" 177 result = self.doQuery("SELECT DISTINCT id, username FROM users WHERE id IN (SELECT userid FROM userpquota WHERE printerid=%s) ORDER BY username" % self.doQuote(printerid)) 178 result = self.doParseResult(result) 179 if result is None : 180 return [] 181 else : 182 return [(record["id"], record["username"]) for record in result] 183 184 def getPrinterGroups(self, printerid) : 185 """Returns the list of groups which uses a given printer.""" 186 result = self.doQuery("SELECT DISTINCT id, groupname FROM groups WHERE id IN (SELECT groupid FROM grouppquota WHERE printerid=%s)" % self.doQuote(printerid)) 187 result = self.doParseResult(result) 188 if result is None : 189 return [] 190 else : 191 return [(record["id"], record["groupname"]) for record in result] 192 193 def getGroupMembersNames(self, groupname) : 194 """Returns the list of user's names which are member of this group.""" 195 groupid = self.getGroupId(groupname) 196 if groupid is None : 197 return [] 198 else : 199 result = self.doQuery("SELECT DISTINCT username FROM users WHERE id IN (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(groupid)) 200 return [record["username"] for record in (self.doParseResult(result) or [])] 201 202 def getUserGroupsNames(self, userid) : 203 """Returns the list of groups' names the user is a member of.""" 204 result = self.doQuery("SELECT DISTINCT groupname FROM groups WHERE id IN (SELECT groupid FROM groupsmembers WHERE userid=%s)" % self.doQuote(userid)) 205 return [record["groupname"] for record in (self.doParseResult(result) or [])] 256 result = self.doSearch("SELECT * FROM printers") 257 if result : 258 for record in result : 259 if self.tool.matchString(record["printername"], [ printerpattern ]) : 260 printer = StoragePrinter(self, record["printername"]) 261 printer.ident = record.get("id") 262 printer.PricePerJob = record.get("priceperjob") 263 printer.PricePerPage = record.get("priceperpage") 264 printer.LastJob = self.getPrinterLastJob(printer) 265 printer.Exists = 1 266 printers.append(printer) 267 return printers 268 269 def getPrinterUsersAndQuotas(self, printer, names=None) : 270 """Returns the list of users who uses a given printer, along with their quotas.""" 271 usersandquotas = [] 272 result = self.doSearch("SELECT users.id as uid,username,balance,lifetimepaid,limitby,userpquota.id,lifepagecounter,pagecounter,softlimit,hardlimit,datelimit FROM users JOIN userpquota ON users.id=userpquota.userid AND printerid=%s" % self.doQuote(printer.ident)) 273 if result : 274 for record in result : 275 user = StorageUser(self, record.get("username")) 276 if (names is None) or self.tool.matchString(user.Name, names) : 277 user.ident = record.get("uid") 278 user.LimitBy = record.get("limitby") 279 user.AccountBalance = record.get("balance") 280 user.LifeTimePaid = record.get("lifetimepaid") 281 user.Exists = 1 282 userpquota = StorageUserPQuota(self, user, printer) 283 userpquota.ident = record.get("id") 284 userpquota.PageCounter = record.get("pagecounter") 285 userpquota.LifePageCounter = record.get("lifepagecounter") 286 userpquota.SoftLimit = record.get("softlimit") 287 userpquota.HardLimit = record.get("hardlimit") 288 userpquota.DateLimit = record.get("datelimit") 289 userpquota.Exists = 1 290 usersandquotas.append((user, userpquota)) 291 return usersandquotas 292 293 def getPrinterGroupsAndQuotas(self, printer, names=None) : 294 """Returns the list of groups which uses a given printer, along with their quotas.""" 295 groupsandquotas = [] 296 result = self.doSearch("SELECT groupname FROM groups JOIN grouppquota ON groups.id=grouppquota.groupid AND printerid=%s" % self.doQuote(printer.ident)) 297 if result : 298 for record in result : 299 group = self.getGroup(record.get("groupname")) 300 if (names is None) or self.tool.matchString(group.Name, names) : 301 grouppquota = self.getGroupPQuota(group, printer) 302 groupsandquotas.append((group, grouppquota)) 303 return groupsandquotas 206 304 207 305 def addPrinter(self, printername) : 208 """Adds a printer to the quota storage, returns it s id."""209 self.do Query("INSERT INTO printers (printername) VALUES (%s)" % self.doQuote(printername))210 return self.getPrinter Id(printername)211 212 def addUser(self, user name) :306 """Adds a printer to the quota storage, returns it.""" 307 self.doModify("INSERT INTO printers (printername) VALUES (%s)" % self.doQuote(printername)) 308 return self.getPrinter(printername) 309 310 def addUser(self, user) : 213 311 """Adds a user to the quota storage, returns its id.""" 214 self.do Query("INSERT INTO users (username) VALUES (%s)" % self.doQuote(username))215 return self.getUser Id(username)216 217 def addGroup(self, group name) :312 self.doModify("INSERT INTO users (username, limitby, balance, lifetimepaid) VALUES (%s, %s, %s, %s)" % (self.doQuote(user.Name), self.doQuote(user.LimitBy), self.doQuote(user.AccountBalance), self.doQuote(user.LifeTimePaid))) 313 return self.getUser(user.Name) 314 315 def addGroup(self, group) : 218 316 """Adds a group to the quota storage, returns its id.""" 219 self.doQuery("INSERT INTO groups (groupname) VALUES (%s)" % self.doQuote(groupname)) 220 return self.getGroupId(groupname) 221 222 def addUserPQuota(self, username, printerid) : 223 """Initializes a user print quota on a printer, adds the user to the quota storage if needed.""" 224 userid = self.getUserId(username) 225 if userid is None : 226 userid = self.addUser(username) 227 uqexists = (self.getUserPQuota(userid, printerid) is not None) 228 if not uqexists : 229 self.doQuery("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(userid), self.doQuote(printerid))) 230 return (userid, printerid) 231 232 def addGroupPQuota(self, groupname, printerid) : 233 """Initializes a group print quota on a printer, adds the group to the quota storage if needed.""" 234 groupid = self.getGroupId(groupname) 235 if groupid is None : 236 groupid = self.addGroup(groupname) 237 gqexists = (self.getGroupPQuota(groupid, printerid) is not None) 238 if not gqexists : 239 self.doQuery("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(groupid), self.doQuote(printerid))) 240 return (groupid, printerid) 241 242 def increaseUserBalance(self, userid, amount) : 243 """Increases (or decreases) an user's account balance by a given amount.""" 244 self.doQuery("UPDATE users SET balance=balance+(%s), lifetimepaid=lifetimepaid+(%s) WHERE id=%s" % (self.doQuote(amount), self.doQuote(amount), self.doQuote(userid))) 245 246 def getUserBalance(self, userid) : 247 """Returns the current account balance for a given user.""" 248 result = self.doQuery("SELECT balance, lifetimepaid FROM users WHERE id=%s" % self.doQuote(userid)) 249 try : 250 result = self.doParseResult(result)[0] 251 except TypeError : # Not found 252 return 253 else : 254 return (result["balance"], result["lifetimepaid"]) 255 256 def getGroupBalance(self, groupid) : 257 """Returns the current account balance for a given group, as the sum of each of its users' account balance.""" 258 result = self.doQuery("SELECT SUM(balance) AS balance, SUM(lifetimepaid) AS lifetimepaid FROM users WHERE id in (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(groupid)) 259 try : 260 result = self.doParseResult(result)[0] 261 except TypeError : # Not found 262 return 263 else : 264 return (result["balance"], result["lifetimepaid"]) 265 266 def getUserLimitBy(self, userid) : 267 """Returns the way in which user printing is limited.""" 268 result = self.doQuery("SELECT limitby FROM users WHERE id=%s" % self.doQuote(userid)) 269 try : 270 return self.doParseResult(result)[0]["limitby"] 271 except TypeError : # Not found 272 return 273 274 def getGroupLimitBy(self, groupid) : 275 """Returns the way in which group printing is limited.""" 276 result = self.doQuery("SELECT limitby FROM groups WHERE id=%s" % self.doQuote(groupid)) 277 try : 278 return self.doParseResult(result)[0]["limitby"] 279 except TypeError : # Not found 280 return 281 282 def setUserBalance(self, userid, balance) : 283 """Sets the account balance for a given user to a fixed value.""" 284 (current, lifetimepaid) = self.getUserBalance(userid) 285 difference = balance - current 286 self.increaseUserBalance(userid, difference) 287 288 def limitUserBy(self, userid, limitby) : 289 """Limits a given user based either on print quota or on account balance.""" 290 self.doQuery("UPDATE users SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(userid))) 291 292 def limitGroupBy(self, groupid, limitby) : 293 """Limits a given group based either on print quota or on sum of its users' account balances.""" 294 self.doQuery("UPDATE groups SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(groupid))) 295 296 def setUserPQuota(self, userid, printerid, softlimit, hardlimit) : 297 """Sets soft and hard limits for a user quota on a specific printer given (userid, printerid).""" 298 self.doQuery("UPDATE userpquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE userid=%s AND printerid=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(userid), self.doQuote(printerid))) 299 300 def setGroupPQuota(self, groupid, printerid, softlimit, hardlimit) : 301 """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid).""" 302 self.doQuery("UPDATE grouppquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE groupid=%s AND printerid=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(groupid), self.doQuote(printerid))) 303 304 def resetUserPQuota(self, userid, printerid) : 305 """Resets the page counter to zero for a user on a printer. Life time page counter is kept unchanged.""" 306 self.doQuery("UPDATE userpquota SET pagecounter=0, datelimit=NULL WHERE userid=%s AND printerid=%s" % (self.doQuote(userid), self.doQuote(printerid))) 307 308 def resetGroupPQuota(self, groupid, printerid) : 309 """Resets the page counter to zero for a group on a printer. Life time page counter is kept unchanged.""" 310 self.doQuery("UPDATE grouppquota SET pagecounter=0, datelimit=NULL WHERE groupid=%s AND printerid=%s" % (self.doQuote(groupid), self.doQuote(printerid))) 311 312 def updateUserPQuota(self, userid, printerid, pagecount) : 313 """Updates the used user Quota information given (userid, printerid) and a job size in pages.""" 314 jobprice = self.computePrinterJobPrice(printerid, pagecount) 315 queries = [] 316 queries.append("UPDATE userpquota SET lifepagecounter=lifepagecounter+(%s), pagecounter=pagecounter+(%s) WHERE userid=%s AND printerid=%s" % (self.doQuote(pagecount), self.doQuote(pagecount), self.doQuote(userid), self.doQuote(printerid))) 317 queries.append("UPDATE users SET balance=balance-(%s) WHERE id=%s" % (self.doQuote(jobprice), self.doQuote(userid))) 318 self.doQuery(queries) 319 320 def getUserPQuota(self, userid, printerid) : 321 """Returns the Print Quota information for a given (userid, printerid).""" 322 result = self.doQuery("SELECT lifepagecounter, pagecounter, softlimit, hardlimit, datelimit FROM userpquota WHERE userid=%s AND printerid=%s" % (self.doQuote(userid), self.doQuote(printerid))) 323 try : 324 return self.doParseResult(result)[0] 325 except TypeError : # Not found 326 return 327 328 def getGroupPQuota(self, groupid, printerid) : 329 """Returns the Print Quota information for a given (groupid, printerid).""" 330 result = self.doQuery("SELECT softlimit, hardlimit, datelimit FROM grouppquota WHERE groupid=%s AND printerid=%s" % (self.doQuote(groupid), self.doQuote(printerid))) 331 try : 332 grouppquota = self.doParseResult(result)[0] 333 except TypeError : 334 return 335 else : 336 result = self.doQuery("SELECT SUM(lifepagecounter) as lifepagecounter, SUM(pagecounter) as pagecounter FROM userpquota WHERE printerid=%s AND userid in (SELECT userid FROM groupsmembers WHERE groupid=%s)" % (self.doQuote(printerid), self.doQuote(groupid))) 337 try : 338 result = self.doParseResult(result)[0] 339 except TypeError : # Not found 340 return 341 else : 342 grouppquota.update({"lifepagecounter": result["lifepagecounter"], "pagecounter": result["pagecounter"]}) 343 return grouppquota 344 345 def setUserDateLimit(self, userid, printerid, datelimit) : 346 """Sets the limit date for a soft limit to become an hard one given (userid, printerid).""" 347 self.doQuery("UPDATE userpquota SET datelimit=%s::TIMESTAMP WHERE userid=%s AND printerid=%s" % (self.doQuote("%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)), self.doQuote(userid), self.doQuote(printerid))) 348 349 def setGroupDateLimit(self, groupid, printerid, datelimit) : 350 """Sets the limit date for a soft limit to become an hard one given (groupid, printerid).""" 351 self.doQuery("UPDATE grouppquota SET datelimit=%s::TIMESTAMP WHERE groupid=%s AND printerid=%s" % (self.doQuote("%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)), self.doQuote(groupid), self.doQuote(printerid))) 352 353 def addJobToHistory(self, jobid, userid, printerid, pagecounter, action, jobsize=None) : 354 """Adds a job to the history: (jobid, userid, printerid, last page counter taken from requester).""" 355 self.doQuery("INSERT INTO jobhistory (jobid, userid, printerid, pagecounter, action, jobsize) VALUES (%s, %s, %s, %s, %s, %s)" % (self.doQuote(jobid), self.doQuote(userid), self.doQuote(printerid), self.doQuote(pagecounter), self.doQuote(action), self.doQuote(jobsize))) 356 return self.getJobHistoryId(jobid, userid, printerid) # in case jobid is not sufficient 357 358 def updateJobSizeInHistory(self, historyid, jobsize) : 359 """Updates a job size in the history given the history line's id.""" 360 self.doQuery("UPDATE jobhistory SET jobsize=%s WHERE id=%s" % (self.doQuote(jobsize), self.doQuote(historyid))) 361 362 def getPrinterPageCounter(self, printerid) : 363 """Returns the last page counter value for a printer given its id, also returns last username, last jobid and history line id.""" 364 result = self.doQuery("SELECT jobhistory.id, jobid, userid, username, pagecounter, jobsize FROM jobhistory, users WHERE printerid=%s AND userid=users.id ORDER BY jobdate DESC LIMIT 1" % self.doQuote(printerid)) 365 try : 366 return self.doParseResult(result)[0] 367 except TypeError : # Not found 368 return 369 370 def addUserToGroup(self, userid, groupid) : 317 self.doModify("INSERT INTO groups (groupname, limitby) VALUES (%s, %s)" % (self.doQuote(group.Name), self.doQuote(group.LimitBy))) 318 return self.getGroup(group.Name) 319 320 def addUserToGroup(self, user, group) : 371 321 """Adds an user to a group.""" 372 result = self.do Query("SELECT COUNT(*) AS mexists FROM groupsmembers WHERE groupid=%s AND userid=%s" % (self.doQuote(groupid), self.doQuote(userid)))322 result = self.doModify("SELECT COUNT(*) AS mexists FROM groupsmembers WHERE groupid=%s AND userid=%s" % (self.doQuote(group.ident), self.doQuote(user.ident))) 373 323 try : 374 324 mexists = self.doParseResult(result)[0]["mexists"] … … 376 326 mexists = 0 377 327 if not mexists : 378 self.doQuery("INSERT INTO groupsmembers (groupid, userid) VALUES (%s, %s)" % (self.doQuote(groupid), self.doQuote(userid))) 379 380 def deleteUser(self, userid) : 328 self.doModify("INSERT INTO groupsmembers (groupid, userid) VALUES (%s, %s)" % (self.doQuote(group.ident), self.doQuote(user.ident))) 329 330 def addUserPQuota(self, user, printer) : 331 """Initializes a user print quota on a printer.""" 332 self.doModify("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident))) 333 return self.getUserPQuota(user, printer) 334 335 def addGroupPQuota(self, group, printer) : 336 """Initializes a group print quota on a printer.""" 337 self.doModify("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(group.ident), self.doQuote(printer.ident))) 338 return self.getGroupPQuota(group, printer) 339 340 def writePrinterPrices(self, printer) : 341 """Write the printer's prices back into the storage.""" 342 self.doModify("UPDATE printers SET priceperpage=%s, priceperjob=%s WHERE printerid=%s" % (self.doQuote(printer.PricePerPage), self.doQuote(printer.PricePerJob), self.doQuote(printer.ident))) 343 344 def writeUserLimitBy(self, user, limitby) : 345 """Sets the user's limiting factor.""" 346 self.doModify("UPDATE users SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(user.ident))) 347 348 def writeGroupLimitBy(self, group, limitby) : 349 """Sets the group's limiting factor.""" 350 self.doModify("UPDATE groups SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(group.ident))) 351 352 def writeUserPQuotaDateLimit(self, userpquota, datelimit) : 353 """Sets the date limit permanently for a user print quota.""" 354 self.doModify("UPDATE userpquota SET datelimit::TIMESTAMP=%s WHERE id=%s" % (self.doQuote(datelimit), self.doQuote(userpquota.ident))) 355 356 def writeGroupPQuotaDateLimit(self, grouppquota, datelimit) : 357 """Sets the date limit permanently for a group print quota.""" 358 self.doModify("UPDATE grouppquota SET datelimit::TIMESTAMP=%s WHERE id=%s" % (self.doQuote(datelimit), self.doQuote(grouppquota.ident))) 359 360 def writeUserPQuotaPagesCounters(self, userpquota, newpagecounter, newlifepagecounter) : 361 """Sets the new page counters permanently for a user print quota.""" 362 self.doModify("UPDATE userpquota SET pagecounter=%s,lifepagecounter=%s WHERE id=%s" % (self.doQuote(newpagecounter), self.doQuote(newlifepagecounter), self.doQuote(userpquota.ident))) 363 364 def writeUserAccountBalance(self, user, newbalance, newlifetimepaid=None) : 365 """Sets the new account balance and eventually new lifetime paid.""" 366 if newlifetimepaid is not None : 367 self.doModify("UPDATE users SET balance=%s, lifetimepaid=%s WHERE id=%s" % (self.doQuote(newbalance), self.doQuote(newlifetimepaid), self.doQuote(user.ident))) 368 else : 369 self.doModify("UPDATE users SET balance=%s WHERE id=%s" % (self.doQuote(newbalance), self.doQuote(user.ident))) 370 371 def writeLastJobSize(self, lastjob, jobsize) : 372 """Sets the last job's size permanently.""" 373 self.doModify("UPDATE jobhistory SET jobsize=%s WHERE id=%s" % (self.doQuote(jobsize), self.doQuote(lastjob.ident))) 374 375 def writeJobNew(self, printer, user, jobid, pagecounter, action, jobsize=None) : 376 """Adds a job in a printer's history.""" 377 if jobsize is not None : 378 self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action, jobsize) VALUES (%s, %s, %s, %s, %s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident), self.doQuote(jobid), self.doQuote(pagecounter), self.doQuote(action), self.doQuote(jobsize))) 379 else : 380 self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action) VALUES (%s, %s, %s, %s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident), self.doQuote(jobid), self.doQuote(pagecounter), self.doQuote(action))) 381 382 def writeUserPQuotaLimits(self, userpquota, softlimit, hardlimit) : 383 """Sets soft and hard limits for a user quota.""" 384 self.doModify("UPDATE userpquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE id=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(userpquota.ident))) 385 386 def writeGroupPQuotaLimits(self, grouppquota, softlimit, hardlimit) : 387 """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid).""" 388 self.doModify("UPDATE grouppquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE id=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(grouppquota.ident))) 389 390 def deleteUser(self, user) : 381 391 """Completely deletes an user from the Quota Storage.""" 382 queries = []383 queries.append("DELETE FROM groupsmembers WHERE userid=%s" % self.doQuote(userid))384 queries.append("DELETE FROM jobhistory WHERE userid=%s" % self.doQuote(userid))385 queries.append("DELETE FROM userpquota WHERE userid=%s" % self.doQuote(userid))386 queries.append("DELETE FROM users WHERE id=%s" % self.doQuote(userid))387 392 # TODO : What should we do if we delete the last person who used a given printer ? 388 self.doQuery(queries) 389 390 def deleteGroup(self, groupid) : 391 """Completely deletes an user from the Quota Storage.""" 392 queries = [] 393 queries.append("DELETE FROM groupsmembers WHERE groupid=%s" % self.doQuote(groupid)) 394 queries.append("DELETE FROM grouppquota WHERE groupid=%s" % self.doQuote(groupid)) 395 queries.append("DELETE FROM groups WHERE id=%s" % self.doQuote(groupid)) 396 self.doQuery(queries) 397 398 def computePrinterJobPrice(self, printerid, jobsize) : 399 """Returns the price for a job on a given printer.""" 400 # TODO : create a base class with things like this 401 prices = self.getPrinterPrices(printerid) 402 if prices is None : 403 perpage = perjob = 0.0 404 else : 405 (perpage, perjob) = prices 406 return perjob + (perpage * jobsize) 407 393 # TODO : we can't reassign the last job to the previous one, because next user would be 394 # TODO : incorrectly charged (overcharged). 395 for q in [ 396 "DELETE FROM groupsmembers WHERE userid=%s" % self.doQuote(user.ident), 397 "DELETE FROM jobhistory WHERE userid=%s" % self.doQuote(user.ident), 398 "DELETE FROM userpquota WHERE userid=%s" % self.doQuote(user.ident), 399 "DELETE FROM users WHERE id=%s" % self.doQuote(user.ident), 400 ] : 401 self.doModify(q) 402 403 def deleteGroup(self, group) : 404 """Completely deletes a group from the Quota Storage.""" 405 for q in [ 406 "DELETE FROM groupsmembers WHERE groupid=%s" % self.doQuote(group.ident), 407 "DELETE FROM grouppquota WHERE groupid=%s" % self.doQuote(group.ident), 408 "DELETE FROM groups WHERE id=%s" % self.doQuote(group.ident), 409 ] : 410 self.doModify(q) 411 -
pykota/trunk/pykota/tool.py
r1021 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.41 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.40 2003/06/10 16:37:54 jalet 24 27 # Deletion of the second user which is not needed anymore. … … 305 308 touser = "%s@%s" % (touser, self.smtpserver) 306 309 server = smtplib.SMTP(self.smtpserver) 307 server.sendmail(adminmail, [touser], fullmessage) 310 try : 311 server.sendmail(adminmail, [touser], fullmessage) 312 except smtplib.SMTPRecipientsRefused, answer : 313 for (k, v) in answer.recipients.items() : 314 self.logger.log_message(_("Impossible to send mail to %s, error %s : %s") % (k, v[0], v[1]), "error") 308 315 server.quit() 309 316 … … 317 324 self.sendMessage(adminmail, adminmail, "Subject: %s\n\n%s" % (subject, message)) 318 325 319 def checkGroupPQuota(self, group name, printername) :326 def checkGroupPQuota(self, grouppquota) : 320 327 """Checks the group quota on a printer and deny or accept the job.""" 321 printerid = self.storage.getPrinterId(printername) 322 policy = self.config.getPrinterPolicy(printername) 323 groupid = self.storage.getGroupId(groupname) 324 limitby = self.storage.getGroupLimitBy(groupid) 325 if limitby == "balance" : 326 balance = self.storage.getGroupBalance(groupid) 327 if balance is None : 328 group = grouppquota.Group 329 printer = grouppquota.Printer 330 if group.LimitBy.lower() == "balance" : 331 # TODO : there's no warning (no account balance soft limit) 332 if float(group.AccountBalance) <= 0.0 : 333 action = "DENY" 334 else : 335 action = "ALLOW" 336 else : 337 if grouppquota.SoftLimit is not None : 338 softlimit = int(grouppquota.SoftLimit) 339 if grouppquota.PageCounter < softlimit : 340 action = "ALLOW" 341 else : 342 if grouppquota.HardLimit is None : 343 # only a soft limit, this is equivalent to having only a hard limit 344 action = "DENY" 345 else : 346 hardlimit = int(grouppquota.HardLimit) 347 if softlimit <= grouppquota.PageCounter < hardlimit : 348 now = DateTime.now() 349 if grouppquota.DateLimit is not None : 350 datelimit = DateTime.ISO.ParseDateTime(grouppquota.DateLimit) 351 else : 352 datelimit = now + self.config.getGraceDelay(printer.Name) 353 grouppquota.setDateLimit(datelimit) 354 if now < datelimit : 355 action = "WARN" 356 else : 357 action = "DENY" 358 else : 359 action = "DENY" 360 else : 361 if grouppquota.HardLimit is not None : 362 # no soft limit, only a hard one. 363 hardlimit = int(grouppquota.HardLimit) 364 if grouppquota.PageCounter < hardlimit : 365 action = "ALLOW" 366 else : 367 action = "DENY" 368 else : 369 # Both are unset, no quota, i.e. accounting only 370 action = "ALLOW" 371 return action 372 373 def checkUserPQuota(self, userpquota) : 374 """Checks the user quota on a printer and deny or accept the job.""" 375 user = userpquota.User 376 printer = userpquota.Printer 377 378 # first we check any group the user is a member of 379 for group in self.storage.getUserGroups(user) : 380 grouppquota = self.storage.getGroupPQuota(group, printer) 381 if grouppquota.Exists : 382 action = self.checkGroupPQuota(grouppquota) 383 if action == "DENY" : 384 return action 385 386 # then we check the user's own quota 387 policy = self.config.getPrinterPolicy(printer.Name) 388 if user.LimitBy.lower() == "balance" : 389 if user.AccountBalance is None : 328 390 if policy == "ALLOW" : 329 391 action = "POLICY_ALLOW" 330 392 else : 331 393 action = "POLICY_DENY" 332 self.logger.log_message(_("Unable to find group %s's account balance, applying default policy (%s) for printer %s") % (groupname, action, printername))394 self.logger.log_message(_("Unable to find user %s's account balance, applying default policy (%s) for printer %s") % (user.Name, action, printer.Name)) 333 395 else : 334 396 # TODO : there's no warning (no account balance soft limit) 335 (balance, lifetimepaid) = balance 336 if balance <= 0.0 : 397 if float(user.AccountBalance or 0.0) <= 0.0 : 337 398 action = "DENY" 338 399 else : 339 400 action = "ALLOW" 340 401 else : 341 quota = self.storage.getGroupPQuota(groupid, printerid) 342 if quota is None : 343 # Unknown group or printer or combination 402 if not userpquota.Exists : 403 # Unknown userquota 344 404 if policy == "ALLOW" : 345 405 action = "POLICY_ALLOW" 346 406 else : 347 407 action = "POLICY_DENY" 348 self.logger.log_message(_("Unable to match group %s on printer %s, applying default policy (%s)") % (groupname, printername, action))408 self.logger.log_message(_("Unable to match user %s on printer %s, applying default policy (%s)") % (user.Name, printer.Name, action)) 349 409 else : 350 pagecounter = quota["pagecounter"] 351 softlimit = quota["softlimit"] 352 hardlimit = quota["hardlimit"] 353 datelimit = quota["datelimit"] 354 if softlimit is not None : 410 pagecounter = int(userpquota.PageCounter or 0) 411 if userpquota.SoftLimit is not None : 412 softlimit = int(userpquota.SoftLimit) 355 413 if pagecounter < softlimit : 356 414 action = "ALLOW" 357 415 else : 358 if hardlimit is None :416 if userpquota.HardLimit is None : 359 417 # only a soft limit, this is equivalent to having only a hard limit 360 418 action = "DENY" 361 419 else : 420 hardlimit = int(userpquota.HardLimit) 362 421 if softlimit <= pagecounter < hardlimit : 363 422 now = DateTime.now() 364 if datelimit is not None :365 datelimit = DateTime.ISO.ParseDateTime( datelimit)423 if userpquota.DateLimit is not None : 424 datelimit = DateTime.ISO.ParseDateTime(userpquota.DateLimit) 366 425 else : 367 datelimit = now + self.config.getGraceDelay(printer name)368 self.storage.setGroupDateLimit(groupid, printerid,datelimit)426 datelimit = now + self.config.getGraceDelay(printer.Name) 427 userpquota.setDateLimit(datelimit) 369 428 if now < datelimit : 370 429 action = "WARN" … … 374 433 action = "DENY" 375 434 else : 376 if hardlimit is not None :435 if userpquota.HardLimit is not None : 377 436 # no soft limit, only a hard one. 437 hardlimit = int(userpquota.HardLimit) 378 438 if pagecounter < hardlimit : 379 439 action = "ALLOW" … … 385 445 return action 386 446 387 def checkUserPQuota(self, username, printername) : 388 """Checks the user quota on a printer and deny or accept the job.""" 389 # first we check any group the user is a member of 390 userid = self.storage.getUserId(username) 391 for groupname in self.storage.getUserGroupsNames(userid) : 392 action = self.checkGroupPQuota(groupname, printername) 393 if action in ("DENY", "POLICY_DENY") : 394 return action 395 396 # then we check the user's own quota 397 printerid = self.storage.getPrinterId(printername) 398 policy = self.config.getPrinterPolicy(printername) 399 limitby = self.storage.getUserLimitBy(userid) 400 if limitby == "balance" : 401 balance = self.storage.getUserBalance(userid) 402 if balance is None : 403 if policy == "ALLOW" : 404 action = "POLICY_ALLOW" 405 else : 406 action = "POLICY_DENY" 407 self.logger.log_message(_("Unable to find user %s's account balance, applying default policy (%s) for printer %s") % (username, action, printername)) 408 else : 409 # TODO : there's no warning (no account balance soft limit) 410 (balance, lifetimepaid) = balance 411 if balance <= 0.0 : 412 action = "DENY" 413 else : 414 action = "ALLOW" 415 else : 416 quota = self.storage.getUserPQuota(userid, printerid) 417 if quota is None : 418 # Unknown user or printer or combination 419 if policy == "ALLOW" : 420 action = "POLICY_ALLOW" 421 else : 422 action = "POLICY_DENY" 423 self.logger.log_message(_("Unable to match user %s on printer %s, applying default policy (%s)") % (username, printername, action)) 424 else : 425 pagecounter = quota["pagecounter"] 426 softlimit = quota["softlimit"] 427 hardlimit = quota["hardlimit"] 428 datelimit = quota["datelimit"] 429 if softlimit is not None : 430 if pagecounter < softlimit : 431 action = "ALLOW" 432 else : 433 if hardlimit is None : 434 # only a soft limit, this is equivalent to having only a hard limit 435 action = "DENY" 436 else : 437 if softlimit <= pagecounter < hardlimit : 438 now = DateTime.now() 439 if datelimit is not None : 440 datelimit = DateTime.ISO.ParseDateTime(datelimit) 441 else : 442 datelimit = now + self.config.getGraceDelay(printername) 443 self.storage.setUserDateLimit(userid, printerid, datelimit) 444 if now < datelimit : 445 action = "WARN" 446 else : 447 action = "DENY" 448 else : 449 action = "DENY" 450 else : 451 if hardlimit is not None : 452 # no soft limit, only a hard one. 453 if pagecounter < hardlimit : 454 action = "ALLOW" 455 else : 456 action = "DENY" 457 else : 458 # Both are unset, no quota, i.e. accounting only 459 action = "ALLOW" 460 return action 461 462 def warnGroupPQuota(self, groupname, printername) : 447 def warnGroupPQuota(self, grouppquota) : 463 448 """Checks a group quota and send messages if quota is exceeded on current printer.""" 464 admin = self.config.getAdmin(printername) 465 adminmail = self.config.getAdminMail(printername) 466 mailto = self.config.getMailTo(printername) 467 action = self.checkGroupPQuota(groupname, printername) 468 groupmembers = self.storage.getGroupMembersNames(groupname) 449 group = grouppquota.Group 450 printer = grouppquota.Printer 451 admin = self.config.getAdmin(printer.Name) 452 adminmail = self.config.getAdminMail(printer.Name) 453 mailto = self.config.getMailTo(printer.Name) 454 action = self.checkGroupPQuota(grouppquota, printer) 469 455 if action.startswith("POLICY_") : 470 456 action = action[7:] 471 457 if action == "DENY" : 472 adminmessage = _("Print Quota exceeded for group %s on printer %s") % (group name, printername)458 adminmessage = _("Print Quota exceeded for group %s on printer %s") % (group.Name, printer.Name) 473 459 self.logger.log_message(adminmessage) 474 460 if mailto in [ "BOTH", "ADMIN" ] : 475 461 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 476 for user name in groupmembers:462 for user in self.storage.getGroupMembers(group) : 477 463 if mailto in [ "BOTH", "USER" ] : 478 self.sendMessageToUser(admin, adminmail, user name, _("Print Quota Exceeded"), _("You are not allowed to print anymore because\nyour group Print Quota is exceeded on printer %s.") % printername)464 self.sendMessageToUser(admin, adminmail, user.Name, _("Print Quota Exceeded"), _("You are not allowed to print anymore because\nyour group Print Quota is exceeded on printer %s.") % printer.Name) 479 465 elif action == "WARN" : 480 adminmessage = _("Print Quota soft limit exceeded for group %s on printer %s") % (group name, printername)466 adminmessage = _("Print Quota soft limit exceeded for group %s on printer %s") % (group.Name, printer.Name) 481 467 self.logger.log_message(adminmessage) 482 468 if mailto in [ "BOTH", "ADMIN" ] : 483 469 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 484 for user name in groupmembers:470 for user in self.storage.getGroupMembers(group) : 485 471 if mailto in [ "BOTH", "USER" ] : 486 self.sendMessageToUser(admin, adminmail, user name, _("Print Quota Exceeded"), _("You will soon be forbidden to print anymore because\nyour group Print Quota is almost reached on printer %s.") % printername)472 self.sendMessageToUser(admin, adminmail, user.Name, _("Print Quota Exceeded"), _("You will soon be forbidden to print anymore because\nyour group Print Quota is almost reached on printer %s.") % printer.Name) 487 473 return action 488 474 489 def warnUserPQuota(self, user name, printername) :475 def warnUserPQuota(self, userpquota) : 490 476 """Checks a user quota and send him a message if quota is exceeded on current printer.""" 491 admin = self.config.getAdmin(printername) 492 adminmail = self.config.getAdminMail(printername) 493 mailto = self.config.getMailTo(printername) 494 action = self.checkUserPQuota(username, printername) 477 user = userpquota.User 478 printer = userpquota.Printer 479 admin = self.config.getAdmin(printer.Name) 480 adminmail = self.config.getAdminMail(printer.Name) 481 mailto = self.config.getMailTo(printer.Name) 482 action = self.checkUserPQuota(userpquota) 495 483 if action.startswith("POLICY_") : 496 484 action = action[7:] 497 485 if action == "DENY" : 498 adminmessage = _("Print Quota exceeded for user %s on printer %s") % (user name, printername)486 adminmessage = _("Print Quota exceeded for user %s on printer %s") % (user.Name, printer.Name) 499 487 self.logger.log_message(adminmessage) 500 488 if mailto in [ "BOTH", "USER" ] : 501 self.sendMessageToUser(admin, adminmail, user name, _("Print Quota Exceeded"), _("You are not allowed to print anymore because\nyour Print Quota is exceeded on printer %s.") % printername)489 self.sendMessageToUser(admin, adminmail, user.Name, _("Print Quota Exceeded"), _("You are not allowed to print anymore because\nyour Print Quota is exceeded on printer %s.") % printer.Name) 502 490 if mailto in [ "BOTH", "ADMIN" ] : 503 491 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 504 492 elif action == "WARN" : 505 adminmessage = _("Print Quota soft limit exceeded for user %s on printer %s") % (user name, printername)493 adminmessage = _("Print Quota soft limit exceeded for user %s on printer %s") % (user.Name, printer.Name) 506 494 self.logger.log_message(adminmessage) 507 495 if mailto in [ "BOTH", "USER" ] : 508 self.sendMessageToUser(admin, adminmail, user name, _("Print Quota Exceeded"), _("You will soon be forbidden to print anymore because\nyour Print Quota is almost reached on printer %s.") % printername)496 self.sendMessageToUser(admin, adminmail, user.Name, _("Print Quota Exceeded"), _("You will soon be forbidden to print anymore because\nyour Print Quota is almost reached on printer %s.") % printer.Name) 509 497 if mailto in [ "BOTH", "ADMIN" ] : 510 498 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage)