224 | | |
225 | | def getAllUsersNames(self) : |
226 | | """Extracts all user names.""" |
227 | | usernames = [] |
228 | | result = self.doSearch("SELECT username FROM users") |
229 | | if result : |
230 | | usernames = [record["username"] for record in result] |
231 | | return usernames |
232 | | |
233 | | def getAllGroupsNames(self) : |
234 | | """Extracts all group names.""" |
235 | | groupnames = [] |
236 | | result = self.doSearch("SELECT groupname FROM groups") |
237 | | if result : |
238 | | groupnames = [record["groupname"] for record in result] |
239 | | return groupnames |
240 | | |
241 | | def getUserFromBackend(self, username) : |
242 | | """Extracts user information given its name.""" |
243 | | user = StorageUser(self, username) |
244 | | result = self.doSearch("SELECT * FROM users WHERE username=%s LIMIT 1" % self.doQuote(username)) |
245 | | if result : |
246 | | fields = result[0] |
247 | | user.ident = fields.get("id") |
248 | | user.LimitBy = fields.get("limitby") |
249 | | user.AccountBalance = fields.get("balance") |
250 | | user.LifeTimePaid = fields.get("lifetimepaid") |
251 | | user.Email = fields.get("email") |
252 | | user.Exists = 1 |
253 | | return user |
254 | | |
255 | | def getGroupFromBackend(self, groupname) : |
256 | | """Extracts group information given its name.""" |
257 | | group = StorageGroup(self, groupname) |
258 | | result = self.doSearch("SELECT * FROM groups WHERE groupname=%s LIMIT 1" % self.doQuote(groupname)) |
259 | | if result : |
260 | | fields = result[0] |
261 | | group.ident = fields.get("id") |
262 | | group.LimitBy = fields.get("limitby") |
263 | | 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)) |
264 | | if result : |
265 | | fields = result[0] |
266 | | group.AccountBalance = fields.get("balance") |
267 | | group.LifeTimePaid = fields.get("lifetimepaid") |
268 | | group.Exists = 1 |
269 | | return group |
270 | | |
271 | | def getPrinterFromBackend(self, printername) : |
272 | | """Extracts printer information given its name.""" |
273 | | printer = StoragePrinter(self, printername) |
274 | | result = self.doSearch("SELECT * FROM printers WHERE printername=%s LIMIT 1" % self.doQuote(printername)) |
275 | | if result : |
276 | | fields = result[0] |
277 | | printer.ident = fields.get("id") |
278 | | printer.PricePerJob = fields.get("priceperjob") |
279 | | printer.PricePerPage = fields.get("priceperpage") |
280 | | printer.LastJob = self.getPrinterLastJob(printer) |
281 | | printer.Exists = 1 |
282 | | return printer |
283 | | |
284 | | def getUserPQuotaFromBackend(self, user, printer) : |
285 | | """Extracts a user print quota.""" |
286 | | userpquota = StorageUserPQuota(self, user, printer) |
287 | | if printer.Exists and user.Exists : |
288 | | 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))) |
289 | | if result : |
290 | | fields = result[0] |
291 | | userpquota.ident = fields.get("id") |
292 | | userpquota.PageCounter = fields.get("pagecounter") |
293 | | userpquota.LifePageCounter = fields.get("lifepagecounter") |
294 | | userpquota.SoftLimit = fields.get("softlimit") |
295 | | userpquota.HardLimit = fields.get("hardlimit") |
296 | | userpquota.DateLimit = fields.get("datelimit") |
297 | | userpquota.Exists = 1 |
298 | | return userpquota |
299 | | |
300 | | def getGroupPQuotaFromBackend(self, group, printer) : |
301 | | """Extracts a group print quota.""" |
302 | | grouppquota = StorageGroupPQuota(self, group, printer) |
303 | | if group.Exists : |
304 | | result = self.doSearch("SELECT id, softlimit, hardlimit, datelimit FROM grouppquota WHERE groupid=%s AND printerid=%s" % (self.doQuote(group.ident), self.doQuote(printer.ident))) |
305 | | if result : |
306 | | fields = result[0] |
307 | | grouppquota.ident = fields.get("id") |
308 | | grouppquota.SoftLimit = fields.get("softlimit") |
309 | | grouppquota.HardLimit = fields.get("hardlimit") |
310 | | grouppquota.DateLimit = fields.get("datelimit") |
311 | | 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))) |
312 | | if result : |
313 | | fields = result[0] |
314 | | grouppquota.PageCounter = fields.get("pagecounter") |
315 | | grouppquota.LifePageCounter = fields.get("lifepagecounter") |
316 | | grouppquota.Exists = 1 |
317 | | return grouppquota |
318 | | |
319 | | def getPrinterLastJobFromBackend(self, printer) : |
320 | | """Extracts a printer's last job information.""" |
321 | | lastjob = StorageLastJob(self, printer) |
322 | | result = self.doSearch("SELECT jobhistory.id, jobid, userid, username, pagecounter, jobsize, jobprice, filename, title, copies, options, jobdate FROM jobhistory, users WHERE printerid=%s AND userid=users.id ORDER BY jobdate DESC LIMIT 1" % self.doQuote(printer.ident)) |
323 | | if result : |
324 | | fields = result[0] |
325 | | lastjob.ident = fields.get("id") |
326 | | lastjob.JobId = fields.get("jobid") |
327 | | lastjob.User = self.getUser(fields.get("username")) |
328 | | lastjob.PrinterPageCounter = fields.get("pagecounter") |
329 | | lastjob.JobSize = fields.get("jobsize") |
330 | | lastjob.JobPrice = fields.get("jobprice") |
331 | | lastjob.JobAction = fields.get("action") |
332 | | lastjob.JobFileName = fields.get("filename") |
333 | | lastjob.JobTitle = fields.get("title") |
334 | | lastjob.JobCopies = fields.get("copies") |
335 | | lastjob.JobOptions = fields.get("options") |
336 | | lastjob.JobDate = fields.get("jobdate") |
337 | | lastjob.Exists = 1 |
338 | | return lastjob |
339 | | |
340 | | def getGroupMembersFromBackend(self, group) : |
341 | | """Returns the group's members list.""" |
342 | | groupmembers = [] |
343 | | result = self.doSearch("SELECT * FROM groupsmembers JOIN users ON groupsmembers.userid=users.id WHERE groupid=%s" % self.doQuote(group.ident)) |
344 | | if result : |
345 | | for record in result : |
346 | | user = StorageUser(self, record.get("username")) |
347 | | user.ident = record.get("userid") |
348 | | user.LimitBy = record.get("limitby") |
349 | | user.AccountBalance = record.get("balance") |
350 | | user.LifeTimePaid = record.get("lifetimepaid") |
351 | | user.Email = record.get("email") |
352 | | user.Exists = 1 |
353 | | groupmembers.append(user) |
354 | | self.cacheEntry("USERS", user.Name, user) |
355 | | return groupmembers |
356 | | |
357 | | def getUserGroupsFromBackend(self, user) : |
358 | | """Returns the user's groups list.""" |
359 | | groups = [] |
360 | | result = self.doSearch("SELECT groupname FROM groupsmembers JOIN groups ON groupsmembers.groupid=groups.id WHERE userid=%s" % self.doQuote(user.ident)) |
361 | | if result : |
362 | | for record in result : |
363 | | groups.append(self.getGroup(record.get("groupname"))) |
364 | | return groups |
365 | | |
366 | | def getParentPrintersFromBackend(self, printer) : |
367 | | """Get all the printer groups this printer is a member of.""" |
368 | | pgroups = [] |
369 | | result = self.doSearch("SELECT groupid,printername FROM printergroupsmembers JOIN printers ON groupid=id WHERE printerid=%s" % self.doQuote(printer.ident)) |
370 | | if result : |
371 | | for record in result : |
372 | | if record["groupid"] != printer.ident : # in case of integrity violation |
373 | | parentprinter = self.getPrinter(record.get("printername")) |
374 | | if parentprinter.Exists : |
375 | | pgroups.append(parentprinter) |
376 | | return pgroups |
377 | | |
378 | | def getMatchingPrinters(self, printerpattern) : |
379 | | """Returns the list of all printers for which name matches a certain pattern.""" |
380 | | printers = [] |
381 | | # We 'could' do a SELECT printername FROM printers WHERE printername LIKE ... |
382 | | # but we don't because other storages semantics may be different, so every |
383 | | # storage should use fnmatch to match patterns and be storage agnostic |
384 | | result = self.doSearch("SELECT * FROM printers") |
385 | | if result : |
386 | | for record in result : |
387 | | if self.tool.matchString(record["printername"], printerpattern.split(",")) : |
388 | | printer = StoragePrinter(self, record["printername"]) |
389 | | printer.ident = record.get("id") |
390 | | printer.PricePerJob = record.get("priceperjob") |
391 | | printer.PricePerPage = record.get("priceperpage") |
392 | | printer.LastJob = self.getPrinterLastJob(printer) |
393 | | printer.Exists = 1 |
394 | | printers.append(printer) |
395 | | self.cacheEntry("PRINTERS", printer.Name, printer) |
396 | | return printers |
397 | | |
398 | | def getPrinterUsersAndQuotas(self, printer, names=["*"]) : |
399 | | """Returns the list of users who uses a given printer, along with their quotas.""" |
400 | | usersandquotas = [] |
401 | | 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)) |
402 | | if result : |
403 | | for record in result : |
404 | | if self.tool.matchString(record.get("username"), names) : |
405 | | user = StorageUser(self, record.get("username")) |
406 | | user.ident = record.get("uid") |
407 | | user.LimitBy = record.get("limitby") |
408 | | user.AccountBalance = record.get("balance") |
409 | | user.LifeTimePaid = record.get("lifetimepaid") |
410 | | user.Email = record.get("email") |
411 | | user.Exists = 1 |
412 | | userpquota = StorageUserPQuota(self, user, printer) |
413 | | userpquota.ident = record.get("id") |
414 | | userpquota.PageCounter = record.get("pagecounter") |
415 | | userpquota.LifePageCounter = record.get("lifepagecounter") |
416 | | userpquota.SoftLimit = record.get("softlimit") |
417 | | userpquota.HardLimit = record.get("hardlimit") |
418 | | userpquota.DateLimit = record.get("datelimit") |
419 | | userpquota.Exists = 1 |
420 | | usersandquotas.append((user, userpquota)) |
421 | | self.cacheEntry("USERS", user.Name, user) |
422 | | self.cacheEntry("USERPQUOTAS", "%s@%s" % (user.Name, printer.Name), userpquota) |
423 | | return usersandquotas |
424 | | |
425 | | def getPrinterGroupsAndQuotas(self, printer, names=["*"]) : |
426 | | """Returns the list of groups which uses a given printer, along with their quotas.""" |
427 | | groupsandquotas = [] |
428 | | 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)) |
429 | | if result : |
430 | | for record in result : |
431 | | if self.tool.matchString(record.get("groupname"), names) : |
432 | | group = self.getGroup(record.get("groupname")) |
433 | | grouppquota = self.getGroupPQuota(group, printer) |
434 | | groupsandquotas.append((group, grouppquota)) |
435 | | return groupsandquotas |
436 | | |
437 | | def addPrinter(self, printername) : |
438 | | """Adds a printer to the quota storage, returns it.""" |
439 | | self.doModify("INSERT INTO printers (printername) VALUES (%s)" % self.doQuote(printername)) |
440 | | return self.getPrinter(printername) |
441 | | |
442 | | def addUser(self, user) : |
443 | | """Adds a user to the quota storage, returns its id.""" |
444 | | self.doModify("INSERT INTO users (username, limitby, balance, lifetimepaid, email) VALUES (%s, %s, %s, %s, %s)" % (self.doQuote(user.Name), self.doQuote(user.LimitBy), self.doQuote(user.AccountBalance), self.doQuote(user.LifeTimePaid), self.doQuote(user.Email))) |
445 | | return self.getUser(user.Name) |
446 | | |
447 | | def addGroup(self, group) : |
448 | | """Adds a group to the quota storage, returns its id.""" |
449 | | self.doModify("INSERT INTO groups (groupname, limitby) VALUES (%s, %s)" % (self.doQuote(group.Name), self.doQuote(group.LimitBy))) |
450 | | return self.getGroup(group.Name) |
451 | | |
452 | | def addUserToGroup(self, user, group) : |
453 | | """Adds an user to a group.""" |
454 | | result = self.doSearch("SELECT COUNT(*) AS mexists FROM groupsmembers WHERE groupid=%s AND userid=%s" % (self.doQuote(group.ident), self.doQuote(user.ident))) |
455 | | try : |
456 | | mexists = int(result[0].get("mexists")) |
457 | | except (IndexError, TypeError) : |
458 | | mexists = 0 |
459 | | if not mexists : |
460 | | self.doModify("INSERT INTO groupsmembers (groupid, userid) VALUES (%s, %s)" % (self.doQuote(group.ident), self.doQuote(user.ident))) |
461 | | |
462 | | def addUserPQuota(self, user, printer) : |
463 | | """Initializes a user print quota on a printer.""" |
464 | | self.doModify("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident))) |
465 | | return self.getUserPQuota(user, printer) |
466 | | |
467 | | def addGroupPQuota(self, group, printer) : |
468 | | """Initializes a group print quota on a printer.""" |
469 | | self.doModify("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(group.ident), self.doQuote(printer.ident))) |
470 | | return self.getGroupPQuota(group, printer) |
471 | | |
472 | | def writePrinterPrices(self, printer) : |
473 | | """Write the printer's prices back into the storage.""" |
474 | | self.doModify("UPDATE printers SET priceperpage=%s, priceperjob=%s WHERE id=%s" % (self.doQuote(printer.PricePerPage), self.doQuote(printer.PricePerJob), self.doQuote(printer.ident))) |
475 | | |
476 | | def writeUserLimitBy(self, user, limitby) : |
477 | | """Sets the user's limiting factor.""" |
478 | | self.doModify("UPDATE users SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(user.ident))) |
479 | | |
480 | | def writeGroupLimitBy(self, group, limitby) : |
481 | | """Sets the group's limiting factor.""" |
482 | | self.doModify("UPDATE groups SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(group.ident))) |
483 | | |
484 | | def writeUserPQuotaDateLimit(self, userpquota, datelimit) : |
485 | | """Sets the date limit permanently for a user print quota.""" |
486 | | self.doModify("UPDATE userpquota SET datelimit=%s WHERE id=%s" % (self.doQuote(datelimit), self.doQuote(userpquota.ident))) |
487 | | |
488 | | def writeGroupPQuotaDateLimit(self, grouppquota, datelimit) : |
489 | | """Sets the date limit permanently for a group print quota.""" |
490 | | self.doModify("UPDATE grouppquota SET datelimit=%s WHERE id=%s" % (self.doQuote(datelimit), self.doQuote(grouppquota.ident))) |
491 | | |
492 | | def increaseUserPQuotaPagesCounters(self, userpquota, nbpages) : |
493 | | """Increase page counters for a user print quota.""" |
494 | | self.doModify("UPDATE userpquota SET pagecounter=pagecounter+%s,lifepagecounter=lifepagecounter+%s WHERE id=%s" % (self.doQuote(nbpages), self.doQuote(nbpages), self.doQuote(userpquota.ident))) |
495 | | |
496 | | def writeUserPQuotaPagesCounters(self, userpquota, newpagecounter, newlifepagecounter) : |
497 | | """Sets the new page counters permanently for a user print quota.""" |
498 | | self.doModify("UPDATE userpquota SET pagecounter=%s,lifepagecounter=%s WHERE id=%s" % (self.doQuote(newpagecounter), self.doQuote(newlifepagecounter), self.doQuote(userpquota.ident))) |
499 | | |
500 | | def decreaseUserAccountBalance(self, user, amount) : |
501 | | """Decreases user's account balance from an amount.""" |
502 | | self.doModify("UPDATE users SET balance=balance-%s WHERE id=%s" % (self.doQuote(amount), self.doQuote(user.ident))) |
503 | | |
504 | | def writeUserAccountBalance(self, user, newbalance, newlifetimepaid=None) : |
505 | | """Sets the new account balance and eventually new lifetime paid.""" |
506 | | if newlifetimepaid is not None : |
507 | | self.doModify("UPDATE users SET balance=%s, lifetimepaid=%s WHERE id=%s" % (self.doQuote(newbalance), self.doQuote(newlifetimepaid), self.doQuote(user.ident))) |
508 | | else : |
509 | | self.doModify("UPDATE users SET balance=%s WHERE id=%s" % (self.doQuote(newbalance), self.doQuote(user.ident))) |
510 | | |
511 | | def writeLastJobSize(self, lastjob, jobsize, jobprice) : |
512 | | """Sets the last job's size permanently.""" |
513 | | self.doModify("UPDATE jobhistory SET jobsize=%s, jobprice=%s WHERE id=%s" % (self.doQuote(jobsize), self.doQuote(jobprice), self.doQuote(lastjob.ident))) |
514 | | |
515 | | def writeJobNew(self, printer, user, jobid, pagecounter, action, jobsize=None, jobprice=None, filename=None, title=None, copies=None, options=None) : |
516 | | """Adds a job in a printer's history.""" |
517 | | if (not self.disablehistory) or (not printer.LastJob.Exists) : |
518 | | if jobsize is not None : |
519 | | self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action, jobsize, jobprice, filename, title, copies, options) 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(jobsize), self.doQuote(jobprice), self.doQuote(filename), self.doQuote(title), self.doQuote(copies), self.doQuote(options))) |
520 | | else : |
521 | | self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action, filename, title, copies, options) VALUES (%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))) |
522 | | else : |
523 | | # here we explicitly want to reset jobsize to NULL if needed |
524 | | 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, 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(printer.LastJob.ident))) |
525 | | |
526 | | def writeUserPQuotaLimits(self, userpquota, softlimit, hardlimit) : |
527 | | """Sets soft and hard limits for a user quota.""" |
528 | | self.doModify("UPDATE userpquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE id=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(userpquota.ident))) |
529 | | |
530 | | def writeGroupPQuotaLimits(self, grouppquota, softlimit, hardlimit) : |
531 | | """Sets soft and hard limits for a group quota on a specific printer.""" |
532 | | self.doModify("UPDATE grouppquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE id=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(grouppquota.ident))) |
533 | | |
534 | | def writePrinterToGroup(self, pgroup, printer) : |
535 | | """Puts a printer into a printer group.""" |
536 | | children = [] |
537 | | result = self.doSearch("SELECT printerid FROM printergroupsmembers WHERE groupid=%s" % self.doQuote(pgroup.ident)) |
538 | | if result : |
539 | | for record in result : |
540 | | children.append(record.get("printerid")) # TODO : put this into the database integrity rules |
541 | | if printer.ident not in children : |
542 | | self.doModify("INSERT INTO printergroupsmembers (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(pgroup.ident), self.doQuote(printer.ident))) |
543 | | |
544 | | def retrieveHistory(self, user=None, printer=None, datelimit=None, limit=100) : |
545 | | """Retrieves all print jobs for user on printer (or all) before date, limited to first 100 results.""" |
546 | | query = "SELECT jobhistory.*,username,printername FROM jobhistory,users,printers WHERE users.id=userid AND printers.id=printerid" |
547 | | where = [] |
548 | | if (user is not None) and user.Exists : |
549 | | where.append("userid=%s" % self.doQuote(user.ident)) |
550 | | if (printer is not None) and printer.Exists : |
551 | | where.append("printerid=%s" % self.doQuote(printer.ident)) |
552 | | if datelimit is not None : |
553 | | where.append("jobdate<=%s" % self.doQuote(datelimit)) |
554 | | if where : |
555 | | query += " AND %s" % " AND ".join(where) |
556 | | query += " ORDER BY id DESC" |
557 | | if limit : |
558 | | query += " LIMIT %s" % self.doQuote(int(limit)) |
559 | | jobs = [] |
560 | | result = self.doSearch(query) |
561 | | if result : |
562 | | for fields in result : |
563 | | job = StorageJob(self) |
564 | | job.ident = fields.get("id") |
565 | | job.JobId = fields.get("jobid") |
566 | | job.PrinterPageCounter = fields.get("pagecounter") |
567 | | job.JobSize = fields.get("jobsize") |
568 | | job.JobPrice = fields.get("jobprice") |
569 | | job.JobAction = fields.get("action") |
570 | | job.JobFileName = fields.get("filename") |
571 | | job.JobTitle = fields.get("title") |
572 | | job.JobCopies = fields.get("copies") |
573 | | job.JobOptions = fields.get("options") |
574 | | job.JobDate = fields.get("jobdate") |
575 | | job.User = self.getUser(fields.get("username")) |
576 | | job.Printer = self.getPrinter(fields.get("printername")) |
577 | | job.Exists = 1 |
578 | | jobs.append(job) |
579 | | return jobs |
580 | | |
581 | | def deleteUser(self, user) : |
582 | | """Completely deletes an user from the Quota Storage.""" |
583 | | # TODO : What should we do if we delete the last person who used a given printer ? |
584 | | # TODO : we can't reassign the last job to the previous one, because next user would be |
585 | | # TODO : incorrectly charged (overcharged). |
586 | | for q in [ |
587 | | "DELETE FROM groupsmembers WHERE userid=%s" % self.doQuote(user.ident), |
588 | | "DELETE FROM jobhistory WHERE userid=%s" % self.doQuote(user.ident), |
589 | | "DELETE FROM userpquota WHERE userid=%s" % self.doQuote(user.ident), |
590 | | "DELETE FROM users WHERE id=%s" % self.doQuote(user.ident), |
591 | | ] : |
592 | | self.doModify(q) |
593 | | |
594 | | def deleteGroup(self, group) : |
595 | | """Completely deletes a group from the Quota Storage.""" |
596 | | for q in [ |
597 | | "DELETE FROM groupsmembers WHERE groupid=%s" % self.doQuote(group.ident), |
598 | | "DELETE FROM grouppquota WHERE groupid=%s" % self.doQuote(group.ident), |
599 | | "DELETE FROM groups WHERE id=%s" % self.doQuote(group.ident), |
600 | | ] : |
601 | | self.doModify(q) |
602 | | |