From ee33e84c8579ffe5d61d71859d4bfda7b10abdb3 Mon Sep 17 00:00:00 2001 From: richard Date: Mon, 21 Oct 2002 00:42:00 +0000 Subject: [PATCH] - remember the change note on bad submissions (sf bug 625989) - highlight required form fields (sf bug 625989) add a couple of examples to the customisation doc too. un-reversed the message list so first messages appear first. fixed the messages header (post introduction of "remove") git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1366 57a73879-2fb5-44c3-a270-3262357dd7e2 --- CHANGES.txt | 2 + doc/customizing.txt | 180 +++++++++++++++++++++- roundup/templates/classic/html/issue.item | 20 ++- roundup/templates/classic/html/style.css | 7 +- 4 files changed, 200 insertions(+), 9 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 8493624..62653bc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,8 @@ are given with the most recent entry first. - added CGI :remove: and :add: which specify item ids to remove / add in multilink. - bugfix in boolean templating +- remember the change note on bad submissions (sf bug 625989) +- highlight required form fields (sf bug 625989) 2002-10-16 0.5.1 diff --git a/doc/customizing.txt b/doc/customizing.txt index d683f27..1c410ba 100644 --- a/doc/customizing.txt +++ b/doc/customizing.txt @@ -2,7 +2,7 @@ Customising Roundup =================== -:Version: $Revision: 1.58 $ +:Version: $Revision: 1.59 $ .. This document borrows from the ZopeBook section on ZPT. The original is at: http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx @@ -2579,6 +2579,184 @@ able to give a summary of the total time spent on a particular issue. example - then you'll need to restart that to pick up the code changes. When that's done, you'll be able to use the new time logging interface. +Using a UN*X passwd file as the user database +--------------------------------------------- + +On some systems, the primary store of users is the UN*X passwd file. It holds +information on users such as their username, real name, password and primary +user group. + +Roundup can use this store as its primary source of user information, but it +needs additional information too - email address(es), roundup Roles, vacation +flags, roundup hyperdb item ids, etc. Also, "retired" users must still exist +in the user database, unlike some passwd files in which the users are removed +when they no longer have access to a system. + +To make use of the passwd file, we therefore synchronise between the two user +stores. We also use the passwd file to validate the user logins, as described +in the previous example, `using an external password validation source`_. We +keep the users lists in sync using a fairly simple script that runs once a +day, or several times an hour if more immediate access is needed. In short, it: + +1. parses the passwd file, finding usernames, passwords and real names, +2. compares that list to the current roundup user list: + a. entries no longer in the passwd file are *retired* + b. entries with mismatching real names are *updated* + a. entries only exist in the passwd file are *created* +3. send an email to administrators to let them know what's been done. + +The retiring and updating are simple operations, requiring only a call to +``retire()`` or ``set()``. The creation operation requires more information +though - the user's email address and their roundup Roles. We're going to +assume that the user's email address is the same as their login name, so we +just append the domain name to that. The Roles are determined using the +passwd group identifier - mapping their UN*X group to an appropriate set of +Roles. + +The script to perform all this, broken up into its main components, is as +follows. Firstly, we import the necessary modules and open the tracker we're +to work on:: + + import sys, os, smtplib + from roundup import instance, date + + # open the tracker + tracker_home = sys.argv[1] + tracker = instance.open(tracker_home) + +Next we read in the *passwd* file from the tracker home:: + + # read in the users + file = os.path.join(tracker_home, 'users.passwd') + users = [x.strip().split(':') for x in open(file).readlines()] + +Handle special users (those to ignore in the file, and those who don't appear +in the file):: + + # users to not keep ever, pre-load with the users I know aren't + # "real" users + ignore = ['ekmmon', 'bfast', 'csrmail'] + + # users to keep - pre-load with the roundup-specific users + keep = ['comment_pool', 'network_pool', 'admin', 'dev-team', 'cs_pool', + 'anonymous', 'system_pool', 'automated'] + +Now we map the UN*X group numbers to the Roles that users should have:: + + roles = { + '501': 'User,Tech', # tech + '502': 'User', # finance + '503': 'User,CSR', # customer service reps + '504': 'User', # sales + '505': 'User', # marketing + } + +Now we do all the work. Note that the body of the script (where we have the +tracker database open) is wrapped in a ``try`` / ``finally`` clause, so that +we always close the database cleanly when we're finished. So, we now do all +the work:: + + # open the database + db = tracker.open('admin') + try: + # store away messages to send to the tracker admins + msg = [] + + # loop over the users list read in from the passwd file + for user,passw,uid,gid,real,home,shell in users: + if user in ignore: + # this user shouldn't appear in our tracker + continue + keep.append(user) + try: + # see if the user exists in the tracker + uid = db.user.lookup(user) + + # yes, they do - now check the real name for correctness + if real != db.user.get(uid, 'realname'): + db.user.set(uid, realname=real) + msg.append('FIX %s - %s'%(user, real)) + except KeyError: + # nope, the user doesn't exist + db.user.create(username=user, realname=real, + address='%s@ekit-inc.com'%user, roles=roles[gid]) + msg.append('ADD %s - %s (%s)'%(user, real, roles[gid])) + + # now check that all the users in the tracker are also in our "keep" + # list - retire those who aren't + for uid in db.user.list(): + user = db.user.get(uid, 'username') + if user not in keep: + db.user.retire(uid) + msg.append('RET %s'%user) + + # if we did work, then send email to the tracker admins + if msg: + # create the email + msg = '''Subject: %s user database maintenance + + %s + '''%(db.config.TRACKER_NAME, '\n'.join(msg)) + + # send the email + smtp = smtplib.SMTP(db.config.MAILHOST) + addr = db.config.ADMIN_EMAIL + smtp.sendmail(addr, addr, msg) + + # now we're done - commit the changes + db.commit() + finally: + # always close the database cleanly + db.close() + +And that's it! + + +Enabling display of either message summaries or the entire messages +------------------------------------------------------------------- + +This is pretty simple - all we need to do is copy the code from the example +`displaying entire message contents in the issue display`_ into our template +alongside the summary display, and then introduce a switch that shows either +one or the other. We'll use a new form variable, ``:whole_messages`` to +achieve this:: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Messages + show entire messages +
authordatesummary + remove +
Messagesshow only summaries
authordate + (remove) +
+ ------------------- diff --git a/roundup/templates/classic/html/issue.item b/roundup/templates/classic/html/issue.item index 3215703..2094185 100644 --- a/roundup/templates/classic/html/issue.item +++ b/roundup/templates/classic/html/issue.item @@ -18,12 +18,12 @@ You are not allowed to view this page. - + - + @@ -60,7 +60,8 @@ python:db.user.classhelp('username,realname,address,phone')" />
@@ -76,9 +77,16 @@ python:db.user.classhelp('username,realname,address,phone')" />
TitleTitle title
PriorityPriority priority Status status
Change Note - +
- + + + + + + +
Note: highlighted fields are required.
+ @@ -114,8 +122,8 @@ python:db.user.classhelp('username,realname,address,phone')" />

Titletitle
- - + + diff --git a/roundup/templates/classic/html/style.css b/roundup/templates/classic/html/style.css index 8aad458..fc376d4 100644 --- a/roundup/templates/classic/html/style.css +++ b/roundup/templates/classic/html/style.css @@ -70,19 +70,22 @@ table.form { } table.form th { - font-weight: bold; color: #333388; text-align: right; vertical-align: top; + font-weight: normal; } table.form th.header { font-weight: bold; - color: #333388; background-color: #eeeeff; text-align: left; } +table.form th.required { + font-weight: bold; +} + table.form td { color: #333333; empty-cells: show; -- 2.30.2
Messages
Messages
author