From 00fff27257d55a1f7b2fc6daaa6e1fb037e8fb91 Mon Sep 17 00:00:00 2001 From: richard Date: Thu, 3 Oct 2002 06:56:30 +0000 Subject: [PATCH] merge from maintenance branch git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1311 57a73879-2fb5-44c3-a270-3262357dd7e2 --- CHANGES.txt | 14 + TODO.txt | 11 +- doc/.cvsignore | 1 - doc/Makefile | 2 +- doc/announcement.txt | 77 +---- doc/customizing.txt | 385 ++++++++++++++++----- doc/design.txt | 154 +++------ doc/developers.txt | 42 ++- doc/getting_started.txt | 279 --------------- doc/index.txt | 2 +- doc/installation.txt | 27 +- roundup/__init__.py | 36 +- roundup/admin.py | 38 +- roundup/backends/__init__.py | 8 +- roundup/backends/back_bsddb3.py | 5 +- roundup/backends/back_gadfly.py | 24 +- roundup/backends/portalocker.py | 4 +- roundup/backends/rdbms_common.py | 23 +- roundup/cgi/TAL/TALGenerator.py | 13 +- roundup/cgi/client.py | 47 ++- roundup/cgi/templating.py | 2 +- roundup/hyperdb.py | 4 +- roundup/mailgw.py | 4 +- roundup/templates/classic/html/issue.index | 32 +- roundup/templates/classic/html/query.item | 17 +- roundup/templates/classic/html/style.css | 8 + roundup/templates/classic/html/user.index | 2 +- roundup/templates/minimal/html/style.css | 8 + roundup/templates/minimal/html/user.index | 2 +- test/test_db.py | 2 +- 30 files changed, 618 insertions(+), 655 deletions(-) delete mode 100644 doc/getting_started.txt diff --git a/CHANGES.txt b/CHANGES.txt index e968842..597a754 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,19 @@ This file contains the changes to the Roundup system over time. The entries are given with the most recent entry first. +2002-10-?? 0.5.1 +- highlight rows in groups of three +- metakit cleanups +- nicer "navigation" style in index views + + +2002-10-02 0.5.0 +- fixed style for alternating rows in user lists +- fixed query edit form so it doesn't barf +- #617133 ] 0.5.0pr1 uses nonexistent renderTemplate +- merged Zope Collector #539 fix from ZPT CVS trunk + + 2002-09-27 0.5.0 pr1 - handling of None for Date/Interval/Password values in export/import - handling of journal values in export/import @@ -48,6 +61,7 @@ are given with the most recent entry first. tracker interfaces module - fixed login attempt by user that doesn't exist + 2002-09-13 0.5.0 beta2 - all backends now have a .close() method, and it's used everywhere - fixed bug in detectors __init__ diff --git a/TODO.txt b/TODO.txt index 598ea05..f02a0b0 100644 --- a/TODO.txt +++ b/TODO.txt @@ -30,6 +30,8 @@ pending mailgw Allow multiple email addresses at one gw with different pending mailgw Identification of users should have a configurable degree of strictness (ie. turn off username==address matching) +pending mailgw Use in-reply-to for determining message lineage when subject + line lets us down pending project switch to a Roundup instance for Roundup bug/feature tracking pending security authenticate over a secure connection pending security optionally auth with Basic HTTP auth instead of cookies @@ -44,15 +46,18 @@ pending web Quick help links next to the property labels giving a pending web clicking on a group header should filter for that type of entry pending web re-enable auth basic http auth -pending web search "refinement" - pre-fill the search page with the - current search parameters -pending web UNIX init.d script for roundup-server pending web allow multilink selections to select a "none" element to allow people with broken browsers to select nothing? pending web automagically link designators pending web add checkbox-based removal/addition for multilink entries (eg "add me"/"remove me" for nosy list) +pending web multilink item removal action (with retirement) +pending web search "refinement" - pre-fill the search page with the + current search parameters +pending web column-heading sort stuff isn't implemented +active web UNIX init.d script for roundup-server bug docs need to mention somewhere how sorting works +bug web query editing isn't fully implemented ======= ========= ============================================================= diff --git a/doc/.cvsignore b/doc/.cvsignore index 21d8992..a6565df 100644 --- a/doc/.cvsignore +++ b/doc/.cvsignore @@ -1,7 +1,6 @@ announcement.html customizing.html developers.html -getting_started.html implementation.html index.html installation.html diff --git a/doc/Makefile b/doc/Makefile index 75d4f2b..987dfe7 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,7 +2,7 @@ PYTHON = /usr/bin/python2 STXTOHTML = -c "from docutils.core import publish;publish(writer_name='html')" SOURCE = announcement.txt customizing.txt developers.txt FAQ.txt features.txt \ - getting_started.txt glossary.txt implementation.txt index.txt \ + glossary.txt implementation.txt index.txt design.txt \ installation.txt security.txt upgrading.txt user_guide.txt \ maintenance.txt diff --git a/doc/announcement.txt b/doc/announcement.txt index e9c0646..b2602f2 100644 --- a/doc/announcement.txt +++ b/doc/announcement.txt @@ -1,76 +1,37 @@ -=========================================================== -SC-Track Roundup 0.5 pre-release - an issue tracking system -=========================================================== +================================================= +SC-Track Roundup 0.5.0 - an issue tracking system +================================================= -Note: This is the final pre-release of the newest version of Roundup. It is - strongly recommended that you maintain your existing 0.4 installation if - you have one, and run 0.5 on a copy of the database. If you are - upgrading from 0.4, you must read doc/upgrading.txt! +Note: If you are upgrading, you *must* read doc/upgrading.txt! Roundup requires python 2.1.1 for correct operation. Support for dumbdbm requires python 2.1.2 or 2.2. 2.1.3 and 2.2.1 are recommended. -This release fixes the following specific problems: - -- fixes to import/export -- password edit now has a confirmation field -- cleanups and fixes to the shipped classic template -- new backend for sqlite (and it rocks :) -- many performance improvements in dbm and sql backends -- cgi.client base URL is now obtained from the config TRACKER_WEB (as a result - request.url has gone away - there's too much magic in trying to figure - what it should be) -- cgi-bin script redirects to https now if the request was https -- FileClass "content" property wasn't being returned by getprops() in most - backends -- we now verify instance attributes on instance open and throw a useful error - if they're not all there -- sf bug 611217 ] menu() has problems when labelprop==None -- verify contents of tracker module when the tracker is opened -- fixes to value parsing from edit forms -- mailgw was missing an "import sys" (!) -- setup now installs scripts with python -O flag, doubling performance in some - cases (there's a lot of __debug__ use) -- added getItem to HTMLClass so you can access arbitrary items in templates -- replaced the content() callback ickiness with Page Template macro usage -- changed the default CSS style to be less offensive to some ;) -- better handling of Page Template compilation errors -- sf bug 614188 ] Exception in mailgw.py -- sf bug 613310 ] traceback on onexistant items -- sf bug 613291 ] typos in nosy list -- handle stupid mailers that QUOTE their Re; 'Re: "[issue1] bla blah"' -- giving a user a Role that doesn't exist doesn't break stuff any more -- revamped user guide, customisation guide, added basic maintenance guide -- merged some bugfixes from the Zope Page Templates trunk -- added the "minimal" template - -A lot has been done since 0.4: +A lot has been done since 0.4.4: - new backend for metakit (thanks Gordon McMillan) - new backend for sqlite - new backend for gadfly (it's as done as it's going to get) -- further split the dbm backends from the core code, allowing easier - non-dict-like backends (eg metakit, RDB) - added Boolean and Number types -- fixed the journal bloat +- fixed the journal bloat, re-enabling useful link journal events - full-text search may also search certain String properties -- entire database export and import (incl files) -- implemented and used the new access control mechanisms (Permissions, Roles) +- entire database export and import (including files) +- implemented new per-user access control mechanisms (Permissions, Roles) - switched templating to use Zope's PageTemplates giving much more flexibility +- made web interface more generic, robust, give nicer errors, ... - revamped look and feel in web interface including cleaned up CSS usage -- re-worked cgi interface to abstract out the explicit "issue" interface -- switched to sessions for web authentication +- switched to cookie-based sessions for web authentication - saving of named search queries -- updated design document for new access controls -- updated customisation document, including more examples -- added maintenance guide -- better mailgw help message (feature request #558562) -- we handle "not found", access and item page render errors better -- fixed double-submit by having new-item-submit redirect at end +- lots of documentation cleanups including an updated customisation document + with los of examples and a new maintenance guide - roundup-server may be a daemon now (fork, logfile, pidfile) -- renamed "instance" to "tracker" everywhere, and "node" to "item" in most - places -- many more bug fixes, cleanups and minor improvements +- many, many more bug fixes, cleanups and minor improvements (see CHANGES.txt) + +This final 0.5.0 release fixes the following problems: + +- fixed style for alternating rows in user lists +- a couple of other minor bugs +- updated demo to use 0.5 codebase Source and documentation is available at the website: http://roundup.sourceforge.net/ diff --git a/doc/customizing.txt b/doc/customizing.txt index 55d7acb..96e52ca 100644 --- a/doc/customizing.txt +++ b/doc/customizing.txt @@ -2,7 +2,7 @@ Customising Roundup =================== -:Version: $Revision: 1.50 $ +:Version: $Revision: 1.51 $ .. This document borrows from the ZopeBook section on ZPT. The original is at: http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx @@ -13,6 +13,9 @@ Customising Roundup What You Can Do =============== +Before you get too far, it's probably worth having a quick read of the Roundup +`design documentation`_. + Customisation of Roundup can take one of five forms: 1. `tracker configuration`_ file changes @@ -20,6 +23,7 @@ Customisation of Roundup can take one of five forms: 3. "definition" class `database content`_ changes 4. behavioural changes, through detectors_ 5. `access controls`_ +6. change the `web interface`_ The third case is special because it takes two distinctly different forms depending upon whether the tracker has been initialised or not. The other two @@ -190,45 +194,27 @@ tracker. The "classic" schema looks like this:: pri = Class(db, "priority", name=String(), order=String()) pri.setkey("name") - pri.create(name="critical", order="1") - pri.create(name="urgent", order="2") - pri.create(name="bug", order="3") - pri.create(name="feature", order="4") - pri.create(name="wish", order="5") stat = Class(db, "status", name=String(), order=String()) stat.setkey("name") - stat.create(name="unread", order="1") - stat.create(name="deferred", order="2") - stat.create(name="chatting", order="3") - stat.create(name="need-eg", order="4") - stat.create(name="in-progress", order="5") - stat.create(name="testing", order="6") - stat.create(name="done-cbb", order="7") - stat.create(name="resolved", order="8") keyword = Class(db, "keyword", name=String()) keyword.setkey("name") - user = Class(db, "user", username=String(), password=String(), - address=String(), realname=String(), phone=String(), - organisation=String()) + user = Class(db, "user", username=String(), organisation=String(), + password=String(), address=String(), realname=String(), phone=String()) user.setkey("username") - user.create(username="admin", password=adminpw, - address=config.ADMIN_EMAIL) - msg = FileClass(db, "msg", author=Link("user"), recipients=Multilink - ("user"), date=Date(), summary=String(), files=Multilink("file")) + msg = FileClass(db, "msg", author=Link("user"), summary=String(), + date=Date(), recipients=Multilink("user"), files=Multilink("file")) file = FileClass(db, "file", name=String(), type=String()) - issue = IssueClass(db, "issue", assignedto=Link("user"), - topic=Multilink("keyword"), priority=Link("priority"), status=Link - ("status")) + issue = IssueClass(db, "issue", topic=Multilink("keyword"), + status=Link("status"), assignedto=Link("user"), + priority=Link("priority")) issue.setkey('title') -XXX security definitions - Classes and Properties - creating a new information store --------------------------------------------------------- @@ -434,6 +420,143 @@ See "`adding a new field to the classic schema`_" for an example that requires database content changes. +Access Controls +=============== + +A set of Permissions are built in to the security module by default: + +- Edit (everything) +- View (everything) + +The default interfaces define: + +- Web Registration +- Web Access +- Web Roles +- Email Registration +- Email Access + +These are hooked into the default Roles: + +- Admin (Edit everything, View everything, Web Roles) +- User (Web Access, Email Access) +- Anonymous (Web Registration, Email Registration) + +And finally, the "admin" user gets the "Admin" Role, and the "anonymous" user +gets the "Anonymous" assigned when the database is initialised on installation. +The two default schemas then define: + +- Edit issue, View issue (both) +- Edit file, View file (both) +- Edit msg, View msg (both) +- Edit support, View support (extended only) + +and assign those Permissions to the "User" Role. Put together, these settings +appear in the ``open()`` function of the tracker ``dbinit.py`` (the following +is taken from the "minimal" template ``dbinit.py``):: + + # + # SECURITY SETTINGS + # + # new permissions for this schema + for cl in ('user', ): + db.security.addPermission(name="Edit", klass=cl, + description="User is allowed to edit "+cl) + db.security.addPermission(name="View", klass=cl, + description="User is allowed to access "+cl) + + # and give the regular users access to the web and email interface + p = db.security.getPermission('Web Access') + db.security.addPermissionToRole('User', p) + p = db.security.getPermission('Email Access') + db.security.addPermissionToRole('User', p) + + # May users view other user information? Comment these lines out + # if you don't want them to + p = db.security.getPermission('View', 'user') + db.security.addPermissionToRole('User', p) + + # Assign the appropriate permissions to the anonymous user's Anonymous + # Role. Choices here are: + # - Allow anonymous users to register through the web + p = db.security.getPermission('Web Registration') + db.security.addPermissionToRole('Anonymous', p) + # - Allow anonymous (new) users to register through the email gateway + p = db.security.getPermission('Email Registration') + db.security.addPermissionToRole('Anonymous', p) + + +New User Roles +-------------- + +New users are assigned the Roles defined in the config file as: + +- NEW_WEB_USER_ROLES +- NEW_EMAIL_USER_ROLES + + +Changing Access Controls +------------------------ + +You may alter the configuration variables to change the Role that new web or +email users get, for example to not give them access to the web interface if +they register through email. + +You may use the ``roundup-admin`` "``security``" command to display the +current Role and Permission configuration in your tracker. + +Adding a new Permission +~~~~~~~~~~~~~~~~~~~~~~~ + +When adding a new Permission, you will need to: + +1. add it to your tracker's dbinit so it is created +2. enable it for the Roles that should have it (verify with + "``roundup-admin security``") +3. add it to the relevant HTML interface templates +4. add it to the appropriate xxxPermission methods on in your tracker + interfaces module + +Example Scenarios +~~~~~~~~~~~~~~~~~ + +**automatic registration of users in the e-mail gateway** + By giving the "anonymous" user the "Email Registration" Role, any + unidentified user will automatically be registered with the tracker (with + no password, so they won't be able to log in through the web until an admin + sets them a password). Note: this is the default behaviour in the tracker + templates that ship with Roundup. + +**anonymous access through the e-mail gateway** + Give the "anonymous" user the "Email Access" and ("Edit", "issue") Roles + but not giving them the "Email Registration" Role. This means that when an + unknown user sends email into the tracker, they're automatically logged in + as "anonymous". Since they don't have the "Email Registration" Role, they + won't be automatically registered, but since "anonymous" has permission + to use the gateway, they'll still be able to submit issues. Note that the + Sender information - their email address - will not be available - they're + *anonymous*. + +**only developers may be assigned issues** + Create a new Permission called "Fixer" for the "issue" class. Create a new + Role "Developer" which has that Permission, and assign that to the + appropriate users. Filter the list of users available in the assignedto + list to include only those users. Enforce the Permission with an auditor. See + the example `restricting the list of users that are assignable to a task`_. + +**only managers may sign off issues as complete** + Create a new Permission called "Closer" for the "issue" class. Create a new + Role "Manager" which has that Permission, and assign that to the appropriate + users. In your web interface, only display the "resolved" issue state option + when the user has the "Closer" Permissions. Enforce the Permission with + an auditor. This is very similar to the previous example, except that the + web interface check would look like:: + + + + + Web Interface ============= @@ -777,9 +900,19 @@ forms: stringified. Path expressions may have an optional ``path:`` prefix, though they are the default expression type, so it's not necessary. - XXX | components of expressions + If an expression evaluates to ``default`` then the expression is + "cancelled" - whatever HTML already exists in the template will remain + (tag content in the case of tal:content, attributes in the case of + tal:attributes). + + If an expression evaluates to ``nothing`` then the target of the expression + is removed (tag content in the case of tal:content, attributes in the case + of tal:attributes and the tag itself in the case of tal:replace). - XXX "nothing" and "default" + If an element in the path may not exist, then you can use the ``|`` + operator in the expression to provide an alternative. So, the expression + ``request/form/foo/value | default`` would simply leave the current HTML + in place if the "foo" form variable doesn't exist. **String Expressions** - eg. ``string:hello ${user/name}`` These expressions are simple string interpolations (though they can be just @@ -1421,91 +1554,70 @@ through the "journal" method of the item*:: Defining new web actions ------------------------ -XXX - - -Access Controls -=============== +You may define new actions to be triggered by the ``:action`` form variable. +These are added to the tracker ``interfaces.py`` as methods on the ``Client`` +class. -A set of Permissions are built in to the security module by default: +Adding action methods takes three steps; first you `define the new action +method`_, then you `register the action method`_ with the cgi interface so +it may be triggered by the ``:action`` form variable. Finally you actually +`use the new action`_ in your HTML form. -- Edit (everything) -- View (everything) +See "`setting up a "wizard" (or "druid") for controlled adding of issues`_" +for an example. -The default interfaces define: - -- Web Registration -- Web Access -- Web Roles -- Email Registration -- Email Access +Define the new action method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -These are hooked into the default Roles: +The action methods have the following interface:: -- Admin (Edit everything, View everything, Web Roles) -- User (Web Access, Email Access) -- Anonymous (Web Registration, Email Registration) + def myActionMethod(self): + ''' Perform some action. No return value is required. + ''' -And finally, the "admin" user gets the "Admin" Role, and the "anonymous" user -gets the "Anonymous" assigned when the database is initialised on installation. -The two default schemas then define: +The *self* argument is an instance of your tracker ``instance.Client`` class - +thus it's mostly implemented by ``roundup.cgi.Client``. See the docstring of +that class for details of what it can do. -- Edit issue, View issue (both) -- Edit file, View file (both) -- Edit msg, View msg (both) -- Edit support, View support (extended only) +The method will typically check the ``self.form`` variable's contents. It +may then: -and assign those Permissions to the "User" Role. New users are assigned the -Roles defined in the config file as: +- add information to ``self.ok_message`` or ``self.error_message`` +- change the ``self.template`` variable to alter what the user will see next +- raise Unauthorised, SendStaticFile, SendFile, NotFound or Redirect + exceptions -- NEW_WEB_USER_ROLES -- NEW_EMAIL_USER_ROLES -You may alter the configuration variables to change the Role that new web or -email users get, for example to not give them access to the web interface if -they register through email. +Register the action method +~~~~~~~~~~~~~~~~~~~~~~~~~~ -You may use the ``roundup-admin`` "``security``" command to display the -current Role and Permission configuration in your tracker. +The method is now written, but isn't available to the user until you add it to +the `instance.Client`` class ``actions`` variable, like so:: -Adding a new Permission ------------------------ + actions = client.Class.actions + ( + ('myaction', 'myActionMethod'), + ) -When adding a new Permission, you will need to: +This maps the action name "myaction" to the action method we defined. -1. add it to your tracker's dbinit so it is created -2. enable it for the Roles that should have it (verify with - "``roundup-admin security``") -3. add it to the relevant HTML interface templates -4. add it to the appropriate xxxPermission methods on in your tracker - interfaces module -Example Scenarios ------------------ +Use the new action +~~~~~~~~~~~~~~~~~~ -**automatic registration of users in the e-mail gateway** - By giving the "anonymous" user the "Email Registration" Role, any - unidentified user will automatically be registered with the tracker (with - no password, so they won't be able to log in through the web until an admin - sets them a password). Note: this is the default behaviour in the tracker - templates that ship with Roundup. +In your HTML form, add a hidden form element like so:: -**anonymous access through the e-mail gateway** - Give the "anonymous" user the "Email Access" and ("Edit", "issue") Roles - but not giving them the "Email Registration" Role. This means that when an - unknown user sends email into the tracker, they're automatically logged in - as "anonymous". Since they don't have the "Email Registration" Role, they - won't be automatically registered, but since "anonymous" has permission - to use the gateway, they'll still be able to submit issues. Note that the - Sender information - their email address - will not be available - they're - *anonymous*. + -XXX more examples needed +where "myaction" is the name you registered in the previous step. Examples ======== +.. contents:: + :local: + :depth: 1 + Adding a new field to the classic schema ---------------------------------------- @@ -2101,7 +2213,7 @@ Setting up a "wizard" (or "druid") for controlled adding of issues hooks to those actions in the "actions" attribute on that class, like so:: actions = client.Class.actions + ( - ('page1_submit', page1SubmitAction), + ('page1_submit', 'page1SubmitAction'), ) def page1SubmitAction(self): @@ -2157,9 +2269,100 @@ matches. We also remove the redundant password fields from the ``user.item`` template. +Adding a "vacation" flag to users for stopping nosy messages +------------------------------------------------------------ + +When users go on vacation and set up vacation email bouncing, you'll start to +see a lot of messages come back through Roundup "Fred is on vacation". Not +very useful, and relatively easy to stop. + +1. add a "vacation" flag to your users:: + + user = Class(db, "user", + username=String(), password=Password(), + address=String(), realname=String(), + phone=String(), organisation=String(), + alternate_addresses=String(), + roles=String(), queries=Multilink("query"), + vacation=Boolean()) + +2. edit your detector ``nosyreactor.py`` so that the ``nosyreaction()`` + consists of:: + + def nosyreaction(db, cl, nodeid, oldvalues): + # send a copy of all new messages to the nosy list + for msgid in determineNewMessages(cl, nodeid, oldvalues): + try: + users = db.user + messages = db.msg + + # figure the recipient ids + sendto = [] + r = {} + recipients = messages.get(msgid, 'recipients') + for recipid in messages.get(msgid, 'recipients'): + r[recipid] = 1 + + # figure the author's id, and indicate they've received the + # message + authid = messages.get(msgid, 'author') + + # possibly send the message to the author, as long as they aren't + # anonymous + if (db.config.MESSAGES_TO_AUTHOR == 'yes' and + users.get(authid, 'username') != 'anonymous'): + sendto.append(authid) + r[authid] = 1 + + # now figure the nosy people who weren't recipients + nosy = cl.get(nodeid, 'nosy') + for nosyid in nosy: + # Don't send nosy mail to the anonymous user (that user + # shouldn't appear in the nosy list, but just in case they + # do...) + if users.get(nosyid, 'username') == 'anonymous': + continue + # make sure they haven't seen the message already + if not r.has_key(nosyid): + # send it to them + sendto.append(nosyid) + recipients.append(nosyid) + + # generate a change note + if oldvalues: + note = cl.generateChangeNote(nodeid, oldvalues) + else: + note = cl.generateCreateNote(nodeid) + + # we have new recipients + if sendto: + # filter out the people on vacation + sendto = [i for i in sendto if not users.get(i, 'vacation', 0)] + + # map userids to addresses + sendto = [users.get(i, 'address') for i in sendto] + + # update the message's recipients list + messages.set(msgid, recipients=recipients) + + # send the message + cl.send_message(nodeid, msgid, note, sendto) + except roundupdb.MessageSendError, message: + raise roundupdb.DetectorError, message + + Note that this is the standard nosy reaction code, with the small addition + of:: + + # filter out the people on vacation + sendto = [i for i in sendto if not users.get(i, 'vacation', 0)] + + which filters out the users that have the vacation flag set to true. + + ------------------- Back to `Table of Contents`_ .. _`Table of Contents`: index.html +.. _`design documentation`: design.html diff --git a/doc/design.txt b/doc/design.txt index f5fddba..5d7ac09 100644 --- a/doc/design.txt +++ b/doc/design.txt @@ -1135,34 +1135,29 @@ Displaying Properties ~~~~~~~~~~~~~~~~~~~~~ Properties appear in the user interface in three contexts: -in indices, in editors, and as filters. For each type of +in indices, in editors, and as search filters. For each type of property, there are several display possibilities. For example, in an index view, a string property may just be printed as a plain string, but in an editor view, that property should be displayed in an editable field. The display of a property is handled by functions in -a displayers module. Each function accepts at -least three standard arguments -- the database, class name, -and item id -- and returns a chunk of HTML. +the ``cgi.templating`` module. -Displayer functions are triggered by -tags in templates. The call attribute of the tag -provides a Python expression for calling the displayer -function. The three standard arguments are inserted in -front of the arguments given. For example, the occurrence of:: +Displayer functions are triggered by ``tal:content`` or ``tal:replace`` +tag attributes in templates. The value of the attribute +provides an expression for calling the displayer function. +For example, the occurrence of:: - + tal:content="context/status/plain" in a template triggers a call to:: - plain(db, "issue", 13, "status", max=30) + context['status'].plain() - -when displaying issue 13 in the "issue" class. The displayer +where the context would be an item of the "issue" class. The displayer functions can accept extra arguments to further specify -details about the widgets that should be generated. By defining new -displayer functions, the user interface can be highly customized. +details about the widgets that should be generated. Some of the standard displayer functions include: @@ -1174,30 +1169,19 @@ plain display a String property directly; to omit the time from the date stamp; for a Link or Multilink property, display the key strings of the linked items (or the ids if the linked class has no key property) -field display a property like the - plain displayer above, but in a text field - to be edited -menu for a Link property, display - a menu of the available choices -link for a Link or Multilink property, - display the names of the linked items, hyperlinked to the - issue views on those items -count for a Multilink property, display - a count of the number of links in the list -reldate display a Date property in terms - of an interval relative to the current date (e.g. "+ 3w", "- 2d"). -download show a Link("file") or Multilink("file") - property using links that allow you to download files -checklist for a Link or Multilink property, - display checkboxes for the available choices to permit filtering +field display a property like the plain displayer above, but in a text + field to be edited +menu for a Link property, display a menu of the available choices ========= ==================================================================== -TODO: See the htmltemplate pydoc for a complete list of the functions +See the `customisation`_ documentation for the complete list. Index Views ~~~~~~~~~~~ +XXX The following needs to be clearer + An index view contains two sections: a filter section and an index section. The filter section provides some widgets for selecting @@ -1210,11 +1194,11 @@ Index View Specifiers An index view specifier looks like this (whitespace has been added for clarity):: - /issue?status=unread,in-progress,resolved& - topic=security,ui& - :group=priority& - :sort=-activity& - :filters=status,topic& + /issue?status=unread,in-progress,resolved& + topic=security,ui& + :group=priority& + :sort=-activity& + :filters=status,topic& :columns=title,status,fixer @@ -1256,29 +1240,6 @@ example is the default layout to be provided with the default bug-tracker schema described above in section 4.4. -Filter Section -"""""""""""""" - -The template for a filter section provides the -filtering widgets at the top of the index view. -Fragments enclosed in ``...`` -tags are included or omitted depending on whether the -view specifier requests a filter for a particular property. - -Here's a simple example of a filter template:: - - - - -
- - - -
- - - - Index Section """"""""""""" @@ -1293,15 +1254,9 @@ to display the values of the issue's properties. Here's a simple example of an index template:: - - - - - - - - - + + + Sorting @@ -1340,36 +1295,25 @@ Here's an example of a basic editor template:: - + - - + - - +
- -
- - -
- - -
- +
-As shown in the example, the editor template can also -request the display of a "note" field, which is a -text area for entering a note to go along with a change. +As shown in the example, the editor template can also include a ":note" field, +which is a text area for entering a note to go along with a change. When a change is submitted, the system automatically generates a message describing the changed properties. @@ -1383,7 +1327,7 @@ An example of such a message might be this:: fixer: (none) keywords: parrot,plumage,perch,nailed,dead -If a note is given in the "note" field, the note is +If a note is given in the ":note" field, the note is appended to the description. The message is then added to the issue's message spool (thus triggering the standard detector to react by sending out this message to the nosy list). @@ -1539,25 +1483,16 @@ to perform some action:: # all ok Code in the core will make use of these methods, as should code in auditors in -custom templates. The htmltemplate will implement a new tag, ```` -which has the form:: +custom templates. The HTML templating may access the access controls through +the *user* attribute of the *request* variable. It exposes a ``hasPermission()`` +method:: - - HTML to display if the user has the permission. - - HTML to display if the user does not have the permission. - + tal:condition="python:request.user.hasPermission('Edit', 'issue')" -where: +or, if the *context* is *issue*, then the following is the same:: -- the permission attribute gives a comma-separated list of permission names. - These are checked in turn using ``hasPermission`` and requires one to - be OK. -- the other attributes are lookups on the item using ``hasItemPermission``. If - the attribute value is "$userid" then the current user's userid is tested. + tal:condition="python:request.user.hasPermission('Edit')" -Any of these tests must pass or the ```` check will fail. The section -of html within the side of the ```` that fails is remove from processing. Authentication of Users ~~~~~~~~~~~~~~~~~~~~~~~ @@ -1605,8 +1540,7 @@ system - automated request handlers running various report/escalation scripts privacy - issues that are only visible to some users A new property is added to the issue which marks the user or group of users who are allowed to view and edit the issue. An auditor will check - for edit access, and the htmltemplate tag can check for view - access. + for edit access, and the template user object can check for view access. Deployment Scenarios @@ -1638,5 +1572,13 @@ Changes to this document - Added section Hyperdatabase Implementations - "Item" has been renamed to "Issue" to account for the more specific nature of the Class. +- New Templating +- Access Controls + +------------------ + +Back to `Table of Contents`_ +.. _`Table of Contents`: index.html +.. _customisation: customizing.html diff --git a/doc/developers.txt b/doc/developers.txt index 620d9a6..24f8959 100644 --- a/doc/developers.txt +++ b/doc/developers.txt @@ -2,7 +2,7 @@ Developing Roundup ================== -:Version: $Revision: 1.4 $ +:Version: $Revision: 1.5 $ Note: the intended audience of this document is the developers of the core Roundup code. If you just wish to alter some behaviour of your Roundup @@ -35,6 +35,46 @@ CVS Access To get CVS access, contact richard@users.sourceforge.net. +CVS stuff: + +1. to tag a release (eg. the pre-release of 0.5.0):: + + cvs tag release-0-5-0-pr1 + +1. to make a branch (eg. branching for code freeze/release):: + + cvs co -d maint-0-5 -r release-0-5-0-pr1 + cd maint-0-5 + cvs tag -b maint-0-5 + +2. to check out a branch (eg. the maintenance branch for 0.5.x):: + + cvs co -d maint-0-5 -r maint-0-5 + +3. to merge changes from the maintenance branch to the trunk, in the + directory containing the HEAD checkout:: + + cvs up -j maint-0-5 + +Standard tag names: + +*release-maj-min-patch[-sub]* + Release of the major.minor.patch release, possibly a beta or pre-release, + in which case *sub* will be one of "b*N*" or "pr*N*". +*maint-maj-min* + Maintenance branch for the major.minor release. Patch releases are tagged in + this branch. + +Typically, release happen like this: + +1. work progresses in the HEAD branch until milestones are met, +2. a series of beta releases are tagged in the HEAD until the code is + stable enough to freeze, +3. the pre-release is tagged in the HEAD, with the resultant code branched + to the maintenance branch for that release, +4. bugs in the release are patched in the maintenance branch, and the final + and patch releases are tagged there, and +5. further major work happens in the HEAD. Project Rules ------------- diff --git a/doc/getting_started.txt b/doc/getting_started.txt deleted file mode 100644 index 689967a..0000000 --- a/doc/getting_started.txt +++ /dev/null @@ -1,279 +0,0 @@ -=============== -Getting Started -=============== - -:Version: $Revision: 1.7 $ - -.. contents:: - - -The following instructions assume that you have installed roundup. If you -haven't, you may still proceed - just run the commands as -"``PYTHONPATH=. python roundup/scripts/roundup_admin.py``" for -``roundup-admin`` and -"``PYTHONPATH=. python roundup/scripts/roundup_server.py``" for -``roundup-server``. - -The Tracker ------------ - -We'll be referring to the term tracker a lot from now on. A tracker is a -directory in your filesystem that is where all the information about a live -issue -tracker database is stored. The data that is entered as issues, the users who -access the database and the definition of the database itself all reside there: - -Hyperdatabase - This is the lowest component of Roundup and is where all the issues, - users, file attachments and messages are stored. - -Database schema - This describes the content of the hyperdatabase - what fields are stored - for issues, what user information, etc. Being stored in the tracker, - this allows it to be customised for a particular application. It also - means that changes in the Roundup core code do not affect a running - tracker. - -Web Interface - The web interface templates are defined in the tracker too - and the - actual CGI interface class is defined (mostly using base classes in the - Roundup core code) so it, like the database, may be customised for each - tracker in use. - -Trackers are created using the ``roundup-admin`` tool. - -Command Line Tool ------------------ - -To set up a new tracker, run "``roundup-admin install``". You will be -asked a few questions: - -1. Tracker home directory -2. Schema to use -3. Database back-end to use - -Once you've chosen these, roundup will install the tracker for you. It will -then indicate that you should configure some more information in the -file "``config.py``" in the tracker home. It -should be edited before roundup is initialised, and may have the following -variable declarations: - -MAILHOST - The SMTP mail host that roundup will use to send mail -MAIL_DOMAIN - The domain name used for email addresses -TRACKER_WEB - The web address of the issue tracker's web interface - -The email addresses used by the system by default are: - -TRACKER_EMAIL: ``issue_tracker@MAIL_DOMAIN`` - submissions of issues - -ADMIN_EMAIL: ``roundup-admin@MAIL_DOMAIN`` - roundup's internal use (problems, etc) - -You may also alter the default schema - see the `customisation`_ documentation -for more info on both configuration variables and schema modifications. - -Once you're happy (and note that you can change any of this after the tracker -is initialised too!) you must run "``roundup-admin initialise``". - -You should also think about whether there is going to be controlled access -to the -tracker on the machine the tracker is running on. That is, who can -actually make -changes to the database using the roundup-admin tool. See the section on -Users_and_Access_Control for information on how to secure your tracker from the -start. - -E-Mail Interface ----------------- - -Setup 1: As a mail alias pipe process -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Set up a mail alias called "issue_tracker" as (include the quote marks): -"``|/usr/bin/python /usr/local/bin/roundup-mailgw ``" - -In some installations (e.g. RedHat 6.2 I think) you'll need to set up smrsh so -sendmail will accept the pipe command. In that case, symlink -``/etc/smrsh/roundup-mailgw`` to "``/usr/local/bin/roundup-mailgw``" and change -the command to:: - - |roundup-mailgw - -To test the mail gateway on unix systems, try:: - - echo test |mail -s '[issue] test' issue_tracker@your.domain - - -Setup 2: As a regular cron job using a mailbox source -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Set ``roundup-mailgw`` up to run every 10 minutes or so. For example:: - - 10 * * * * /usr/local/bin/roundup-mailgw mailbox - -Where the ``mail_spool_file`` argument is the location of the roundup submission -user's mail spool. On most systems, the spool for a user "issue_tracker" -will be "``/var/mail/issue_tracker``". - -Setup 3: As a regular cron job using a POP source -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To retrieve from a POP mailbox, use a similar cron entry to the mailbox one:: - - 10 * * * * /usr/local/bin/roundup-mailgw pop - -where pop_spec is "``username:password@server``" that specifies the roundup -submission user's POP account name, password and server. - - -Web Interface -------------- - -This software will work through apache or stand-alone. - -Stand-alone: - 1. Edit roundup-server at the top - ``TRACKER_HOMES`` needs to know - about your tracker. You may also specify the values for - ``TRACKER_HOMES`` on the command-line using "name=home" pairs. - - 2. "``roundup-server [-p port] (name=tracker_home)*``" (hostname may be "") - - 3. Load up the page "``//index``" where tracker name is the name - you nominated in ``TRACKER_HOMES``. - -Apache: - 1. The CGI script is found in the cgi-bin directory of the roundup - distribution. - - 2. Make sure roundup.cgi is executable. Edit it at the top - - ``TRACKER_HOMES`` needs to know about your tracker. - - 3. Edit your "``/etc/httpd/conf/httpd.conf``" and make sure that the - "``/home/httpd/html/roundup/roundup.cgi``" script will be treated as a CGI script. - - 4. Re-start your apache to re-load the config if necessary. - - 5. Load up the page "``/roundup/roundup.cgi/index/``" where tracker name is the - name you nominated in ``TRACKER_HOMES``. - - 6. To use the CGI script unchanged, which allows much easier updates, add - these directives to your "httpd.conf":: - - SetEnv ROUNDUP_LOG "/var/log/roundup.log" - SetEnv TRACKER_HOMES "Default=/usr/local/share/roundup/trackers/Default" - SetEnv ROUNDUP_DEBUG "0" - - 7. On Windows, write a batch file "roundup.bat" similar to the one below and - place it into your cgi-bin directory:: - - @echo off - set ROUNDUP_LOG=c:\Python21\share\roundup\cgi.log - set TRACKER_HOMES=Default=c:\Python21\share\roundup\trackers\Default; - set ROUNDUP_DEBUG=0 - c:\Python21\python.exe c:\Python21\share\roundup\cgi-bin\roundup.cgi - - -Users ------ - -Users and permissions -~~~~~~~~~~~~~~~~~~~~~ - -By default, roundup automatically creates one user when the tracker database is -initialised (using roundup-admin init). The user is "admin" and the password is -the one you supply at that time. - -If users attempt to use roundup in any manner and are not identified to roundup, -they will be using the database in a read-only mode. That is, if roundup doesn't -know who they are, they can't change anything. This has the following -repurcussions: - -Command-line interface - The data modification commands (create, init, retire, set) are performed - as the "admin" user. It is therefore important that the database be - protected by the filesystem if protection is required. On a Unix system, - the easiest and most flexible method of doing so is: - - 1. Add a new user and group to your system (e.g. "issue_tracker") - - 2. When creating a new tracker home, use the following commands - (substituting tracker_home for the directory you want to use):: - - mkdir tracker_home - chown issue_tracker:issue_tracker tracker_home - chmod g+rwxs tracker_home - roundup-admin -i tracker_home init - - 3. Now, edit the /etc/group line for the issue_tracker group so it - includes the unix logins of all the users who are going to - administer your roundup tracker. If you're running the web or mail - gateways, then be sure to include those users in the group too (on - some Linux systems, these users are "www" or "apache" and "mail".) - -E-Mail interface - Users are identified by e-mail address - a new user entry will be created - for any e-mail address that is not recognised, so users are always - identified by roundup. - -Web interface - Unidentified users have read-only access. If the users database has an - entry with the username "anonymous", then unidentified users are - automatically logged in as that user. This gives them write access. - -**anonymous access and the ANONYMOUS_* configurations.** - - -Adding users -~~~~~~~~~~~~ - -To add users, use one of the following interfaces: - -1. On the web, access the URL ...//newuser to bring up a form - which may be used to add a new user. - -2. On the command-line, use:: - - roundup-admin -i create user username=bozo password=bozo - address=richard@clown.org - - Supply the admin username and password. roundup-admin will print the id - of the new user. - -3. Any e-mail sent to roundup from an address that doesn't match an existing - user in the database will result in a new user entry being created for - that user. - - -Issues ------- - -To add issues, use one of the following interfaces: - -1. On the web, access the URL ...//newissue to bring up a - form which may be used to add a new issue. - -2. On the command-line, use:: - - roundup-admin -i create issue title="test issue" - - Supply the admin username and password. roundup-admin will print the id - of the new issue. - -3. Any e-mail sent to roundup with the subject line containing [issue] will - automatically created a new issue in the database using the contents of - the e-mail. - ------------------ - -Back to `Table of Contents`_ - -Next: `User Guide`_ - -.. _`table of contents`: index.html -.. _`user guide`: user_guide.html -.. _`customisation`: customizing.html - diff --git a/doc/index.txt b/doc/index.txt index 4bb87a1..a1b5c09 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -6,7 +6,7 @@ Contents ======== - Overview_ and Features_ -- Installation_ and `Getting Started`_ (and Upgrading_) +- Installation_ and Upgrading_ - `User Guide`_ - `Customising Roundup`_ - `Maintaining Roundup Trackers`_ diff --git a/doc/installation.txt b/doc/installation.txt index 2f14f14..204a3e2 100644 --- a/doc/installation.txt +++ b/doc/installation.txt @@ -2,7 +2,7 @@ Installing Roundup ================== -:Version: $Revision: 1.29 $ +:Version: $Revision: 1.30 $ .. contents:: @@ -117,7 +117,14 @@ Basic Installation Steps Select backend [anydbm]: anydbm You will now be directed to edit the tracker configuration and - initial schema. See `Customising Roundup`_ for details on configuration + initial schema. At a minimum, you must set ``MAILHOST``, + ``TRACKER_WEB``, ``MAIL_DOMAIN`` and ``ADMIN_EMAIL``. If you just want + to get set up to test things quickly, you can even just set the + TRACKER_WEB variable to:: + + TRACKER_WEB = 'http://localhost:8080/support/' + + See `Customising Roundup`_ for details on configuration and schema changes. Note that you may change any of the configuration after you've initialised the tracker - it's just better to have valid values for this stuff now. @@ -131,9 +138,19 @@ Basic Installation Steps Once this is done, the tracker has been created. -At this point, your tracker is set up, but doesn't have a nice user interface. -To set that up, we need to `configure a web interface`_ and optionally -`configure an email interface`_. +3. At this point, your tracker is set up, but doesn't have a nice user + interface. To set that up, we need to `configure a web interface`_ and + optionally `configure an email interface`_. To quickly test the web + interface, assuming ``TRACKER_WEB`` is set to + ``'http://localhost:8080/support/'``:: + + roundup-server -p 8080 support=/opt/roundup/trackers/support + + then direct your web browser at: + + http://locahost:8080/support/ + + and you should see the tracker interface. Choosing Your Template diff --git a/roundup/__init__.py b/roundup/__init__.py index 7f20653..5386a39 100644 --- a/roundup/__init__.py +++ b/roundup/__init__.py @@ -15,9 +15,10 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: __init__.py,v 1.13 2002-09-26 04:19:53 richard Exp $ +# $Id: __init__.py,v 1.14 2002-10-03 06:56:28 richard Exp $ + +''' Roundup - issue tracking for knowledge workers. -__doc__ = ''' This is a simple-to-use and -install issue-tracking system with command-line, web and e-mail interfaces. @@ -28,19 +29,19 @@ other participants. The system will facilitate communication among the participants by managing discussions and notifying interested parties when issues are edited. -Roundup's structure is that of a cake: +Roundup's structure is that of a cake:: - _________________________________________________________________________ -| E-mail Client | Web Browser | Detector Scripts | Shell | -|------------------+-----------------+----------------------+-------------| -| E-mail User | Web User | Detector | Command | -|-------------------------------------------------------------------------| -| Roundup Database Layer | -|-------------------------------------------------------------------------| -| Hyperdatabase Layer | -|-------------------------------------------------------------------------| -| Storage Layer | - ------------------------------------------------------------------------- + _________________________________________________________________________ + | E-mail Client | Web Browser | Detector Scripts | Shell | + |------------------+-----------------+----------------------+-------------| + | E-mail User | Web User | Detector | Command | + |-------------------------------------------------------------------------| + | Roundup Database Layer | + |-------------------------------------------------------------------------| + | Hyperdatabase Layer | + |-------------------------------------------------------------------------| + | Storage Layer | + ------------------------------------------------------------------------- The first layer represents the users (chocolate). The second layer is the Roundup interface to the users (vanilla). @@ -48,10 +49,11 @@ The third and fourth layers are the internal Roundup database storage mechanisms (strawberry). The final, lowest layer is the underlying database storage (rum). -These are implemented in the code in the following manner: +These are implemented in the code in the following manner:: + E-mail User: roundup-mailgw and roundup.mailgw Web User: cgi-bin/roundup.cgi or roundup-server over - roundup.cgi_client, roundup.cgitb and roundup.htmltemplate + roundup.cgi.client and roundup.cgi.template Detector: roundup.roundupdb and templates/