root / pykota / trunk / pykota / storages / sql.py @ 1761

Revision 1761, 32.0 kB (checked in by jalet, 20 years ago)

Should now correctly deal with charsets both when storing into databases and when
retrieving datas. Works with both PostgreSQL and LDAP.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1# PyKota
2# -*- coding: ISO-8859-15 -*-
3#
4# PyKota : Print Quotas for CUPS and LPRng
5#
6# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20#
21# $Id$
22#
23# $Log$
24# Revision 1.48  2004/10/02 05:48:56  jalet
25# Should now correctly deal with charsets both when storing into databases and when
26# retrieving datas. Works with both PostgreSQL and LDAP.
27#
28# Revision 1.47  2004/09/15 07:26:20  jalet
29# Data dumps are now ordered by entry creation date if applicable.
30# Now dumpykota exits with a message when there's a broken pipe like
31# in dumpykota --data history | head -3
32#
33# Revision 1.46  2004/09/15 06:58:25  jalet
34# User groups membership and printer groups membership can now be dumped too
35#
36# Revision 1.45  2004/09/14 22:29:13  jalet
37# First version of dumpykota. Works fine but only with PostgreSQL backend
38# for now.
39#
40# Revision 1.44  2004/09/10 21:32:54  jalet
41# Small fixes for incomplete entry intialization
42#
43# Revision 1.43  2004/07/01 17:45:49  jalet
44# Added code to handle the description field for printers
45#
46# Revision 1.42  2004/06/08 17:44:43  jalet
47# Payment now gets deleted when the user is deleted
48#
49# Revision 1.41  2004/06/05 22:03:50  jalet
50# Payments history is now stored in database
51#
52# Revision 1.40  2004/06/03 23:14:11  jalet
53# Now stores the job's size in bytes in the database.
54# Preliminary work on payments storage : database schemas are OK now,
55# but no code to store payments yet.
56# Removed schema picture, not relevant anymore.
57#
58# Revision 1.39  2004/05/26 14:50:12  jalet
59# First try at saving the job-originating-hostname in the database
60#
61# Revision 1.38  2004/05/06 12:37:47  jalet
62# pkpgcounter : comments
63# pkprinters : when --add is used, existing printers are now skipped.
64#
65# Revision 1.37  2004/02/23 22:53:21  jalet
66# Don't retrieve data when it's not needed, to avoid database queries
67#
68# Revision 1.36  2004/02/04 13:24:41  jalet
69# pkprinters can now remove printers from printers groups.
70#
71# Revision 1.35  2004/02/04 11:17:00  jalet
72# pkprinters command line tool added.
73#
74# Revision 1.34  2004/02/02 22:44:16  jalet
75# Preliminary work on Relationnal Database Independance via DB-API 2.0
76#
77#
78#
79
80from pykota.storage import PyKotaStorageError,BaseStorage,StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageJob,StorageLastJob,StorageUserPQuota,StorageGroupPQuota
81
82class SQLStorage :
83    def prepareRawResult(self, result) :
84        """Prepares a raw result by including the headers."""
85        if result.ntuples() > 0 :
86            entries = [result.listfields()]
87            entries.extend(result.getresult())
88            return entries
89       
90    def extractPrinters(self) :
91        """Extracts all printer records."""
92        result = self.doRawSearch("SELECT * FROM printers ORDER BY id ASC")
93        return self.prepareRawResult(result)
94       
95    def extractUsers(self) :
96        """Extracts all user records."""
97        result = self.doRawSearch("SELECT * FROM users ORDER BY id ASC")
98        return self.prepareRawResult(result)
99       
100    def extractGroups(self) :
101        """Extracts all group records."""
102        result = self.doRawSearch("SELECT * FROM groups ORDER BY id ASC")
103        return self.prepareRawResult(result)
104       
105    def extractPayments(self) :
106        """Extracts all payment records."""
107        result = self.doRawSearch("SELECT username,payments.* FROM users,payments WHERE users.id=payments.userid ORDER BY payments.id ASC")
108        return self.prepareRawResult(result)
109       
110    def extractUpquotas(self) :
111        """Extracts all userpquota records."""
112        result = self.doRawSearch("SELECT users.username,printers.printername,userpquota.* FROM users,printers,userpquota WHERE users.id=userpquota.userid AND printers.id=userpquota.printerid ORDER BY userpquota.id ASC")
113        return self.prepareRawResult(result)
114       
115    def extractGpquotas(self) :
116        """Extracts all grouppquota records."""
117        result = self.doRawSearch("SELECT groups.groupname,printers.printername,grouppquota.* FROM groups,printers,grouppquota WHERE groups.id=grouppquota.groupid AND printers.id=grouppquota.printerid ORDER BY grouppquota.id ASC")
118        return self.prepareRawResult(result)
119       
120    def extractUmembers(self) :
121        """Extracts all user groups members."""
122        result = self.doRawSearch("SELECT groups.groupname, users.username, groupsmembers.* FROM groups,users,groupsmembers WHERE users.id=groupsmembers.userid AND groups.id=groupsmembers.groupid ORDER BY groupsmembers.groupid, groupsmembers.userid ASC")
123        return self.prepareRawResult(result)
124       
125    def extractPmembers(self) :
126        """Extracts all printer groups members."""
127        result = self.doRawSearch("SELECT p1.printername as pgroupname, p2.printername as printername, printergroupsmembers.* FROM printers p1, printers p2, printergroupsmembers WHERE p1.id=printergroupsmembers.groupid AND p2.id=printergroupsmembers.printerid ORDER BY printergroupsmembers.groupid, printergroupsmembers.printerid ASC")
128        return self.prepareRawResult(result)
129       
130    def extractHistory(self) :
131        """Extracts all jobhistory records."""
132        result = self.doRawSearch("SELECT users.username,printers.printername,jobhistory.* FROM users,printers,jobhistory WHERE users.id=jobhistory.userid AND printers.id=jobhistory.printerid ORDER BY jobhistory.id ASC")
133        return self.prepareRawResult(result)
134       
135    def getAllUsersNames(self) :   
136        """Extracts all user names."""
137        usernames = []
138        result = self.doSearch("SELECT username FROM users")
139        if result :
140            usernames = [record["username"] for record in result]
141        return usernames
142       
143    def getAllGroupsNames(self) :   
144        """Extracts all group names."""
145        groupnames = []
146        result = self.doSearch("SELECT groupname FROM groups")
147        if result :
148            groupnames = [record["groupname"] for record in result]
149        return groupnames
150       
151    def getUserFromBackend(self, username) :   
152        """Extracts user information given its name."""
153        user = StorageUser(self, username)
154        result = self.doSearch("SELECT * FROM users WHERE username=%s LIMIT 1" % self.doQuote(username))
155        if result :
156            fields = result[0]
157            user.ident = fields.get("id")
158            user.Name = fields.get("username", username)
159            user.LimitBy = fields.get("limitby")
160            user.AccountBalance = fields.get("balance")
161            user.LifeTimePaid = fields.get("lifetimepaid")
162            user.Email = fields.get("email")
163            user.Exists = 1
164        return user
165       
166    def getGroupFromBackend(self, groupname) :   
167        """Extracts group information given its name."""
168        group = StorageGroup(self, groupname)
169        result = self.doSearch("SELECT * FROM groups WHERE groupname=%s LIMIT 1" % self.doQuote(groupname))
170        if result :
171            fields = result[0]
172            group.ident = fields.get("id")
173            group.Name = fields.get("groupname", groupname)
174            group.LimitBy = fields.get("limitby")
175            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))
176            if result :
177                fields = result[0]
178                group.AccountBalance = fields.get("balance")
179                group.LifeTimePaid = fields.get("lifetimepaid")
180            group.Exists = 1
181        return group
182       
183    def getPrinterFromBackend(self, printername) :       
184        """Extracts printer information given its name."""
185        printer = StoragePrinter(self, printername)
186        result = self.doSearch("SELECT * FROM printers WHERE printername=%s LIMIT 1" % self.doQuote(printername))
187        if result :
188            fields = result[0]
189            printer.ident = fields.get("id")
190            printer.Name = fields.get("printername", printername)
191            printer.PricePerJob = fields.get("priceperjob") or 0.0
192            printer.PricePerPage = fields.get("priceperpage") or 0.0
193            printer.Description = (fields.get("description") or "").decode("UTF-8").encode(self.tool.getCharset()) 
194            printer.Exists = 1
195        return printer   
196       
197    def getUserPQuotaFromBackend(self, user, printer) :       
198        """Extracts a user print quota."""
199        userpquota = StorageUserPQuota(self, user, printer)
200        if printer.Exists and user.Exists :
201            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)))
202            if result :
203                fields = result[0]
204                userpquota.ident = fields.get("id")
205                userpquota.PageCounter = fields.get("pagecounter")
206                userpquota.LifePageCounter = fields.get("lifepagecounter")
207                userpquota.SoftLimit = fields.get("softlimit")
208                userpquota.HardLimit = fields.get("hardlimit")
209                userpquota.DateLimit = fields.get("datelimit")
210                userpquota.Exists = 1
211        return userpquota
212       
213    def getGroupPQuotaFromBackend(self, group, printer) :       
214        """Extracts a group print quota."""
215        grouppquota = StorageGroupPQuota(self, group, printer)
216        if group.Exists :
217            result = self.doSearch("SELECT id, softlimit, hardlimit, datelimit FROM grouppquota WHERE groupid=%s AND printerid=%s" % (self.doQuote(group.ident), self.doQuote(printer.ident)))
218            if result :
219                fields = result[0]
220                grouppquota.ident = fields.get("id")
221                grouppquota.SoftLimit = fields.get("softlimit")
222                grouppquota.HardLimit = fields.get("hardlimit")
223                grouppquota.DateLimit = fields.get("datelimit")
224                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)))
225                if result :
226                    fields = result[0]
227                    grouppquota.PageCounter = fields.get("pagecounter")
228                    grouppquota.LifePageCounter = fields.get("lifepagecounter")
229                grouppquota.Exists = 1
230        return grouppquota
231       
232    def getPrinterLastJobFromBackend(self, printer) :       
233        """Extracts a printer's last job information."""
234        lastjob = StorageLastJob(self, printer)
235        result = self.doSearch("SELECT jobhistory.id, jobid, userid, username, pagecounter, jobsize, jobprice, filename, title, copies, options, hostname, jobdate FROM jobhistory, users WHERE printerid=%s AND userid=users.id ORDER BY jobdate DESC LIMIT 1" % self.doQuote(printer.ident))
236        if result :
237            fields = result[0]
238            lastjob.ident = fields.get("id")
239            lastjob.JobId = fields.get("jobid")
240            lastjob.UserName = fields.get("username")
241            lastjob.PrinterPageCounter = fields.get("pagecounter")
242            lastjob.JobSize = fields.get("jobsize")
243            lastjob.JobPrice = fields.get("jobprice")
244            lastjob.JobAction = fields.get("action")
245            lastjob.JobFileName = (fields.get("filename") or "").decode("UTF-8").encode(self.tool.getCharset()) 
246            lastjob.JobTitle = (fields.get("title") or "").decode("UTF-8").encode(self.tool.getCharset()) 
247            lastjob.JobCopies = fields.get("copies")
248            lastjob.JobOptions = (fields.get("options") or "").decode("UTF-8").encode(self.tool.getCharset()) 
249            lastjob.JobDate = fields.get("jobdate")
250            lastjob.JobHostName = fields.get("hostname")
251            lastjob.JobSizeBytes = fields.get("jobsizebytes")
252            lastjob.Exists = 1
253        return lastjob
254           
255    def getGroupMembersFromBackend(self, group) :       
256        """Returns the group's members list."""
257        groupmembers = []
258        result = self.doSearch("SELECT * FROM groupsmembers JOIN users ON groupsmembers.userid=users.id WHERE groupid=%s" % self.doQuote(group.ident))
259        if result :
260            for record in result :
261                user = StorageUser(self, record.get("username"))
262                user.ident = record.get("userid")
263                user.LimitBy = record.get("limitby")
264                user.AccountBalance = record.get("balance")
265                user.LifeTimePaid = record.get("lifetimepaid")
266                user.Email = record.get("email")
267                user.Exists = 1
268                groupmembers.append(user)
269                self.cacheEntry("USERS", user.Name, user)
270        return groupmembers       
271       
272    def getUserGroupsFromBackend(self, user) :       
273        """Returns the user's groups list."""
274        groups = []
275        result = self.doSearch("SELECT groupname FROM groupsmembers JOIN groups ON groupsmembers.groupid=groups.id WHERE userid=%s" % self.doQuote(user.ident))
276        if result :
277            for record in result :
278                groups.append(self.getGroup(record.get("groupname")))
279        return groups       
280       
281    def getParentPrintersFromBackend(self, printer) :   
282        """Get all the printer groups this printer is a member of."""
283        pgroups = []
284        result = self.doSearch("SELECT groupid,printername FROM printergroupsmembers JOIN printers ON groupid=id WHERE printerid=%s" % self.doQuote(printer.ident))
285        if result :
286            for record in result :
287                if record["groupid"] != printer.ident : # in case of integrity violation
288                    parentprinter = self.getPrinter(record.get("printername"))
289                    if parentprinter.Exists :
290                        pgroups.append(parentprinter)
291        return pgroups
292       
293    def getMatchingPrinters(self, printerpattern) :
294        """Returns the list of all printers for which name matches a certain pattern."""
295        printers = []
296        # We 'could' do a SELECT printername FROM printers WHERE printername LIKE ...
297        # but we don't because other storages semantics may be different, so every
298        # storage should use fnmatch to match patterns and be storage agnostic
299        result = self.doSearch("SELECT * FROM printers")
300        if result :
301            for record in result :
302                if self.tool.matchString(record["printername"], printerpattern.split(",")) :
303                    printer = StoragePrinter(self, record["printername"])
304                    printer.ident = record.get("id")
305                    printer.PricePerJob = record.get("priceperjob") or 0.0
306                    printer.PricePerPage = record.get("priceperpage") or 0.0
307                    printer.Description = (record.get("description") or "").decode("UTF-8").encode(self.tool.getCharset()) 
308                    printer.Exists = 1
309                    printers.append(printer)
310                    self.cacheEntry("PRINTERS", printer.Name, printer)
311        return printers       
312       
313    def getPrinterUsersAndQuotas(self, printer, names=["*"]) :       
314        """Returns the list of users who uses a given printer, along with their quotas."""
315        usersandquotas = []
316        result = self.doSearch("SELECT users.id as uid,username,balance,lifetimepaid,limitby,email,userpquota.id,lifepagecounter,pagecounter,softlimit,hardlimit,datelimit FROM users JOIN userpquota ON users.id=userpquota.userid AND printerid=%s ORDER BY username ASC" % self.doQuote(printer.ident))
317        if result :
318            for record in result :
319                if self.tool.matchString(record.get("username"), names) :
320                    user = StorageUser(self, record.get("username"))
321                    user.ident = record.get("uid")
322                    user.LimitBy = record.get("limitby")
323                    user.AccountBalance = record.get("balance")
324                    user.LifeTimePaid = record.get("lifetimepaid")
325                    user.Email = record.get("email") 
326                    user.Exists = 1
327                    userpquota = StorageUserPQuota(self, user, printer)
328                    userpquota.ident = record.get("id")
329                    userpquota.PageCounter = record.get("pagecounter")
330                    userpquota.LifePageCounter = record.get("lifepagecounter")
331                    userpquota.SoftLimit = record.get("softlimit")
332                    userpquota.HardLimit = record.get("hardlimit")
333                    userpquota.DateLimit = record.get("datelimit")
334                    userpquota.Exists = 1
335                    usersandquotas.append((user, userpquota))
336                    self.cacheEntry("USERS", user.Name, user)
337                    self.cacheEntry("USERPQUOTAS", "%s@%s" % (user.Name, printer.Name), userpquota)
338        return usersandquotas
339               
340    def getPrinterGroupsAndQuotas(self, printer, names=["*"]) :       
341        """Returns the list of groups which uses a given printer, along with their quotas."""
342        groupsandquotas = []
343        result = self.doSearch("SELECT groupname FROM groups JOIN grouppquota ON groups.id=grouppquota.groupid AND printerid=%s ORDER BY groupname ASC" % self.doQuote(printer.ident))
344        if result :
345            for record in result :
346                if self.tool.matchString(record.get("groupname"), names) :
347                    group = self.getGroup(record.get("groupname"))
348                    grouppquota = self.getGroupPQuota(group, printer)
349                    groupsandquotas.append((group, grouppquota))
350        return groupsandquotas
351       
352    def addPrinter(self, printername) :       
353        """Adds a printer to the quota storage, returns it."""
354        self.doModify("INSERT INTO printers (printername) VALUES (%s)" % self.doQuote(printername))
355        return self.getPrinter(printername)
356       
357    def addUser(self, user) :       
358        """Adds a user to the quota storage, returns its id."""
359        self.doModify("INSERT INTO users (username, limitby, balance, lifetimepaid, email) VALUES (%s, %s, %s, %s, %s)" % (self.doQuote(user.Name), self.doQuote(user.LimitBy or 'quota'), self.doQuote(user.AccountBalance or 0.0), self.doQuote(user.LifeTimePaid or 0.0), self.doQuote(user.Email)))
360        return self.getUser(user.Name)
361       
362    def addGroup(self, group) :       
363        """Adds a group to the quota storage, returns its id."""
364        self.doModify("INSERT INTO groups (groupname, limitby) VALUES (%s, %s)" % (self.doQuote(group.Name), self.doQuote(group.LimitBy or "quota")))
365        return self.getGroup(group.Name)
366
367    def addUserToGroup(self, user, group) :   
368        """Adds an user to a group."""
369        result = self.doSearch("SELECT COUNT(*) AS mexists FROM groupsmembers WHERE groupid=%s AND userid=%s" % (self.doQuote(group.ident), self.doQuote(user.ident)))
370        try :
371            mexists = int(result[0].get("mexists"))
372        except (IndexError, TypeError) :   
373            mexists = 0
374        if not mexists :   
375            self.doModify("INSERT INTO groupsmembers (groupid, userid) VALUES (%s, %s)" % (self.doQuote(group.ident), self.doQuote(user.ident)))
376           
377    def addUserPQuota(self, user, printer) :
378        """Initializes a user print quota on a printer."""
379        self.doModify("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident)))
380        return self.getUserPQuota(user, printer)
381       
382    def addGroupPQuota(self, group, printer) :
383        """Initializes a group print quota on a printer."""
384        self.doModify("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(group.ident), self.doQuote(printer.ident)))
385        return self.getGroupPQuota(group, printer)
386       
387    def writePrinterPrices(self, printer) :   
388        """Write the printer's prices back into the storage."""
389        self.doModify("UPDATE printers SET priceperpage=%s, priceperjob=%s WHERE id=%s" % (self.doQuote(printer.PricePerPage), self.doQuote(printer.PricePerJob), self.doQuote(printer.ident)))
390       
391    def writePrinterDescription(self, printer) :   
392        """Write the printer's description back into the storage."""
393        description = printer.Description
394        if description is not None :
395            description = printer.Description.decode(self.tool.getCharset()).encode("UTF-8"), 
396        self.doModify("UPDATE printers SET description=%s WHERE id=%s" % (self.doQuote(description), self.doQuote(printer.ident)))
397       
398    def writeUserLimitBy(self, user, limitby) :   
399        """Sets the user's limiting factor."""
400        self.doModify("UPDATE users SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(user.ident)))
401       
402    def writeGroupLimitBy(self, group, limitby) :   
403        """Sets the group's limiting factor."""
404        self.doModify("UPDATE groups SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(group.ident)))
405       
406    def writeUserPQuotaDateLimit(self, userpquota, datelimit) :   
407        """Sets the date limit permanently for a user print quota."""
408        self.doModify("UPDATE userpquota SET datelimit=%s WHERE id=%s" % (self.doQuote(datelimit), self.doQuote(userpquota.ident)))
409           
410    def writeGroupPQuotaDateLimit(self, grouppquota, datelimit) :   
411        """Sets the date limit permanently for a group print quota."""
412        self.doModify("UPDATE grouppquota SET datelimit=%s WHERE id=%s" % (self.doQuote(datelimit), self.doQuote(grouppquota.ident)))
413       
414    def increaseUserPQuotaPagesCounters(self, userpquota, nbpages) :   
415        """Increase page counters for a user print quota."""
416        self.doModify("UPDATE userpquota SET pagecounter=pagecounter+%s,lifepagecounter=lifepagecounter+%s WHERE id=%s" % (self.doQuote(nbpages), self.doQuote(nbpages), self.doQuote(userpquota.ident)))
417       
418    def writeUserPQuotaPagesCounters(self, userpquota, newpagecounter, newlifepagecounter) :   
419        """Sets the new page counters permanently for a user print quota."""
420        self.doModify("UPDATE userpquota SET pagecounter=%s,lifepagecounter=%s WHERE id=%s" % (self.doQuote(newpagecounter), self.doQuote(newlifepagecounter), self.doQuote(userpquota.ident)))
421       
422    def decreaseUserAccountBalance(self, user, amount) :   
423        """Decreases user's account balance from an amount."""
424        self.doModify("UPDATE users SET balance=balance-%s WHERE id=%s" % (self.doQuote(amount), self.doQuote(user.ident)))
425       
426    def writeUserAccountBalance(self, user, newbalance, newlifetimepaid=None) :   
427        """Sets the new account balance and eventually new lifetime paid."""
428        if newlifetimepaid is not None :
429            self.doModify("UPDATE users SET balance=%s, lifetimepaid=%s WHERE id=%s" % (self.doQuote(newbalance), self.doQuote(newlifetimepaid), self.doQuote(user.ident)))
430        else :   
431            self.doModify("UPDATE users SET balance=%s WHERE id=%s" % (self.doQuote(newbalance), self.doQuote(user.ident)))
432           
433    def writeNewPayment(self, user, amount) :       
434        """Adds a new payment to the payments history."""
435        self.doModify("INSERT INTO payments (userid, amount) VALUES (%s, %s)" % (self.doQuote(user.ident), self.doQuote(amount)))
436       
437    def writeLastJobSize(self, lastjob, jobsize, jobprice) :       
438        """Sets the last job's size permanently."""
439        self.doModify("UPDATE jobhistory SET jobsize=%s, jobprice=%s WHERE id=%s" % (self.doQuote(jobsize), self.doQuote(jobprice), self.doQuote(lastjob.ident)))
440       
441    def writeJobNew(self, printer, user, jobid, pagecounter, action, jobsize=None, jobprice=None, filename=None, title=None, copies=None, options=None, clienthost=None, jobsizebytes=None) :
442        """Adds a job in a printer's history."""
443        if filename is not None :
444            filename = filename.decode(self.tool.getCharset()).encode("UTF-8")
445        if title is not None :
446            title = title.decode(self.tool.getCharset()).encode("UTF-8")
447        if options is not None :
448            options = options.decode(self.tool.getCharset()).encode("UTF-8")
449        if (not self.disablehistory) or (not printer.LastJob.Exists) :
450            if jobsize is not None :
451                self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action, jobsize, jobprice, filename, title, copies, options, hostname, jobsizebytes) VALUES (%s, %s, %s, %s, %s, %s, %s, %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), self.doQuote(jobprice), self.doQuote(filename), self.doQuote(title), self.doQuote(copies), self.doQuote(options), self.doQuote(clienthost), self.doQuote(jobsizebytes)))
452            else :   
453                self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action, filename, title, copies, options, hostname, jobsizebytes) VALUES (%s, %s, %s, %s, %s, %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(filename), self.doQuote(title), self.doQuote(copies), self.doQuote(options), self.doQuote(clienthost), self.doQuote(jobsizebytes)))
454        else :       
455            # here we explicitly want to reset jobsize to NULL if needed
456            self.doModify("UPDATE jobhistory SET userid=%s, jobid=%s, pagecounter=%s, action=%s, jobsize=%s, jobprice=%s, filename=%s, title=%s, copies=%s, options=%s, hostname=%s, jobsizebytes=%s, jobdate=now() WHERE id=%s" % (self.doQuote(user.ident), self.doQuote(jobid), self.doQuote(pagecounter), self.doQuote(action), self.doQuote(jobsize), self.doQuote(jobprice), self.doQuote(filename), self.doQuote(title), self.doQuote(copies), self.doQuote(options), self.doQuote(clienthost), self.doQuote(jobsizebytes), self.doQuote(printer.LastJob.ident)))
457           
458    def writeUserPQuotaLimits(self, userpquota, softlimit, hardlimit) :
459        """Sets soft and hard limits for a user quota."""
460        self.doModify("UPDATE userpquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE id=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(userpquota.ident)))
461       
462    def writeGroupPQuotaLimits(self, grouppquota, softlimit, hardlimit) :
463        """Sets soft and hard limits for a group quota on a specific printer."""
464        self.doModify("UPDATE grouppquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE id=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(grouppquota.ident)))
465
466    def writePrinterToGroup(self, pgroup, printer) :
467        """Puts a printer into a printer group."""
468        children = []
469        result = self.doSearch("SELECT printerid FROM printergroupsmembers WHERE groupid=%s" % self.doQuote(pgroup.ident))
470        if result :
471            for record in result :
472                children.append(record.get("printerid")) # TODO : put this into the database integrity rules
473        if printer.ident not in children :       
474            self.doModify("INSERT INTO printergroupsmembers (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(pgroup.ident), self.doQuote(printer.ident)))
475       
476    def removePrinterFromGroup(self, pgroup, printer) :
477        """Removes a printer from a printer group."""
478        self.doModify("DELETE FROM printergroupsmembers WHERE groupid=%s AND printerid=%s" % (self.doQuote(pgroup.ident), self.doQuote(printer.ident)))
479       
480    def retrieveHistory(self, user=None, printer=None, datelimit=None, hostname=None, limit=100) :   
481        """Retrieves all print jobs for user on printer (or all) before date, limited to first 100 results."""
482        query = "SELECT jobhistory.*,username,printername FROM jobhistory,users,printers WHERE users.id=userid AND printers.id=printerid"
483        where = []
484        if (user is not None) and user.Exists :
485            where.append("userid=%s" % self.doQuote(user.ident))
486        if (printer is not None) and printer.Exists :
487            where.append("printerid=%s" % self.doQuote(printer.ident))
488        if hostname is not None :   
489            where.append("hostname=%s" % self.doQuote(hostname))
490        if datelimit is not None :   
491            where.append("jobdate<=%s" % self.doQuote(datelimit))
492        if where :   
493            query += " AND %s" % " AND ".join(where)
494        query += " ORDER BY id DESC"
495        if limit :
496            query += " LIMIT %s" % self.doQuote(int(limit))
497        jobs = []   
498        result = self.doSearch(query)   
499        if result :
500            for fields in result :
501                job = StorageJob(self)
502                job.ident = fields.get("id")
503                job.JobId = fields.get("jobid")
504                job.PrinterPageCounter = fields.get("pagecounter")
505                job.JobSize = fields.get("jobsize")
506                job.JobPrice = fields.get("jobprice")
507                job.JobAction = fields.get("action")
508                job.JobFileName = (fields.get("filename") or "").decode("UTF-8").encode(self.tool.getCharset()) 
509                job.JobTitle = (fields.get("title") or "").decode("UTF-8").encode(self.tool.getCharset()) 
510                job.JobCopies = fields.get("copies")
511                job.JobOptions = (fields.get("options") or "").decode("UTF-8").encode(self.tool.getCharset()) 
512                job.JobDate = fields.get("jobdate")
513                job.JobHostName = fields.get("hostname")
514                job.JobSizeBytes = fields.get("jobsizebytes")
515                job.UserName = fields.get("username")
516                job.PrinterName = fields.get("printername")
517                job.Exists = 1
518                jobs.append(job)
519        return jobs
520       
521    def deleteUser(self, user) :   
522        """Completely deletes an user from the Quota Storage."""
523        # TODO : What should we do if we delete the last person who used a given printer ?
524        # TODO : we can't reassign the last job to the previous one, because next user would be
525        # TODO : incorrectly charged (overcharged).
526        for q in [ 
527                    "DELETE FROM payments WHERE userid=%s" % self.doQuote(user.ident),
528                    "DELETE FROM groupsmembers WHERE userid=%s" % self.doQuote(user.ident),
529                    "DELETE FROM jobhistory WHERE userid=%s" % self.doQuote(user.ident),
530                    "DELETE FROM userpquota WHERE userid=%s" % self.doQuote(user.ident),
531                    "DELETE FROM users WHERE id=%s" % self.doQuote(user.ident),
532                  ] :
533            self.doModify(q)
534       
535    def deleteGroup(self, group) :   
536        """Completely deletes a group from the Quota Storage."""
537        for q in [
538                   "DELETE FROM groupsmembers WHERE groupid=%s" % self.doQuote(group.ident),
539                   "DELETE FROM grouppquota WHERE groupid=%s" % self.doQuote(group.ident),
540                   "DELETE FROM groups WHERE id=%s" % self.doQuote(group.ident),
541                 ] : 
542            self.doModify(q)
543           
544    def deletePrinter(self, printer) :   
545        """Completely deletes a printer from the Quota Storage."""
546        for q in [ 
547                    "DELETE FROM printergroupsmembers WHERE groupid=%s OR printerid=%s" % (self.doQuote(printer.ident), self.doQuote(printer.ident)),
548                    "DELETE FROM jobhistory WHERE printerid=%s" % self.doQuote(printer.ident),
549                    "DELETE FROM grouppquota WHERE printerid=%s" % self.doQuote(printer.ident),
550                    "DELETE FROM userpquota WHERE printerid=%s" % self.doQuote(printer.ident),
551                    "DELETE FROM printers WHERE id=%s" % self.doQuote(printer.ident),
552                  ] :
553            self.doModify(q)
554       
Note: See TracBrowser for help on using the browser.