Changeset 1041 for pykota/trunk/pykota

Show
Ignore:
Timestamp:
06/25/03 16:10:01 (21 years ago)
Author:
jalet
Message:

Hey, it may work (edpykota --reset excepted) !

Location:
pykota/trunk/pykota
Files:
8 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/pykota/accounters/external.py

    r1000 r1041  
    2121# 
    2222# $Log$ 
     23# Revision 1.4  2003/06/25 14:10:01  jalet 
     24# Hey, it may work (edpykota --reset excepted) ! 
     25# 
    2326# Revision 1.3  2003/05/27 23:00:21  jalet 
    2427# Big rewrite of external accounting methods. 
     
    4144 
    4245class Accounter(AccounterBase) : 
    43     def doAccounting(self, printerid, userid) : 
     46    def doAccounting(self, printer, user) : 
    4447        """Deletgates the computation of the job size to an external command. 
    4548         
     
    5053             
    5154        # 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 : 
    5456            # The printer hasn't been used yet, from PyKota's point of view 
    5557            counterbeforejob = 0 
     
    5860            # Last lifetime page counter before actual job is  
    5961            # 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) 
    6163             
    6264        # 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) 
    6467         
    6568        # update the quota for the current user on this printer, if allowed to print 
     
    6770            jobsize = 0 
    6871        else :     
    69             self.filter.storage.updateUserPQuota(userid, printerid, jobsize) 
     72            userpquota.increasePagesUsage(jobsize) 
    7073         
    7174        # 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) 
    7376             
    7477        return action 
     
    102105            # launches child process 
    103106            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() 
    107107            retcode = os.system(command) 
    108108             
  • pykota/trunk/pykota/accounters/querying.py

    r988 r1041  
    2121# 
    2222# $Log$ 
     23# Revision 1.4  2003/06/25 14:10:01  jalet 
     24# Hey, it may work (edpykota --reset excepted) ! 
     25# 
    2326# Revision 1.3  2003/05/06 14:55:47  jalet 
    2427# Missing import ! 
     
    3841from pykota.requester import openRequester, PyKotaRequesterError 
    3942 
    40 MAXTRIES = 6     # maximum number of tries to get the printer's internal page counter 
     43MAXTRIES = 12    # maximum number of tries to get the printer's internal page counter 
    4144TIMETOSLEEP = 10 # number of seconds to sleep between two tries to get the printer's internal page counter 
    4245 
    4346class Accounter(AccounterBase) : 
    44     def doAccounting(self, printerid, userid) : 
     47    def doAccounting(self, printer, user) : 
    4548        """Does print accounting and returns if the job status is ALLOW or DENY.""" 
    4649        # Get the page counter directly from the printer itself 
     
    6568         
    6669        # 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 : 
    6971            # 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 
    7474            lastpagecounter = counterbeforejob 
    7575        else :     
    7676            # 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 
    7880             
    7981        # if printer is off then we assume the correct counter value is the last one 
     
    107109            # For more accurate accounting, don't switch off your HP printers ! 
    108110            # 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, lastusername, 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") 
    110112            jobsize = abs(int((10 - abs(jobsize)) / 2))     # Workaround for HP printers' feature ! 
    111113             
    112114        # 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) 
    114118         
    115119        # 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) 
    117122         
    118123        # 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) 
    120126             
    121127        # 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)) 
    123129         
    124130        # 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) 
    126132             
    127133        return action 
  • pykota/trunk/pykota/accounters/stupid.py

    r1000 r1041  
    2121# 
    2222# $Log$ 
     23# Revision 1.4  2003/06/25 14:10:01  jalet 
     24# Hey, it may work (edpykota --reset excepted) ! 
     25# 
    2326# Revision 1.3  2003/05/27 23:00:21  jalet 
    2427# Big rewrite of external accounting methods. 
     
    3942 
    4043class Accounter(AccounterBase) : 
    41     def doAccounting(self, printerid, userid) : 
     44    def doAccounting(self, printer, user) : 
    4245        """Does print accounting by stupidly counting the 'showpage' postscript instructions in the document. 
    4346         
     
    5154             
    5255        # 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 : 
    5557            # The printer hasn't been used yet, from PyKota's point of view 
    5658            counterbeforejob = 0 
     
    5961            # Last lifetime page counter before actual job is  
    6062            # 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) 
    6264             
    6365        # 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) 
    6568         
    6669        # update the quota for the current user on this printer, if allowed to print 
     
    6871            jobsize = 0 
    6972        else :     
    70             self.filter.storage.updateUserPQuota(userid, printerid, jobsize) 
     73            userpquota.increasePagesUsage(jobsize) 
    7174         
    7275        # 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) 
    7477             
    7578        return action 
  • pykota/trunk/pykota/config.py

    r1029 r1041  
    2121# 
    2222# $Log$ 
     23# Revision 1.30  2003/06/25 14:10:01  jalet 
     24# Hey, it may work (edpykota --reset excepted) ! 
     25# 
    2326# Revision 1.29  2003/06/14 22:44:21  jalet 
    2427# More work on LDAP storage backend. 
     
    201204        ldapinfo = {} 
    202205        for option in [ "userbase", "userrdn", \ 
     206                        "balancebase", "balancerdn", \ 
    203207                        "groupbase", "grouprdn", "groupmembers", \ 
    204208                        "printerbase", "printerrdn", \ 
  • pykota/trunk/pykota/storage.py

    r1021 r1041  
    2121# 
    2222# $Log$ 
     23# Revision 1.14  2003/06/25 14:10:01  jalet 
     24# Hey, it may work (edpykota --reset excepted) ! 
     25# 
    2326# Revision 1.13  2003/06/10 16:37:54  jalet 
    2427# Deletion of the second user which is not needed anymore. 
     
    8487    __str__ = __repr__ 
    8588         
     89class 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         
     97class 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         
     133class 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         
     160class 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         
     186class 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         
     234class 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         
     258class 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     
    86275def openConnection(pykotatool) : 
    87276    """Returns a connection handle to the appropriate Quota Storage Database.""" 
  • pykota/trunk/pykota/storages/ldapstorage.py

    r1032 r1041  
    2121# 
    2222# $Log$ 
     23# Revision 1.11  2003/06/25 14:10:01  jalet 
     24# Hey, it may work (edpykota --reset excepted) ! 
     25# 
    2326# Revision 1.10  2003/06/16 21:55:15  jalet 
    2427# More work on LDAP, again. Problem detected. 
     
    6669import time 
    6770import md5 
    68 import fnmatch 
    6971 
    7072from pykota.storage import PyKotaStorageError 
     73from pykota.storage import StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 
    7174 
    7275try : 
     
    114117        return md5.md5("%s" % time.time()).hexdigest() 
    115118         
     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         
    116134    def doSearch(self, key, fields=None, base="", scope=ldap.SCOPE_SUBTREE) : 
    117135        """Does an LDAP search query.""" 
     
    119137            base = base or self.basedn 
    120138            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") 
    122140            result = self.database.search_s(base or self.basedn, scope, key, fields) 
    123141        except ldap.LDAPError :     
     
    139157            return dn 
    140158             
    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) : 
    142169        """Modifies an entry in the LDAP directory.""" 
    143170        try : 
     
    145172            if self.debug : 
    146173                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)) 
    148175        except ldap.LDAPError : 
    149176            raise PyKotaStorageError, _("Problem modifying LDAP entry (%s, %s)") % (dn, fields) 
    150177        else : 
    151178            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 
    152353         
    153354    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 
    248417         
    249418    def addPrinter(self, printername) :         
    250         """Adds a printer to the quota storage, returns its id.""" 
     419        """Adds a printer to the quota storage, returns it.""" 
    251420        fields = { self.info["printerrdn"] : printername, 
    252421                   "objectClass" : ["pykotaObject", "pykotaPrinter"], 
     422                   "cn" : printername, 
    253423                   "pykotaPrinterName" : printername, 
    254424                   "pykotaPricePerPage" : "0.0", 
     
    256426                 }  
    257427        dn = "%s=%s,%s" % (self.info["printerrdn"], printername, self.info["printerbase"]) 
    258         return self.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                    "pykotaBalance" : "0.0", 
    267                    "pykotaLifeTimePaid" : "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"), 
    268438                 }  
    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, 
    275455                   "objectClass" : ["pykotaObject", "pykotaGroup"], 
    276                    "pykotaGroupName" : groupname, 
    277                    "pykotaLimitBy" : "quota", 
     456                   "cn" : group.Name, 
     457                   "pykotaGroupName" : group.Name, 
     458                   "pykotaLimitBY" : (group.LimitBy or "quota"), 
    278459                 }  
    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.""" 
    284476        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", 
    289482                   "pykotaPageCounter" : "0", 
    290483                   "pykotaLifePageCounter" : "0", 
    291                    "pykotaSoftLimit" : "0", 
    292                    "pykotaHardLimit" : "0", 
    293                    "pykotaDateLimit" : "None", 
    294484                 }  
    295485        dn = "cn=%s,%s" % (uuid, self.info["userquotabase"]) 
    296486        self.doAdd(dn, fields) 
    297         return (dn, printerid) 
    298          
    299     def addGroupPQuota(self, groupname, 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.""" 
    301491        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, 
    308496                   "pykotaDateLimit" : "None", 
    309497                 }  
    310498        dn = "cn=%s,%s" % (uuid, self.info["groupquotabase"]) 
    311499        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.""" 
    509526        fields = { 
    510527                   "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second), 
    511528                 } 
    512         return self.doModify(userquotaid, 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.""" 
    516533        fields = { 
    517534                   "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second), 
    518535                 } 
    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.""" 
    523564        uuid = self.genUUID() 
    524         printername = self.getPrinterName(printerid) 
    525565        fields = { 
    526566                   "objectClass" : ["pykotaObject", "pykotaJob"], 
    527567                   "cn" : uuid, 
    528                    "pykotaUserName" : self.getUserName(userid), 
    529                    "pykotaPrinterName" : printername, 
     568                   "pykotaUserName" : user.Name, 
     569                   "pykotaPrinterName" : printer.Name, 
    530570                   "pykotaJobId" : jobid, 
    531571                   "pykotaPrinterPageCounter" : str(pagecounter), 
     
    536576        dn = "cn=%s,%s" % (uuid, self.info["jobbase"]) 
    537577        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 : 
    541579            fields = { 
    542580                       "pykotaLastJobIdent" : uuid, 
    543581                     } 
    544             self.doModify(lastjdn, fields)          
     582            self.doModify(printer.LastJob.lastjobident, fields)          
    545583        else :     
    546584            lastjuuid = self.genUUID() 
     
    549587                       "objectClass" : ["pykotaObject", "pykotaLastJob"], 
    550588                       "cn" : lastjuuid, 
    551                        "pykotaPrinterName" : printername, 
     589                       "pykotaPrinterName" : printer.Name, 
    552590                       "pykotaLastJobIdent" : uuid, 
    553591                     }   
    554592            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)     
    568625        if result : 
    569626            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  
    2121# 
    2222# $Log$ 
     23# Revision 1.3  2003/06/25 14:10:01  jalet 
     24# Hey, it may work (edpykota --reset excepted) ! 
     25# 
    2326# Revision 1.2  2003/06/12 21:09:57  jalet 
    2427# wrongly placed code. 
     
    3437# 
    3538 
    36 import fnmatch 
    37  
    3839from pykota.storage import PyKotaStorageError 
     40from pykota.storage import StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 
    3941 
    4042try : 
     
    7476                self.tool.logger.log_message("Database closed.", "debug") 
    7577         
    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.""" 
    8098        query = query.strip()     
    8199        if not query.endswith(';') :     
    82100            query += ';' 
    83         self.database.query("BEGIN;") 
    84         if self.debug : 
    85             self.tool.logger.log_message("Transaction began.", "debug") 
    86101        try : 
    87102            if self.debug : 
     
    89104            result = self.database.query(query) 
    90105        except pg.error, msg :     
    91             self.database.query("ROLLBACK;") 
    92             if self.debug : 
    93                 self.tool.logger.log_message("Transaction aborted.", "debug") 
    94106            raise PyKotaStorageError, msg 
    95107        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 : 
    97117            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             
    101123    def doQuote(self, field) : 
    102124        """Quotes a field for use as a string in SQL queries.""" 
     
    109131        return pg._quote(field, typ) 
    110132         
    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         
    116250    def getMatchingPrinters(self, printerpattern) : 
    117         """Returns the list of all printers as tuples (id, name) for printer names which match a certain pattern.""" 
    118         printerslist = [] 
     251        """Returns the list of all printers for which name matches a certain pattern.""" 
     252        printers = [] 
    119253        # We 'could' do a SELECT printername FROM printers WHERE printername LIKE ... 
    120254        # but we don't because other storages semantics may be different, so every 
    121255        # 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 
    206304         
    207305    def addPrinter(self, printername) :         
    208         """Adds a printer to the quota storage, returns its id.""" 
    209         self.doQuery("INSERT INTO printers (printername) VALUES (%s)" % self.doQuote(printername)) 
    210         return self.getPrinterId(printername) 
    211          
    212     def addUser(self, username) :         
     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) :         
    213311        """Adds a user to the quota storage, returns its id.""" 
    214         self.doQuery("INSERT INTO users (username) VALUES (%s)" % self.doQuote(username)) 
    215         return self.getUserId(username) 
    216          
    217     def addGroup(self, groupname) :         
     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) :         
    218316        """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) :     
    371321        """Adds an user to a group.""" 
    372         result = self.doQuery("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))) 
    373323        try : 
    374324            mexists = self.doParseResult(result)[0]["mexists"] 
     
    376326            mexists = 0 
    377327        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) :     
    381391        """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)) 
    387392        # 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  
    2121# 
    2222# $Log$ 
     23# Revision 1.41  2003/06/25 14:10:01  jalet 
     24# Hey, it may work (edpykota --reset excepted) ! 
     25# 
    2326# Revision 1.40  2003/06/10 16:37:54  jalet 
    2427# Deletion of the second user which is not needed anymore. 
     
    305308            touser = "%s@%s" % (touser, self.smtpserver) 
    306309        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") 
    308315        server.quit() 
    309316         
     
    317324        self.sendMessage(adminmail, adminmail, "Subject: %s\n\n%s" % (subject, message)) 
    318325         
    319     def checkGroupPQuota(self, groupname, printername) :     
     326    def checkGroupPQuota(self, grouppquota) :     
    320327        """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 : 
    328390                if policy == "ALLOW" : 
    329391                    action = "POLICY_ALLOW" 
    330392                else :     
    331393                    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)) 
    333395            else :     
    334396                # 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 : 
    337398                    action = "DENY" 
    338399                else :     
    339400                    action = "ALLOW" 
    340401        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  
    344404                if policy == "ALLOW" : 
    345405                    action = "POLICY_ALLOW" 
    346406                else :     
    347407                    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)) 
    349409            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) 
    355413                    if pagecounter < softlimit : 
    356414                        action = "ALLOW" 
    357415                    else :     
    358                         if hardlimit is None : 
     416                        if userpquota.HardLimit is None : 
    359417                            # only a soft limit, this is equivalent to having only a hard limit 
    360418                            action = "DENY" 
    361419                        else :     
     420                            hardlimit = int(userpquota.HardLimit) 
    362421                            if softlimit <= pagecounter < hardlimit :     
    363422                                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) 
    366425                                else : 
    367                                     datelimit = now + self.config.getGraceDelay(printername) 
    368                                     self.storage.setGroupDateLimit(groupid, printerid, datelimit) 
     426                                    datelimit = now + self.config.getGraceDelay(printer.Name) 
     427                                    userpquota.setDateLimit(datelimit) 
    369428                                if now < datelimit : 
    370429                                    action = "WARN" 
     
    374433                                action = "DENY" 
    375434                else :         
    376                     if hardlimit is not None : 
     435                    if userpquota.HardLimit is not None : 
    377436                        # no soft limit, only a hard one. 
     437                        hardlimit = int(userpquota.HardLimit) 
    378438                        if pagecounter < hardlimit : 
    379439                            action = "ALLOW" 
     
    385445        return action 
    386446     
    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) : 
    463448        """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) 
    469455        if action.startswith("POLICY_") : 
    470456            action = action[7:] 
    471457        if action == "DENY" : 
    472             adminmessage = _("Print Quota exceeded for group %s on printer %s") % (groupname, printername) 
     458            adminmessage = _("Print Quota exceeded for group %s on printer %s") % (group.Name, printer.Name) 
    473459            self.logger.log_message(adminmessage) 
    474460            if mailto in [ "BOTH", "ADMIN" ] : 
    475461                self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 
    476             for username in groupmembers : 
     462            for user in self.storage.getGroupMembers(group) : 
    477463                if mailto in [ "BOTH", "USER" ] : 
    478                     self.sendMessageToUser(admin, adminmail, username, _("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) 
    479465        elif action == "WARN" :     
    480             adminmessage = _("Print Quota soft limit exceeded for group %s on printer %s") % (groupname, printername) 
     466            adminmessage = _("Print Quota soft limit exceeded for group %s on printer %s") % (group.Name, printer.Name) 
    481467            self.logger.log_message(adminmessage) 
    482468            if mailto in [ "BOTH", "ADMIN" ] : 
    483469                self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 
    484             for username in groupmembers : 
     470            for user in self.storage.getGroupMembers(group) : 
    485471                if mailto in [ "BOTH", "USER" ] : 
    486                     self.sendMessageToUser(admin, adminmail, username, _("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) 
    487473        return action         
    488474         
    489     def warnUserPQuota(self, username, printername) : 
     475    def warnUserPQuota(self, userpquota) : 
    490476        """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) 
    495483        if action.startswith("POLICY_") : 
    496484            action = action[7:] 
    497485        if action == "DENY" : 
    498             adminmessage = _("Print Quota exceeded for user %s on printer %s") % (username, printername) 
     486            adminmessage = _("Print Quota exceeded for user %s on printer %s") % (user.Name, printer.Name) 
    499487            self.logger.log_message(adminmessage) 
    500488            if mailto in [ "BOTH", "USER" ] : 
    501                 self.sendMessageToUser(admin, adminmail, username, _("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) 
    502490            if mailto in [ "BOTH", "ADMIN" ] : 
    503491                self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 
    504492        elif action == "WARN" :     
    505             adminmessage = _("Print Quota soft limit exceeded for user %s on printer %s") % (username, printername) 
     493            adminmessage = _("Print Quota soft limit exceeded for user %s on printer %s") % (user.Name, printer.Name) 
    506494            self.logger.log_message(adminmessage) 
    507495            if mailto in [ "BOTH", "USER" ] : 
    508                 self.sendMessageToUser(admin, adminmail, username, _("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) 
    509497            if mailto in [ "BOTH", "ADMIN" ] : 
    510498                self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage)