root / pykota / trunk / pykota / storages / ldapstorage.py @ 1030

Revision 1030, 24.8 kB (checked in by jalet, 21 years ago)

More work on LDAP

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[1016]1# PyKota
2#
3# PyKota : Print Quotas for CUPS and LPRng
4#
5# (c) 2003 Jerome Alet <alet@librelogiciel.com>
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19#
20# $Id$
21#
22# $Log$
[1030]23# Revision 1.8  2003/06/15 22:26:52  jalet
24# More work on LDAP
25#
[1029]26# Revision 1.7  2003/06/14 22:44:21  jalet
27# More work on LDAP storage backend.
28#
[1027]29# Revision 1.6  2003/06/13 19:07:57  jalet
30# Two big bugs fixed, time to release something ;-)
31#
[1021]32# Revision 1.5  2003/06/10 16:37:54  jalet
33# Deletion of the second user which is not needed anymore.
34# Added a debug configuration field in /etc/pykota.conf
35# All queries can now be sent to the logger in debug mode, this will
36# greatly help improve performance when time for this will come.
37#
[1020]38# Revision 1.4  2003/06/10 10:45:32  jalet
39# Not implemented methods now raise an exception when called.
40#
[1018]41# Revision 1.3  2003/06/06 20:49:15  jalet
42# Very latest schema. UNTESTED.
43#
[1017]44# Revision 1.2  2003/06/06 14:21:08  jalet
45# New LDAP schema.
46# Small bug fixes.
47#
[1016]48# Revision 1.1  2003/06/05 11:19:13  jalet
49# More good work on LDAP storage.
50#
51#
52#
53
54#
55# My IANA assigned number, for
56# "Conseil Internet & Logiciels Libres, J�me Alet"
57# is 16868. Use this as a base to create the LDAP schema.
58#
59
[1030]60import time
61import md5
[1016]62import fnmatch
63
64from pykota.storage import PyKotaStorageError
65
66try :
67    import ldap
[1030]68    from ldap import modlist
[1016]69except ImportError :   
70    import sys
71    # TODO : to translate or not to translate ?
72    raise PyKotaStorageError, "This python version (%s) doesn't seem to have the python-ldap module installed correctly." % sys.version.split()[0]
73   
74class Storage :
[1021]75    def __init__(self, pykotatool, host, dbname, user, passwd) :
[1016]76        """Opens the LDAP connection."""
77        # raise PyKotaStorageError, "Sorry, the LDAP backend for PyKota is not yet implemented !"
[1029]78        self.closed = 1
[1021]79        self.tool = pykotatool
80        self.debug = pykotatool.config.getDebug()
[1029]81        self.info = pykotatool.config.getLDAPInfo()
[1016]82        try :
83            self.database = ldap.initialize(host) 
84            self.database.simple_bind_s(user, passwd)
85            self.basedn = dbname
86        except ldap.SERVER_DOWN :   
87            raise PyKotaStorageError, "LDAP backend for PyKota seems to be down !" # TODO : translate
88        else :   
89            self.closed = 0
[1021]90            if self.debug :
91                self.tool.logger.log_message("Database opened (host=%s, dbname=%s, user=%s)" % (host, dbname, user), "debug")
[1016]92           
93    def __del__(self) :       
94        """Closes the database connection."""
95        if not self.closed :
96            del self.database
97            self.closed = 1
[1021]98            if self.debug :
99                self.tool.logger.log_message("Database closed.", "debug")
[1016]100       
[1030]101    def genUUID(self) :   
102        """Generates an unique identifier.
103       
104           TODO : this one is not unique accross several print servers, but should be sufficient for testing.
105        """
106        return md5.md5("%s" % time.time()).hexdigest()
107       
108    def doSearch(self, key, fields=None, base="", scope=ldap.SCOPE_SUBTREE) :
[1016]109        """Does an LDAP search query."""
110        try :
[1030]111            base = base or self.basedn
[1021]112            if self.debug :
[1030]113                self.tool.logger.log_message("QUERY : BaseDN : %s, Scope : %s, Filter : %s, Attributes : %s" % (base, scope, key, fields), "debug")
[1017]114            result = self.database.search_s(base or self.basedn, scope, key, fields)
[1030]115        except ldap.LDAPError :   
116            raise PyKotaStorageError, _("Search for %s(%s) from %s(scope=%s) returned no answer.") % (key, fields, base, scope)
[1016]117        else :     
118            return result
[1030]119           
120    def doAdd(self, dn, fields) :
121        """Adds an entry in the LDAP directory."""
122        try :
123            if self.debug :
124                self.tool.logger.log_message("QUERY : ADD(%s, %s)" % (dn, str(fields)), "debug")
125            self.database.add_s(dn, modlist.addModlist(fields))
126        except ldap.LDAPError :
127            raise PyKotaStorageError, _("Problem adding LDAP entry (%s, %s)") % (dn, str(fields))
128        else :
129            return dn
130           
131    def doModify(self, dn, fields) :
132        """Modifies an entry in the LDAP directory."""
133        try :
134            oldentry = self.doSearch("objectClass=*", base=dn, scope=ldap.SCOPE_BASE)
135            if self.debug :
136                self.tool.logger.log_message("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry[0][1], fields), "debug")
137            self.database.modify_s(dn, modlist.modifyModlist(oldentry[0][1], fields, ignore_oldexistent=1))
138        except ldap.LDAPError :
139            raise PyKotaStorageError, _("Problem modifying LDAP entry (%s, %s)") % (dn, fields)
140        else :
141            return dn
[1016]142       
143    def getMatchingPrinters(self, printerpattern) :
144        """Returns the list of all printers as tuples (id, name) for printer names which match a certain pattern."""
[1029]145        result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName"], base=self.info["printerbase"])
[1016]146        if result :
147            return [(printerid, printer["pykotaPrinterName"][0]) for (printerid, printer) in result if fnmatch.fnmatchcase(printer["pykotaPrinterName"][0], printerpattern)]
148           
149    def getPrinterId(self, printername) :       
150        """Returns a printerid given a printername."""
[1029]151        result = self.doSearch("(&(objectClass=pykotaPrinter)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaPrinterName"], base=self.info["printerbase"])
[1016]152        if result :
153            return result[0][0]
154           
[1030]155    def getPrinterName(self, printerid) :       
156        """Returns a printerid given a printer id."""
157        result = self.doSearch("objectClass=*", ["pykotaPrinterName"], base=printerid, scope=ldap.SCOPE_BASE)
158        if result :
159            return result[0][1]["pykotaPrinterName"][0]
160           
[1016]161    def getPrinterPrices(self, printerid) :       
162        """Returns a printer prices per page and per job given a printerid."""
[1029]163        result = self.doSearch("(|(pykotaPrinterName=*)(%s=*))" % self.info["printerrdn"], ["pykotaPricePerPage", "pykotaPricePerJob"], base=printerid, scope=ldap.SCOPE_BASE)
[1016]164        if result :
165            return (float(result[0][1]["pykotaPricePerPage"][0]), float(result[0][1]["pykotaPricePerJob"][0]))
166           
167    def setPrinterPrices(self, printerid, perpage, perjob) :
168        """Sets prices per job and per page for a given printer."""
[1020]169        raise PyKotaStorageError, "Not implemented !"
[1016]170   
171    def getUserId(self, username) :
172        """Returns a userid given a username."""
[1029]173        result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), [self.info["userrdn"]], base=self.info["userbase"])
[1016]174        if result :
175            return result[0][0]
176           
177    def getGroupId(self, groupname) :
178        """Returns a groupid given a grupname."""
[1029]179        result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), [self.info["grouprdn"]], base=self.info["groupbase"])
[1016]180        if result is not None :
181            (groupid, dummy) = result[0]
182            return groupid
183           
184    def getJobHistoryId(self, jobid, userid, printerid) :       
[1027]185        """Returns the history line's id given a (jobid, userid, printerid).
186       
187           TODO : delete because shouldn't be needed by the LDAP backend
188        """
[1020]189        raise PyKotaStorageError, "Not implemented !"
[1016]190           
191    def getPrinterUsers(self, printerid) :       
192        """Returns the list of userids and usernames which uses a given printer."""
[1017]193        # first get the printer's name from the id
[1029]194        result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE)
[1016]195        if result :
[1018]196            fields = result[0][1]
[1029]197            printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0]
198            result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaPrinterName=%s))" % printername, ["pykotaUserName"], base=self.info["userquotabase"]) 
[1017]199            if result :
200                return [(pquotauserid, fields["pykotaUserName"][0]) for (pquotauserid, fields) in result]
[1016]201       
202    def getPrinterGroups(self, printerid) :       
203        """Returns the list of groups which uses a given printer."""
[1017]204        # first get the printer's name from the id
[1029]205        result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE)
[1016]206        if result :
[1018]207            fields = result[0][1]
[1029]208            printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0]
209            result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaPrinterName=%s))" % printername, ["pykotaGroupName"], base=self.info["groupquotabase"]) 
[1017]210            if result :
211                return [(pquotagroupid, fields["pykotaGroupName"][0]) for (pquotagroupid, fields) in result]
[1016]212       
213    def getGroupMembersNames(self, groupname) :       
214        """Returns the list of user's names which are member of this group."""
[1029]215        result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), [self.info["groupmembers"]])
[1016]216        if result :
[1018]217            fields = result[0][1]
[1029]218            return fields.get(self.info["groupmembers"])
[1016]219       
220    def getUserGroupsNames(self, userid) :       
221        """Returns the list of groups' names the user is a member of."""
[1020]222        raise PyKotaStorageError, "Not implemented !"
[1016]223       
224    def addPrinter(self, printername) :       
225        """Adds a printer to the quota storage, returns its id."""
[1030]226        fields = { self.info["printerrdn"] : printername,
227                   "objectClass" : ["pykotaObject", "pykotaPrinter"],
228                   "pykotaPrinterName" : printername,
229                   "pykotaPricePerPage" : "0.0",
230                   "pykotaPricePerJob" : "0.0",
231                 } 
232        dn = "%s=%s,%s" % (self.info["printerrdn"], printername, self.info["printerbase"])
233        return self.doAdd(dn, fields)
[1016]234       
235    def addUser(self, username) :       
236        """Adds a user to the quota storage, returns its id."""
[1030]237        fields = { self.info["userrdn"] : username,
238                   "objectClass" : ["pykotaObject", "pykotaAccount", "pykotaAccountBalance"],
239                   "pykotaUserName" : username,
240                   "pykotaLimitBy" : "quota",
241                   "pykotaBalance" : "0.0",
242                   "pykotaLifeTimePaid" : "0.0",
243                 } 
244        dn = "%s=%s,%s" % (self.info["userrdn"], username, self.info["userbase"])
245        return self.doAdd(dn, fields)
[1016]246       
247    def addGroup(self, groupname) :       
248        """Adds a group to the quota storage, returns its id."""
[1030]249        fields = { self.info["grouprdn"] : groupname,
250                   "objectClass" : ["pykotaObject", "pykotaGroup"],
251                   "pykotaGroupName" : groupname,
252                   "pykotaLimitBy" : "quota",
253                 } 
254        dn = "%s=%s,%s" % (self.info["grouprdn"], groupname, self.info["groupbase"])
255        return self.doAdd(dn, fields)
[1016]256       
257    def addUserPQuota(self, username, printerid) :
258        """Initializes a user print quota on a printer, adds the user to the quota storage if needed."""
[1030]259        uuid = self.genUUID()
260        fields = { "objectClass" : ["pykotaObject", "pykotaUserPQuota"],
261                   "cn" : uuid,
262                   "pykotaUserName" : username,
263                   "pykotaPrinterName" : self.getPrinterName(printerid), 
264                   "pykotaPageCounter" : "0",
265                   "pykotaLifePageCounter" : "0",
266                   "pykotaSoftLimit" : "0",
267                   "pykotaHardLimit" : "0",
268                   "pykotaDateLimit" : "None",
269                 } 
270        dn = "cn=%s,%s" % (uuid, self.info["userquotabase"])
271        return self.doAdd(dn, fields)
[1016]272       
273    def addGroupPQuota(self, groupname, printerid) :
274        """Initializes a group print quota on a printer, adds the group to the quota storage if needed."""
[1030]275        uuid = self.genUUID()
276        fields = { "objectClass" : ["pykotaObject", "pykotaGroupPQuota"],
277                   "cn" : uuid,
278                   "pykotaGroupName" : groupname,
279                   "pykotaPrinterName" : self.getPrinterName(printerid), 
280                   "pykotaSoftLimit" : "0",
281                   "pykotaHardLimit" : "0",
282                   "pykotaDateLimit" : "None",
283                 } 
284        dn = "cn=%s,%s" % (uuid, self.info["groupquotabase"])
285        return self.doAdd(dn, fields)
[1016]286       
287    def increaseUserBalance(self, userid, amount) :   
288        """Increases (or decreases) an user's account balance by a given amount."""
[1020]289        raise PyKotaStorageError, "Not implemented !"
[1016]290       
[1017]291    def getUserBalance(self, userquotaid) :   
292        """Returns the current account balance for a given user quota identifier."""
293        # first get the user's name from the user quota id
294        result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE)
[1016]295        if result :
[1017]296            username = result[0][1]["pykotaUserName"][0]
[1029]297            result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"])
[1017]298            if result :
299                fields = result[0][1]
300                return (float(fields["pykotaBalance"][0]), float(fields["pykotaLifeTimePaid"][0]))
[1016]301       
[1017]302    def getUserBalanceFromUserId(self, userid) :   
303        """Returns the current account balance for a given user id."""
304        # first get the user's name from the user id
[1029]305        result = self.doSearch("objectClass=pykotaAccount", ["pykotaUserName", self.info["userrdn"]], base=userid, scope=ldap.SCOPE_BASE)
[1017]306        if result :
[1018]307            fields = result[0][1]
[1029]308            username = (fields.get("pykotaUserName") or fields.get(self.info["userrdn"]))[0]
309            result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"])
[1017]310            if result :
311                fields = result[0][1]
312                return (float(fields["pykotaBalance"][0]), float(fields["pykotaLifeTimePaid"][0]))
313       
314    def getGroupBalance(self, groupquotaid) :   
[1016]315        """Returns the current account balance for a given group, as the sum of each of its users' account balance."""
[1017]316        # first get the group's name from the group quota id
317        result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE)
318        if result :
319            groupname = result[0][1]["pykotaGroupName"][0]
320            members = self.getGroupMembersNames(groupname)
321            balance = lifetimepaid = 0.0
322            for member in members :
323                userid = self.getUserId(member)
324                if userid :
325                    userbal = self.getUserBalanceFromUserId(userid)
326                    if userbal :
327                        (bal, paid) = userbal
328                        balance += bal
329                        lifetimepaid += paid
330            return (balance, lifetimepaid)           
[1016]331       
[1029]332    def getUserLimitBy(self, userquotaid) :   
[1016]333        """Returns the way in which user printing is limited."""
[1029]334        result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE)
[1016]335        if result :
[1029]336            username = result[0][1]["pykotaUserName"][0]
337            result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaLimitBy"])
338            if result :
339                return result[0][1]["pykotaLimitBy"][0]
[1016]340       
[1017]341    def getGroupLimitBy(self, groupquotaid) :   
[1016]342        """Returns the way in which group printing is limited."""
[1017]343        # first get the group's name from the group quota id
344        result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE)
[1016]345        if result :
[1017]346            groupname = result[0][1]["pykotaGroupName"][0]
[1029]347            result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), ["pykotaLimitBy"])
[1017]348            if result :
349                return result[0][1]["pykotaLimitBy"][0]
[1016]350       
351    def setUserBalance(self, userid, balance) :   
352        """Sets the account balance for a given user to a fixed value."""
[1020]353        raise PyKotaStorageError, "Not implemented !"
[1016]354       
355    def limitUserBy(self, userid, limitby) :   
356        """Limits a given user based either on print quota or on account balance."""
[1020]357        raise PyKotaStorageError, "Not implemented !"
[1016]358       
359    def limitGroupBy(self, groupid, limitby) :   
360        """Limits a given group based either on print quota or on sum of its users' account balances."""
[1020]361        raise PyKotaStorageError, "Not implemented !"
[1016]362       
[1030]363    def setUserPQuota(self, userquotaid, printerid, softlimit, hardlimit) :
[1016]364        """Sets soft and hard limits for a user quota on a specific printer given (userid, printerid)."""
[1030]365        fields = { 
366                   "pykotaSoftLimit" : str(softlimit),
367                   "pykotaHardLimit" : str(hardlimit),
368                 } 
369        return self.doModify(userquotaid, fields)
[1016]370       
[1030]371    def setGroupPQuota(self, groupquotaid, printerid, softlimit, hardlimit) :
[1016]372        """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid)."""
[1030]373        fields = { 
374                   "pykotaSoftLimit" : str(softlimit),
375                   "pykotaHardLimit" : str(hardlimit),
376                 } 
377        return self.doModify(groupquotaid, fields)
[1016]378       
379    def resetUserPQuota(self, userid, printerid) :   
380        """Resets the page counter to zero for a user on a printer. Life time page counter is kept unchanged."""
[1020]381        raise PyKotaStorageError, "Not implemented !"
[1016]382       
383    def resetGroupPQuota(self, groupid, printerid) :   
384        """Resets the page counter to zero for a group on a printer. Life time page counter is kept unchanged."""
[1020]385        raise PyKotaStorageError, "Not implemented !"
[1016]386       
387    def updateUserPQuota(self, userid, printerid, pagecount) :
388        """Updates the used user Quota information given (userid, printerid) and a job size in pages."""
[1020]389        raise PyKotaStorageError, "Not implemented !"
[1016]390       
[1017]391    def getUserPQuota(self, userquotaid, printerid) :
392        """Returns the Print Quota information for a given (userquotaid, printerid)."""
393        # first get the user's name from the id
394        result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName", "pykotaPageCounter", "pykotaLifePageCounter", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=userquotaid, scope=ldap.SCOPE_BASE)
[1016]395        if result :
396            fields = result[0][1]
397            datelimit = fields["pykotaDateLimit"][0].strip()
398            if (not datelimit) or (datelimit.upper() == "NONE") : 
399                datelimit = None
400            return { "lifepagecounter" : int(fields["pykotaLifePageCounter"][0]), 
401                     "pagecounter" : int(fields["pykotaPageCounter"][0]),
402                     "softlimit" : int(fields["pykotaSoftLimit"][0]),
403                     "hardlimit" : int(fields["pykotaHardLimit"][0]),
404                     "datelimit" : datelimit
405                   }
406       
[1017]407    def getGroupPQuota(self, grouppquotaid, printerid) :
408        """Returns the Print Quota information for a given (grouppquotaid, printerid)."""
409        result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=grouppquotaid, scope=ldap.SCOPE_BASE)
[1016]410        if result :
411            fields = result[0][1]
[1017]412            groupname = fields["pykotaGroupName"][0]
[1016]413            datelimit = fields["pykotaDateLimit"][0].strip()
414            if (not datelimit) or (datelimit.upper() == "NONE") : 
415                datelimit = None
416            quota = {
417                      "softlimit" : int(fields["pykotaSoftLimit"][0]),
418                      "hardlimit" : int(fields["pykotaHardLimit"][0]),
419                      "datelimit" : datelimit
420                    }
421            members = self.getGroupMembersNames(groupname)
422            pagecounter = lifepagecounter = 0
423            printerusers = self.getPrinterUsers(printerid)
424            if printerusers :
425                for (userid, username) in printerusers :
426                    if username in members :
427                        userpquota = self.getUserPQuota(userid, printerid)
428                        if userpquota :
429                            pagecounter += userpquota["pagecounter"]
430                            lifepagecounter += userpquota["lifepagecounter"]
431            quota.update({"pagecounter": pagecounter, "lifepagecounter": lifepagecounter})               
432            return quota
433       
434    def setUserDateLimit(self, userid, printerid, datelimit) :
435        """Sets the limit date for a soft limit to become an hard one given (userid, printerid)."""
[1020]436        raise PyKotaStorageError, "Not implemented !"
[1016]437       
438    def setGroupDateLimit(self, groupid, printerid, datelimit) :
439        """Sets the limit date for a soft limit to become an hard one given (groupid, printerid)."""
[1020]440        raise PyKotaStorageError, "Not implemented !"
[1016]441       
442    def addJobToHistory(self, jobid, userid, printerid, pagecounter, action) :
443        """Adds a job to the history: (jobid, userid, printerid, last page counter taken from requester)."""
[1020]444        raise PyKotaStorageError, "Not implemented !"
[1016]445   
446    def updateJobSizeInHistory(self, historyid, jobsize) :
447        """Updates a job size in the history given the history line's id."""
[1020]448        raise PyKotaStorageError, "Not implemented !"
[1016]449   
450    def getPrinterPageCounter(self, printerid) :
451        """Returns the last page counter value for a printer given its id, also returns last username, last jobid and history line id."""
[1029]452        result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE)
[1016]453        if result :
[1027]454            fields = result[0][1]
[1029]455            printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0]
456            result = self.doSearch("(&(objectClass=pykotaLastjob)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaLastJobIdent"], base=self.info["lastjobbase"])
[1027]457            if result :
458                lastjobident = result[0][1]["pykotaLastJobIdent"][0]
[1029]459                result = self.doSearch("(&(objectClass=pykotaJob)(cn=%s))" % lastjobident, ["pykotaUserName", "pykotaPrinterName", "pykotaJobId", "pykotaPrinterPageCounter", "pykotaJobSize", "pykotaAction", "createTimestamp"], base=self.info["jobbase"])
[1027]460                if result :
[1029]461                    fields = result[0][1]
462                    return { "id": lastjobident, 
463                             "jobid" : fields.get("pykotaJobId")[0],
464                             "userid" : self.getUserId(fields.get("pykotaUserName")[0]),
465                             "username" : fields.get("pykotaUserName")[0], 
466                             "pagecounter" : int(fields.get("pykotaPrinterPageCounter")[0]),
467                           }
[1016]468       
469    def addUserToGroup(self, userid, groupid) :   
470        """Adds an user to a group."""
[1020]471        raise PyKotaStorageError, "Not implemented !"
[1016]472       
473    def deleteUser(self, userid) :   
474        """Completely deletes an user from the Quota Storage."""
[1020]475        raise PyKotaStorageError, "Not implemented !"
[1016]476       
477    def deleteGroup(self, groupid) :   
478        """Completely deletes an user from the Quota Storage."""
[1020]479        raise PyKotaStorageError, "Not implemented !"
[1016]480       
481    def computePrinterJobPrice(self, printerid, jobsize) :   
482        """Returns the price for a job on a given printer."""
483        # TODO : create a base class with things like this
484        prices = self.getPrinterPrices(printerid)
485        if prices is None :
486            perpage = perjob = 0.0
487        else :   
488            (perpage, perjob) = prices
489        return perjob + (perpage * jobsize)
Note: See TracBrowser for help on using the browser.