Changeset 927
- Timestamp:
- 04/16/03 14:35:49 (22 years ago)
- Location:
- pykota/trunk
- Files:
-
- 13 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/bin/edpykota
r924 r927 23 23 # 24 24 # $Log$ 25 # Revision 1.41 2003/04/16 12:35:49 jalet 26 # Groups quota work now ! 27 # 25 28 # Revision 1.40 2003/04/16 08:22:09 jalet 26 29 # More strict error detection. … … 340 343 if not names : 341 344 if options["add"] and not printeradded : 342 raise PyKotaToolError, _("You have to pass user names on the command line")345 raise PyKotaToolError, _("You have to pass user or group names on the command line") 343 346 else : 344 347 names = [ "*" ] # all users … … 366 369 if limitby and (limitby not in ('quota', 'balance')) : 367 370 raise PyKotaToolError, _("Invalid limitby value %s" % options["limitby"]) 371 372 if options["ingroups"] : 373 groupnames = [gname.strip() for gname in options["ingroups"].split(',')] 374 else : 375 groupnames = [] 368 376 369 377 for (printerid, printer) in printers : … … 393 401 if softlimit is not None : 394 402 self.logger.log_message(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer)) 395 if (not options[" reset"] and not options["noquota"] and not options["prototype"] and not options["limitby"] and not options["balance"] and not options["delete"] and not options["charge"]) and ((hardlimit is None) or (softlimit is None)) :403 if (not options["ingroups"] and not options["reset"] and not options["noquota"] and not options["prototype"] and not options["limitby"] and not options["balance"] and not options["delete"] and not options["charge"]) and ((hardlimit is None) or (softlimit is None)) : 396 404 raise PyKotaToolError, _("Both hard and soft limits must be set ! Aborting.") 397 405 if options["add"] : … … 458 466 else : 459 467 self.storage.setUserBalance(ident, balancevalue) 468 for groupname in groupnames : 469 groupid = self.storage.getGroupId(groupname) 470 if groupid is not None : 471 self.storage.addUserToGroup(ident, groupid) 460 472 self.warnUserPQuota(name, printer) 461 473 … … 506 518 elif options["groups"] and (options["balance"] or options["ingroups"]) : 507 519 raise PyKotaToolError, _("incompatible options, see help.") 508 elif options["groups"] :509 raise PyKotaToolError, _("option --groups is currently not implemented.")510 520 else : 511 521 sys.exit(editor.main(args, options)) -
pykota/trunk/bin/repykota
r915 r927 23 23 # 24 24 # $Log$ 25 # Revision 1.26 2003/04/16 12:35:49 jalet 26 # Groups quota work now ! 27 # 25 28 # Revision 1.25 2003/04/15 11:30:57 jalet 26 29 # More work done on money print charging. … … 177 180 print _("Group used soft hard grace total") 178 181 print "------------------------------------------------------------" 179 for namein self.storage.getPrinterGroups(printerid) :182 for (ident, name) in self.storage.getPrinterGroups(printerid) : 180 183 quota = self.storage.getGroupPQuota(ident, printerid) 181 184 total += self.printQuota(name, quota) … … 200 203 """Prints the quota information.""" 201 204 if quota is not None : 202 lifepagecounter = quota["lifepagecounter"] 203 pagecounter = quota["pagecounter"] 205 lifepagecounter = quota["lifepagecounter"] or 0 206 pagecounter = quota["pagecounter"] or 0 204 207 softlimit = quota["softlimit"] 205 208 hardlimit = quota["hardlimit"] … … 244 247 elif options["users"] and options["groups"] : 245 248 raise PyKotaToolError, _("incompatible options, see help.") 246 elif options["groups"] :247 raise PyKotaToolError, _("option --groups is currently not implemented.")248 249 elif args : 249 250 raise PyKotaToolError, _("unused arguments [%s]. Aborting.") % ", ".join(args) -
pykota/trunk/bin/warnpykota
r900 r927 23 23 # 24 24 # $Log$ 25 # Revision 1.16 2003/04/16 12:35:49 jalet 26 # Groups quota work now ! 27 # 25 28 # Revision 1.15 2003/04/10 21:47:20 jalet 26 29 # Job history added. Upgrade script neutralized for now ! … … 175 178 elif options["users"] and options["groups"] : 176 179 raise PyKotaToolError, _("incompatible options, see help.") 177 elif options["groups"] :178 raise PyKotaToolError, _("option --groups is currently not implemented.")179 180 elif args : 180 181 raise PyKotaToolError, _("unused arguments [%s]. Aborting.") % ", ".join(args) -
pykota/trunk/NEWS
r926 r927 22 22 PyKota NEWS : 23 23 24 - 1.03beta : 25 26 - Group quotas seem to work now ! 27 24 28 - 1.03alpha : 25 29 -
pykota/trunk/po/en/pykota.po
r925 r927 21 21 # 22 22 # $Log$ 23 # Revision 1.18 2003/04/16 12:35:49 jalet 24 # Groups quota work now ! 25 # 23 26 # Revision 1.17 2003/04/16 08:53:14 jalet 24 27 # Printing can now be limited either by user's account balance or by … … 253 256 msgstr "" 254 257 255 msgid "You have to pass user names on the command line"258 msgid "You have to pass user or group names on the command line" 256 259 msgstr "" 257 260 … … 279 282 msgid "Unable to find user %s's account balance, applying default policy (%s) for printer %s" 280 283 msgstr "" 284 285 msgid "Unable to find group %s's account balance, applying default policy (%s) for printer %s" 286 msgstr "" 287 288 msgid "Unable to match group %s on printer %s, applying default policy (%s)" 289 msgstr "" 290 291 msgid "Print Quota exceeded for group %s on printer %s" 292 msgstr "" 293 294 msgid "" 295 "You are not allowed to print anymore because\n" 296 "your group Print Quota is exceeded on printer %s." 297 msgstr "" 298 299 msgid "Print Quota soft limit exceeded for group %s on printer %s" 300 msgstr "" 301 302 msgid "" 303 "You will soon be forbidden to print anymore because\n" 304 "your group Print Quota is almost reached on printer %s." 305 msgstr "" -
pykota/trunk/po/fr/pykota.po
r925 r927 21 21 # 22 22 # $Log$ 23 # Revision 1.16 2003/04/16 12:35:49 jalet 24 # Groups quota work now ! 25 # 23 26 # Revision 1.15 2003/04/16 08:53:14 jalet 24 27 # Printing can now be limited either by user's account balance or by … … 261 264 msgstr "R� : %s" 262 265 263 msgid "You have to pass user names on the command line"264 msgstr "Vous devez passer des noms d'utilisateur sur la ligne de commande"266 msgid "You have to pass user or group names on the command line" 267 msgstr "Vous devez passer des noms d'utilisateurs ou de groupes sur la ligne de commande" 265 268 266 269 msgid "unknown" … … 287 290 msgid "Unable to find user %s's account balance, applying default policy (%s) for printer %s" 288 291 msgstr "Impossible de trouver le solde du compte de l'utilisateur %s, action par d�ut (%s) appliqu�sur l'imprimante %s" 292 293 msgid "Unable to find group %s's account balance, applying default policy (%s) for printer %s" 294 msgstr "Impossible de trouver le solde du compte du groupe %s, action par d�ut (%s) appliqu�sur l'imprimante %s" 295 296 msgid "Unable to match group %s on printer %s, applying default policy (%s)" 297 msgstr "Impossible de trouver le groupe %s sur l'imprimante %s, action par d�ut (%s) appliqu� 298 299 msgid "Print Quota exceeded for group %s on printer %s" 300 msgstr "D�ssement de Quota d'impression pour le groupe %s sur l'imprimante %s" 301 302 msgid "" 303 "You are not allowed to print anymore because\n" 304 "your group Print Quota is exceeded on printer %s." 305 msgstr "" 306 "Vous n'�s plus autoris� imprimer car\n" 307 "le Quota d'Impression de votre groupe est d�ss�ur l'imprimante %s." 308 309 msgid "Print Quota soft limit exceeded for group %s on printer %s" 310 msgstr "Limite souple de Quota d'Impression d�ss�pour le groupe %s sur l'imprimante %s" 311 312 msgid "" 313 "You will soon be forbidden to print anymore because\n" 314 "your group Print Quota is almost reached on printer %s." 315 msgstr "" 316 "Vous n'aurez bient�lus le droit d'imprimer car\n" 317 "le Quota d'Impression de votre groupe sur l'imprimante %s est presque atteint." -
pykota/trunk/po/pykota.pot
r925 r927 21 21 # 22 22 # $Log$ 23 # Revision 1.18 2003/04/16 12:35:49 jalet 24 # Groups quota work now ! 25 # 23 26 # Revision 1.17 2003/04/16 08:53:14 jalet 24 27 # Printing can now be limited either by user's account balance or by … … 253 256 msgstr "" 254 257 255 msgid "You have to pass user names on the command line"258 msgid "You have to pass user or group names on the command line" 256 259 msgstr "" 257 260 … … 279 282 msgid "Unable to find user %s's account balance, applying default policy (%s) for printer %s" 280 283 msgstr "" 284 285 msgid "Unable to find group %s's account balance, applying default policy (%s) for printer %s" 286 msgstr "" 287 288 msgid "Unable to match group %s on printer %s, applying default policy (%s)" 289 msgstr "" 290 291 msgid "Print Quota exceeded for group %s on printer %s" 292 msgstr "" 293 294 msgid "" 295 "You are not allowed to print anymore because\n" 296 "your group Print Quota is exceeded on printer %s." 297 msgstr "" 298 299 msgid "Print Quota soft limit exceeded for group %s on printer %s" 300 msgstr "" 301 302 msgid "" 303 "You will soon be forbidden to print anymore because\n" 304 "your group Print Quota is almost reached on printer %s." 305 msgstr "" -
pykota/trunk/pykota/storages/sql.py
r925 r927 21 21 # 22 22 # $Log$ 23 # Revision 1.27 2003/04/16 12:35:49 jalet 24 # Groups quota work now ! 25 # 23 26 # Revision 1.26 2003/04/16 08:53:14 jalet 24 27 # Printing can now be limited either by user's account balance or by … … 196 199 return [(record["id"], record["groupname"]) for record in result] 197 200 201 def getGroupMembersNames(self, groupname) : 202 """Returns the list of user's names which are member of this group.""" 203 groupid = self.getGroupId(groupname) 204 if groupid is None : 205 return [] 206 else : 207 result = self.doQuery("SELECT DISTINCT username FROM users WHERE id IN (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(groupid)) 208 return [record["username"] for record in (self.doParseResult(result) or [])] 209 210 def getUserGroupsNames(self, userid) : 211 """Returns the list of groups' names the user is a member of.""" 212 result = self.doQuery("SELECT DISTINCT groupname FROM groups WHERE id IN (SELECT groupid FROM groupsmembers WHERE userid=%s)" % self.doQuote(userid)) 213 return [record["groupname"] for record in (self.doParseResult(result) or [])] 214 198 215 def addPrinter(self, printername) : 199 216 """Adds a printer to the quota storage, returns its id.""" … … 216 233 if userid is None : 217 234 userid = self.addUser(username) 218 self.doQuery("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(userid), self.doQuote(printerid))) 235 uqexists = (self.getUserPQuota(userid, printerid) is not None) 236 if not uqexists : 237 self.doQuery("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(userid), self.doQuote(printerid))) 219 238 return (userid, printerid) 220 239 … … 223 242 groupid = self.getGroupId(groupname) 224 243 if groupid is None : 225 groupid = self.addUser(groupname) 226 self.doQuery("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(groupid), self.doQuote(printerid))) 244 groupid = self.addGroup(groupname) 245 gqexists = (self.getGroupPQuota(groupid, printerid) is not None) 246 if not gqexists : 247 self.doQuery("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(groupid), self.doQuote(printerid))) 227 248 return (groupid, printerid) 228 249 … … 234 255 """Returns the current account balance for a given user.""" 235 256 result = self.doQuery("SELECT balance FROM users WHERE id=%s" % self.doQuote(userid)) 257 try : 258 return self.doParseResult(result)[0]["balance"] 259 except TypeError : # Not found 260 return 261 262 def getGroupBalance(self, groupid) : 263 """Returns the current account balance for a given group, as the sum of each of its users' account balance.""" 264 result = self.doQuery("SELECT SUM(balance) AS balance FROM users WHERE id in (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(groupid)) 236 265 try : 237 266 return self.doParseResult(result)[0]["balance"] … … 273 302 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))) 274 303 304 def setGroupPQuota(self, groupid, printerid, softlimit, hardlimit) : 305 """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid).""" 306 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))) 307 275 308 def resetUserPQuota(self, userid, printerid) : 276 309 """Resets the page counter to zero for a user on a printer. Life time page counter is kept unchanged.""" 277 310 self.doQuery("UPDATE userpquota SET pagecounter=0, datelimit=NULL WHERE userid=%s AND printerid=%s" % (self.doQuote(userid), self.doQuote(printerid))) 311 312 def resetGroupPQuota(self, groupid, printerid) : 313 """Resets the page counter to zero for a group on a printer. Life time page counter is kept unchanged.""" 314 self.doQuery("UPDATE grouppquota SET pagecounter=0, datelimit=NULL WHERE groupid=%s AND printerid=%s" % (self.doQuote(groupid), self.doQuote(printerid))) 278 315 279 316 def updateUserPQuota(self, userid, printerid, pagecount) : … … 293 330 return 294 331 332 def getGroupPQuota(self, groupid, printerid) : 333 """Returns the Print Quota information for a given (groupid, printerid).""" 334 result = self.doQuery("SELECT softlimit, hardlimit, datelimit FROM grouppquota WHERE groupid=%s AND printerid=%s" % (self.doQuote(groupid), self.doQuote(printerid))) 335 try : 336 grouppquota = self.doParseResult(result)[0] 337 except TypeError : 338 return 339 else : 340 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))) 341 try : 342 result = self.doParseResult(result)[0] 343 except TypeError : # Not found 344 return 345 else : 346 grouppquota.update({"lifepagecounter": result["lifepagecounter"], "pagecounter": result["pagecounter"]}) 347 return grouppquota 348 295 349 def setUserDateLimit(self, userid, printerid, datelimit) : 296 350 """Sets the limit date for a soft limit to become an hard one given (userid, printerid).""" 297 351 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))) 352 353 def setGroupDateLimit(self, groupid, printerid, datelimit) : 354 """Sets the limit date for a soft limit to become an hard one given (groupid, printerid).""" 355 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))) 298 356 299 357 def addJobToHistory(self, jobid, userid, printerid, pagecounter, action) : … … 314 372 return 315 373 374 def addUserToGroup(self, userid, groupid) : 375 """Adds an user to a group.""" 376 result = self.doQuery("SELECT COUNT(*) AS mexists FROM groupsmembers WHERE groupid=%s AND userid=%s" % (self.doQuote(groupid), self.doQuote(userid))) 377 try : 378 mexists = self.doParseResult(result)[0]["mexists"] 379 except TypeError : 380 mexists = 0 381 if not mexists : 382 self.doQuery("INSERT INTO groupsmembers (groupid, userid) VALUES (%s, %s)" % (self.doQuote(groupid), self.doQuote(userid))) 383 316 384 def deleteUser(self, userid) : 317 385 """Completely deletes an user from the Quota Storage.""" -
pykota/trunk/pykota/tool.py
r925 r927 21 21 # 22 22 # $Log$ 23 # Revision 1.33 2003/04/16 12:35:49 jalet 24 # Groups quota work now ! 25 # 23 26 # Revision 1.32 2003/04/16 08:53:14 jalet 24 27 # Printing can now be limited either by user's account balance or by … … 287 290 self.sendMessage(adminmail, adminmail, "Subject: %s\n\n%s" % (subject, message)) 288 291 292 def checkGroupPQuota(self, groupname, printername) : 293 """Checks the group quota on a printer and deny or accept the job.""" 294 printerid = self.storage.getPrinterId(printername) 295 groupid = self.storage.getGroupId(groupname) 296 limitby = self.storage.getGroupLimitBy(groupid) 297 if limitby == "balance" : 298 balance = self.storage.getGroupBalance(groupid) 299 if balance is None : 300 policy = self.config.getPrinterPolicy(printername) 301 if policy in [None, "ALLOW"] : 302 action = "POLICY_ALLOW" 303 else : 304 action = "POLICY_DENY" 305 self.logger.log_message(_("Unable to find group %s's account balance, applying default policy (%s) for printer %s") % (groupname, action, printername)) 306 else : 307 # TODO : there's no warning (no account balance soft limit) 308 if balance <= 0.0 : 309 action = "DENY" 310 else : 311 action = "ALLOW" 312 else : 313 quota = self.storage.getGroupPQuota(groupid, printerid) 314 if quota is None : 315 # Unknown group or printer or combination 316 policy = self.config.getPrinterPolicy(printername) 317 if policy in [None, "ALLOW"] : 318 action = "POLICY_ALLOW" 319 else : 320 action = "POLICY_DENY" 321 self.logger.log_message(_("Unable to match group %s on printer %s, applying default policy (%s)") % (groupname, printername, action)) 322 else : 323 pagecounter = quota["pagecounter"] 324 softlimit = quota["softlimit"] 325 hardlimit = quota["hardlimit"] 326 datelimit = quota["datelimit"] 327 if softlimit is not None : 328 if pagecounter < softlimit : 329 action = "ALLOW" 330 else : 331 if hardlimit is None : 332 # only a soft limit, this is equivalent to having only a hard limit 333 action = "DENY" 334 else : 335 if softlimit <= pagecounter < hardlimit : 336 now = DateTime.now() 337 if datelimit is not None : 338 datelimit = DateTime.ISO.ParseDateTime(datelimit) 339 else : 340 datelimit = now + self.config.getGraceDelay(printername) 341 self.storage.setGroupDateLimit(groupid, printerid, datelimit) 342 if now < datelimit : 343 action = "WARN" 344 else : 345 action = "DENY" 346 else : 347 action = "DENY" 348 else : 349 if hardlimit is not None : 350 # no soft limit, only a hard one. 351 if pagecounter < hardlimit : 352 action = "ALLOW" 353 else : 354 action = "DENY" 355 else : 356 # Both are unset, no quota, i.e. accounting only 357 action = "ALLOW" 358 return action 359 289 360 def checkUserPQuota(self, username, printername) : 290 361 """Checks the user quota on a printer and deny or accept the job.""" 362 # first we check any group the user is a member of 363 userid = self.storage.getUserId(username) 364 for groupname in self.storage.getUserGroupsNames(userid) : 365 action = self.checkGroupPQuota(groupname, printername) 366 if action in ("DENY", "POLICY_DENY") : 367 return action 368 369 # then we check the user's own quota 291 370 printerid = self.storage.getPrinterId(printername) 292 userid = self.storage.getUserId(username)293 371 limitby = self.storage.getUserLimitBy(userid) 294 372 if limitby == "balance" : … … 355 433 return action 356 434 357 def warnGroupPQuota(self, username, printername=None) :358 """Checks a user quota and send him a messageif quota is exceeded on current printer."""435 def warnGroupPQuota(self, groupname, printername=None) : 436 """Checks a group quota and send messages if quota is exceeded on current printer.""" 359 437 pname = printername or self.printername 360 raise PyKotaToolError, _("Group quotas are currently not implemented.") 438 admin = self.config.getAdmin(pname) 439 adminmail = self.config.getAdminMail(pname) 440 mailto = self.config.getMailTo(pname) 441 action = self.checkGroupPQuota(groupname, pname) 442 groupmembers = self.storage.getGroupMembersNames(groupname) 443 if action.startswith("POLICY_") : 444 action = action[7:] 445 if action == "DENY" : 446 adminmessage = _("Print Quota exceeded for group %s on printer %s") % (groupname, pname) 447 self.logger.log_message(adminmessage) 448 if mailto in [ "BOTH", "ADMIN" ] : 449 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 450 for username in groupmembers : 451 if mailto in [ "BOTH", "USER" ] : 452 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.") % pname) 453 elif action == "WARN" : 454 adminmessage = _("Print Quota soft limit exceeded for group %s on printer %s") % (groupname, pname) 455 self.logger.log_message(adminmessage) 456 if mailto in [ "BOTH", "ADMIN" ] : 457 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 458 for username in groupmembers : 459 if mailto in [ "BOTH", "USER" ] : 460 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.") % pname) 461 return action 361 462 362 463 def warnUserPQuota(self, username, printername=None) : -
pykota/trunk/pykota/version.py
r883 r927 21 21 # 22 22 23 __version__ = "1.03 alpha-unofficial"23 __version__ = "1.03beta-unofficial" 24 24 25 25 __doc__ = """PyKota : a complete Printing Quota Solution for CUPS.""" -
pykota/trunk/README
r926 r927 30 30 Actual working features : 31 31 32 - Per printer user quotas.32 - Per printer user and group quotas. 33 33 34 34 - Automated email warning of users above quota to the … … 195 195 Copy the conf/pykota.conf.sample sample configuration file to 196 196 /etc/pykota.conf, and adapt this file to your own needs and 197 configuration. 197 configuration. The installation script tries to do this for 198 you if needed and you agreed to this action. 198 199 199 200 Modify the PPD files for each printer on which you want to manage … … 249 250 along with totals. 250 251 251 WARNING : as of today, 2003-02-06, group quotas are not252 implemented.253 254 252 SECURITY : You should ensure that only the print quota administrator 255 253 can run the warnpykota command, but this is actually not -
pykota/trunk/TODO
r873 r927 22 22 TODO, in order of importance : 23 23 24 - Finalize the implementation of group quotas.25 26 24 - Group administrators (think quotagrpdmins for disk quotas). 27 25