Code

more doc
[roundup.git] / doc / upgrading.txt
1 ======================================
2 Upgrading to newer versions of Roundup
3 ======================================
5 Please read each section carefully and edit your tracker home files
6 accordingly.
8 .. contents::
10 Migrating from 0.4.x to 0.5.0
11 =============================
13 This has been a fairly major revision of Roundup:
15 1. Brand new, much more powerful, flexible, tasty and nutritious templating.
16    Unfortunately, this means all your current templates are useless. Hopefully
17    the new documentation and examples will be enough to help you make the
18    transition. Please don't hesitate to ask on roundup-users for help (or
19    complete conversions if you're completely stuck)!
20 2. The database backed got a lot more flexible, allowing Metakit and SQL
21    databases! The only SQL database implemented at present is gadfly, but
22    others shouldn't be a whole lot more work.
23 3. A brand new, highly flexible and much more robust security system including
24    a system of Permissions, Roles and Role assignments to users. You may now
25    define your own Permissions that may be checked in CGI transactions.
26 4. Journalling has been made less storage-hungry, so has been turned on
27    by default *except* for author, recipient and nosy link/unlink events. You
28    are advised to turn it off in your trackers too.
29 5. We've changed the terminology from "instance" to "tracker", to ease the
30    learning curve/impact for new users.
31 6. Because of the above changes, the tracker configuration has seen some
32    major changes. See below for the details.
34 Please, **back up your database** before you start the migration process. This
35 is as simple as copying the "db" directory and all its contents from your
36 tracker to somewhere safe.
39 0.5.0 Configuration
40 -------------------
42 First up, rename your ``instance_config.py`` file to just ``config.py``.
44 Then edit your tracker's ``__init__.py`` module. It'll currently look
45 like this::
47  from instance_config import *
48  try:
49      from dbinit import *
50  except ImportError:
51      pass # in installdir (probably :)
52  from interfaces import *
54 and it needs to be::
56  import config
57  from dbinit import open, init
58  from interfaces import Client, MailGW
60 Due to the new templating having a top-level ``page`` that defines links for
61 searching, indexes, adding items etc, the following variables are no longer
62 used:
64 - HEADER_INDEX_LINKS
65 - HEADER_ADD_LINKS
66 - HEADER_SEARCH_LINKS
67 - SEARCH_FILTERS
68 - DEFAULT_INDEX
69 - UNASSIGNED_INDEX
70 - USER_INDEX
71 - ISSUE_FILTER
73 The new security implementation will require additions to the dbinit module,
74 but also removes the need for the following tracker config variables:
76 - ANONYMOUS_ACCESS
77 - ANONYMOUS_REGISTER
79 but requires two new variables which define the Roles assigned to users who
80 register through the web and e-mail interfaces:
82 - NEW_WEB_USER_ROLES
83 - NEW_EMAIL_USER_ROLES
85 in both cases, 'User' is a good initial setting. To emulate
86 ``ANONYMOUS_ACCESS='deny'``, remove all "View" Permissions from the
87 "Anonymous" Role. To emulate ``ANONYMOUS_REGISTER='deny'``, remove the "Web
88 Registration" and/or the "Email Registration" Permission from the "Anonymous"
89 Role. See the section on customising security in the `customisation
90 documentation`_ for more information.
93 0.5.0 Schema Specification
94 --------------------------
96 0.5.0 Database backend changes
97 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99 Your select_db module in your tracker has changed a fair bit. Where it used
100 to contain::
102  # WARNING: DO NOT EDIT THIS FILE!!!
103  from roundup.backends.back_anydbm import Database
105 it must now contain::
107  # WARNING: DO NOT EDIT THIS FILE!!!
108  from roundup.backends.back_anydbm import Database, Class, FileClass, IssueClass
110 Yes, I realise the irony of the "DO NOT EDIT THIS FILE" statement :)
111 Note the addition of the Class, FileClass, IssueClass imports. These are very
112 important, as they're going to make the next change work too. You now need to
113 modify the top of the dbinit module in your tracker from::
115  import instance_config
116  from roundup import roundupdb
117  from select_db import Database
119  from roundup.roundupdb import Class, FileClass
121  class Database(roundupdb.Database, select_db.Database):
122      ''' Creates a hybrid database from:
123           . the selected database back-end from select_db
124           . the roundup extensions from roundupdb
125      '''
126      pass
128  class IssueClass(roundupdb.IssueClass):
129      ''' issues need the email information
130      '''
131      pass
133 to::
135  import config
136  from select_db import Database, Class, FileClass, IssueClass
138 Yes, remove the Database and IssueClass definitions and those other imports.
139 They're not needed any more!
141 Look for places in dbinit.py where ``instance_config`` is used too, and
142 rename them ``config``.
145 0.5.0 Journalling changes
146 ~~~~~~~~~~~~~~~~~~~~~~~~~
148 Journalling has been optimised for storage. Journalling of links has been
149 turned back on by default. If your tracker has a large user base, you may wish
150 to turn off journalling of nosy list, message author and message recipient
151 link and unlink events. You do this by adding ``do_journal='no'`` to the Class
152 initialisation in your dbinit. For example, your *msg* class initialisation
153 probably looks like this::
155     msg = FileClass(db, "msg",
156                     author=Link("user"), recipients=Multilink("user"),
157                     date=Date(),         summary=String(),
158                     files=Multilink("file"),
159                     messageid=String(),  inreplyto=String())
161 to turn off journalling of author and recipient link events, add
162 ``do_journal='no'`` to the ``author=Link("user")`` part of the statement,
163 like so::
165     msg = FileClass(db, "msg",
166                     author=Link("user", do_journal='no'),
167                     recipients=Multilink("user", do_journal='no'),
168                     date=Date(),         summary=String(),
169                     files=Multilink("file"),
170                     messageid=String(),  inreplyto=String())
172 Nosy list link event journalling is actually turned off by default now. If you
173 want to turn it onn, change to your issue class' nosy list, change its
174 definition from::
176     issue = IssueClass(db, "issue",
177                     assignedto=Link("user"), topic=Multilink("keyword"),
178                     priority=Link("priority"), status=Link("status"))
180 to::
182     issue = IssueClass(db, "issue", nosy=Multilink("user", do_journal='yes'),
183                     assignedto=Link("user"), topic=Multilink("keyword"),
184                     priority=Link("priority"), status=Link("status"))
186 noting that your definition of the nosy Multilink will override the normal one.
189 0.5.0 User schema changes
190 ~~~~~~~~~~~~~~~~~~~~~~~~~
192 Users have two more properties, "queries" and "roles". You'll have something
193 like this in your dbinit module now::
195     user = Class(db, "user",
196                     username=String(),   password=Password(),
197                     address=String(),    realname=String(),
198                     phone=String(),      organisation=String(),
199                     alternate_addresses=String())
200     user.setkey("username")
202 and you'll need to add the new properties and the new "query" class to it
203 like so::
205     query = Class(db, "query",
206                     klass=String(),     name=String(),
207                     url=String())
208     query.setkey("name")
210     # Note: roles is a comma-separated string of Role names
211     user = Class(db, "user",
212                     username=String(),   password=Password(),
213                     address=String(),    realname=String(),
214                     phone=String(),      organisation=String(),
215                     alternate_addresses=String(),
216                     queries=Multilink('query'), roles=String())
217     user.setkey("username")
219 The "queries" property is used to store off the user's favourite database
220 queries. The "roles" property is explained below in `0.5.0 Security
221 Settings`_.
224 0.5.0 Security Settings
225 ~~~~~~~~~~~~~~~~~~~~~~~
227 See the `security documentation`_ for an explanation of how the new security
228 system works. In a nutshell though, the security is handled as a four step
229 process:
231 1. Permissions are defined as having a name and optionally a hyperdb class
232    they're specific to,
233 2. Roles are defined that have one or more Permissions,
234 3. Users are assigned Roles in their "roles" property, and finally
235 4. Roundup checks that users have appropriate Permissions at appropriate times
236    (like editing issues).
238 Your tracker dbinit module's *open* function now has to define any
239 Permissions that are specific to your tracker, and also the assignment
240 of Permissions to Roles. At the moment, your open function
241 ends with::
243     import detectors
244     detectors.init(db)
246     return db
248 and what we need to do is insert some commands that will set up the security
249 parameters. Right above the ``import detectors`` line, you'll want to insert
250 these lines::
252     #
253     # SECURITY SETTINGS
254     #
255     # new permissions for this schema
256     for cl in 'issue', 'file', 'msg', 'user':
257         db.security.addPermission(name="Edit", klass=cl,
258             description="User is allowed to edit "+cl)
259         db.security.addPermission(name="View", klass=cl,
260             description="User is allowed to access "+cl)
262     # Assign the access and edit permissions for issue, file and message
263     # to regular users now
264     for cl in 'issue', 'file', 'msg':
265         p = db.security.getPermission('View', cl)
266         db.security.addPermissionToRole('User', p)
267         p = db.security.getPermission('Edit', cl)
268         db.security.addPermissionToRole('User', p)
269     # and give the regular users access to the web and email interface
270     p = db.security.getPermission('Web Access')
271     db.security.addPermissionToRole('User', p)
272     p = db.security.getPermission('Email Access')
273     db.security.addPermissionToRole('User', p)
275     # May users view other user information? Comment these lines out
276     # if you don't want them to
277     p = db.security.getPermission('View', 'user')
278     db.security.addPermissionToRole('User', p)
280     # Assign the appropriate permissions to the anonymous user's Anonymous
281     # Role. Choices here are:
282     # - Allow anonymous users to register through the web
283     p = db.security.getPermission('Web Registration')
284     db.security.addPermissionToRole('Anonymous', p)
285     # - Allow anonymous (new) users to register through the email gateway
286     p = db.security.getPermission('Email Registration')
287     db.security.addPermissionToRole('Anonymous', p)
288     # - Allow anonymous users access to the "issue" class of data
289     #   Note: this also grants access to related information like files,
290     #         messages, statuses etc that are linked to issues
291     #p = db.security.getPermission('View', 'issue')
292     #db.security.addPermissionToRole('Anonymous', p)
293     # - Allow anonymous users access to edit the "issue" class of data
294     #   Note: this also grants access to create related information like
295     #         files and messages etc that are linked to issues
296     #p = db.security.getPermission('Edit', 'issue')
297     #db.security.addPermissionToRole('Anonymous', p)
299     # oh, g'wan, let anonymous access the web interface too
300     p = db.security.getPermission('Web Access')
301     db.security.addPermissionToRole('Anonymous', p)
303 Note in the comments there the places where you might change the permissions
304 to restrict users or grant users more access. If you've created additional
305 classes that users should be able to edit and view, then you should add them
306 to the "new permissions for this schema" section at the start of the security
307 block. Then add them to the "Assign the access and edit permissions" section
308 too, so people actually have the new Permission you've created.
310 One final change is needed that finishes off the security system's
311 initialisation. We need to add a call to ``db.post_init()`` at the end of the
312 dbinit open() function. Add it like this::
314     import detectors
315     detectors.init(db)
317     # schema is set up - run any post-initialisation
318     db.post_init()
319     return db
321 You may verify the setup of Permissions and Roles using the new
322 "``roundup-admin security``" command.
325 0.5.0 User changes
326 ~~~~~~~~~~~~~~~~~~
328 To support all those schema changes, you'll need to massage your user database
329 a little too, to:
331 1. make sure there's an "anonymous" user - this user is mandatory now and is
332    the one that unknown users are logged in as.
333 2. make sure all users have at least one Role.
335 If you don't have the "anonymous" user, create it now with the command::
337   roundup-admin create user username=anonymous roles=Anonymous
339 making sure the capitalisation is the same as above. Once you've done that,
340 you'll need to set the roles property on all users to a reasonable default.
341 The admin user should get "Admin", the anonymous user "Anonymous"
342 and all other users "User". The ``fixroles.py`` script in the tools directory
343 will do this. Run it like so (where python is your python 2+ binary)::
345   python tools/fixroles.py -i <tracker home>
349 0.5.0 CGI interface changes
350 ---------------------------
352 The CGI interface code was completely reorganised and largely rewritten. The
353 end result is that this section of your tracker interfaces module will need
354 changing from::
356  from roundup import mailgw
357  from roundup.cgi import client
358  
359  class Client(client.Client): 
360      ''' derives basic CGI implementation from the standard module,
361          with any specific extensions
362      '''
363      pass
365 to::
367  from roundup import cgi_client, mailgw
368  from roundup.i18n import _
369  
370  class Client(cgi_client.Client):
371      ''' derives basic CGI implementation from the standard module,
372          with any specific extensions
373      '''
374      pass
376 You will also need to install the new version of roundup.cgi from the source
377 cgi-bin directory if you're using it.
380 0.5.0 HTML templating
381 ---------------------
383 You'll want to make a backup of your current tracker html directory. You
384 should then copy the html directory from the Roundup source "classic" template
385 and modify it according to your local schema changes.
387 If you need help with the new templating system, please ask questions on the
388 roundup-users mailing list (available through the roundup project page on
389 sourceforge, http://roundup.sf.net/)
392 0.5.0 Detectors
393 ---------------
395 The nosy reactor has been updated to handle the tracker not having an
396 "assignedto" property on issues. You may want to copy it into your tracker's
397 detectors directory. Chances are you've already fixed it though :)
400 Migrating from 0.4.1 to 0.4.2
401 =============================
403 0.4.2 Configuration
404 -------------------
405 The USER_INDEX definition introduced in 0.4.1 was too restrictive in its
406 allowing replacement of 'assignedto' with the user's userid. Users must change
407 the None value of 'assignedto' to 'CURRENT USER' (the string, in quotes) for
408 the replacement behaviour to occur now.
410 The new configuration variables are:
412 - EMAIL_KEEP_QUOTED_TEXT 
413 - EMAIL_LEAVE_BODY_UNCHANGED
414 - ADD_RECIPIENTS_TO_NOSY
416 See the sample configuration files in::
418  <roundup source>/roundup/templates/classic/instance_config.py
420 and::
422  <roundup source>/roundup/templates/extended/instance_config.py
424 and the `customisation documentation`_ for information on how they're used.
427 0.4.2 Changes to detectors
428 --------------------------
429 You will need to copy the detectors from the distribution into your instance
430 home "detectors" directory. If you used the classic schema, the detectors
431 are in::
433  <roundup source>/roundup/templates/classic/detectors/
435 If you used the extended schema, the detectors are in::
437  <roundup source>/roundup/templates/extended/detectors/
439 The change means that schema-specific code has been removed from the
440 mail gateway and cgi interface and made into auditors:
442 - nosyreactor.py has now got an updatenosy auditor which updates the nosy
443   list with author, recipient and assignedto information.
444 - statusauditor.py makes the unread or resolved -> chatting changes and
445   presets the status of an issue to unread.
447 There's also a bug or two fixed in the nosyreactor code.
449 0.4.2 HTML templating changes
450 -----------------------------
451 The link() htmltemplate function now has a "showid" option for links and
452 multilinks. When true, it only displays the linked item id as the anchor
453 text. The link value is displayed as a tooltip using the title anchor
454 attribute. To use in eg. the superseder field, have something like this::
456    <td>
457     <display call="field('superseder', showid=1)">
458     <display call="classhelp('issue', 'id,title', label='list', width=500)">
459     <property name="superseder">
460      <br>View: <display call="link('superseder', showid=1)">
461     </property>
462    </td>
464 The stylesheets have been cleaned up too. You may want to use the newer
465 versions in::
467  <roundup source>/roundup/templates/<template>/html/default.css
471 Migrating from 0.4.0 to 0.4.1
472 =============================
474 0.4.1 Files storage
475 -------------------
477 Messages and files from newly created issues will be put into subdierectories
478 in thousands e.g. msg123 will be put into files/msg/0/msg123, file2003
479 will go into files/file/2/file2003. Previous messages are still found, but
480 could be put into this structure.
482 0.4.1 Configuration
483 -------------------
485 To allow more fine-grained access control, the variable used to check
486 permission to auto-register users in the mail gateway is now called
487 ANONYMOUS_REGISTER_MAIL rather than overloading ANONYMOUS_REGISTER. If the
488 variable doesn't exist, then ANONYMOUS_REGISTER is tested as before.
490 Configuring the links in the web header is now easier too. The following
491 variables have been added to the classic instance_config.py::
493   HEADER_INDEX_LINKS   - defines the "index" links to be made available
494   HEADER_ADD_LINKS     - defines the "add" links
495   DEFAULT_INDEX        - specifies the index view for DEFAULT
496   UNASSIGNED_INDEX     - specifies the index view for UNASSIGNED
497   USER_INDEX           - specifies the index view for USER
499 See the <roundup source>/roundup/templates/classic/instance_config.py for more
500 information - including how the variables are to be set up. Most users will
501 just be able to copy the variables from the source to their instance home. If
502 you've modified the header by changing the source of the interfaces.py file in
503 the instance home, you'll need to remove that customisation and move it into
504 the appropriate variables in instance_config.py.
506 The extended schema has similar variables added too - see the source for more
507 info.
509 0.4.1 Alternate E-Mail Addresses
510 --------------------------------
512 If you add the property "alternate_addresses" to your user class, your users
513 will be able to register alternate email addresses that they may use to
514 communicate with roundup as. All email from roundup will continue to be sent
515 to their primary address.
517 If you have not edited the dbinit.py file in your instance home directory,
518 you may simply copy the new dbinit.py file from the core code. If you used
519 the classic schema, the interfaces file is in::
521  <roundup source>/roundup/templates/classic/dbinit.py
523 If you used the extended schema, the file is in::
525  <roundup source>/roundup/templates/extended/dbinit.py 
527 If you have modified your dbinit.py file, you need to edit the dbinit.py
528 file in your instance home directory. Find the lines which define the user
529 class::
531     user = Class(db, "msg",
532                     username=String(),   password=Password(),
533                     address=String(),    realname=String(), 
534                     phone=String(),      organisation=String(),
535                     alternate_addresses=String())
537 You will also want to add the property to the user's details page. The
538 template for this is the "user.item" file in your instance home "html"
539 directory. Similar to above, you may copy the file from the roundup source if
540 you haven't modified it. Otherwise, add the following to the template::
542    <display call="multiline('alternate_addresses')">
544 with appropriate labelling etc. See the standard template for an idea.
548 Migrating from 0.3.x to 0.4.0
549 =============================
551 0.4.0 Message-ID and In-Reply-To addition
552 -----------------------------------------
553 0.4.0 adds the tracking of messages by message-id and allows threading
554 using in-reply-to. Most e-mail clients support threading using this
555 feature, and we hope to add support for it to the web gateway. If you
556 have not edited the dbinit.py file in your instance home directory, you may
557 simply copy the new dbinit.py file from the core code. If you used the
558 classic schema, the interfaces file is in::
560  <roundup source>/roundup/templates/classic/dbinit.py
562 If you used the extended schema, the file is in::
564  <roundup source>/roundup/templates/extended/dbinit.py 
566 If you have modified your dbinit.py file, you need to edit the dbinit.py
567 file in your instance home directory. Find the lines which define the msg
568 class::
570     msg = FileClass(db, "msg",
571                     author=Link("user"), recipients=Multilink("user"),
572                     date=Date(),         summary=String(),
573                     files=Multilink("file"))
575 and add the messageid and inreplyto properties like so::
577     msg = FileClass(db, "msg",
578                     author=Link("user"), recipients=Multilink("user"),
579                     date=Date(),         summary=String(),
580                     files=Multilink("file"),
581                     messageid=String(),  inreplyto=String())
583 Also, configuration is being cleaned up. This means that your dbinit.py will
584 also need to be changed in the open function. If you haven't changed your
585 dbinit.py, the above copy will be enough. If you have, you'll need to change
586 the line (round line 50)::
588     db = Database(instance_config.DATABASE, name)
590 to::
592     db = Database(instance_config, name)
595 0.4.0 Configuration
596 --------------------
597 ``INSTANCE_NAME`` and ``EMAIL_SIGNATURE_POSITION`` have been added to the
598 instance_config.py. The simplest solution is to copy the default values
599 from template in the core source.
601 The mail gateway now checks ``ANONYMOUS_REGISTER`` to see if unknown users
602 are to be automatically registered with the tracker. If it is set to "deny"
603 then unknown users will not have access. If it is set to "allow" they will be
604 automatically registered with the tracker.
607 0.4.0 CGI script roundup.cgi
608 ----------------------------
609 The CGI script has been updated with some features and a bugfix, so you should
610 copy it from the roundup cgi-bin source directory again. Make sure you update
611 the ROUNDUP_INSTANCE_HOMES after the copy.
614 0.4.0 Nosy reactor
615 ------------------
616 The nosy reactor has also changed - copy the nosyreactor.py file from the core
617 source::
619    <roundup source>/roundup/templates/<template>/detectors/nosyreactor.py
621 to your instance home "detectors" directory.
624 0.4.0 HTML templating
625 ---------------------
626 The field() function was incorrectly implemented - links and multilinks now
627 display as text fields when rendered using field(). To display a menu (drop-
628 down or select box) you need to use the menu() function.
632 Migrating from 0.2.x to 0.3.x
633 =============================
635 0.3.x Cookie Authentication changes
636 -----------------------------------
637 0.3.0 introduces cookie authentication - you will need to copy the
638 interfaces.py file from the roundup source to your instance home to enable
639 authentication. If you used the classic schema, the interfaces file is in::
641  <roundup source>/roundup/templates/classic/interfaces.py
643 If you used the extended schema, the file is in::
645  <roundup source>/roundup/templates/extended/interfaces.py
647 If you have modified your interfaces.Client class, you will need to take
648 note of the login/logout functionality provided in roundup.cgi_client.Client
649 (classic schema) or roundup.cgi_client.ExtendedClient (extended schema) and
650 modify your instance code apropriately.
653 0.3.x Password encoding
654 -----------------------
655 This release also introduces encoding of passwords in the database. If you
656 have not edited the dbinit.py file in your instance home directory, you may
657 simply copy the new dbinit.py file from the core code. If you used the
658 classic schema, the interfaces file is in::
660  <roundup source>/roundup/templates/classic/dbinit.py
662 If you used the extended schema, the file is in::
664  <roundup source>/roundup/templates/extended/dbinit.py
667 If you have modified your dbinit.py file, you may use encoded passwords:
669 1. Edit the dbinit.py file in your instance home directory
670    a. At the first code line of the open() function::
672        from roundup.hyperdb import String, Date, Link, Multilink
674       alter to include Password, as so::
676        from roundup.hyperdb import String, Password, Date, Link, Multilink
678    b. Where the password property is defined (around line 66)::
680        user = Class(db, "user", 
681                        username=String(),   password=String(),
682                        address=String(),    realname=String(), 
683                        phone=String(),      organisation=String())
684        user.setkey("username")
686       alter the "password=String()" to "password=Password()"::
688        user = Class(db, "user", 
689                        username=String(),   password=Password(),
690                        address=String(),    realname=String(), 
691                        phone=String(),      organisation=String())
692        user.setkey("username")
694 2. Any existing passwords in the database will remain cleartext until they
695    are edited. It is recommended that at a minimum the admin password be
696    changed immediately::
698       roundup-admin -i <instance home> set user1 password=<new password>
701 0.3.x Configuration
702 -------------------
703 FILTER_POSITION, ANONYMOUS_ACCESS, ANONYMOUS_REGISTER have been added to
704 the instance_config.py. Simplest solution is to copy the default values from
705 template in the core source.
707 MESSAGES_TO_AUTHOR has been added to the IssueClass in dbinit.py. Set to 'yes'
708 to send nosy messages to the author. Default behaviour is to not send nosy
709 messages to the author. You will need to add MESSAGES_TO_AUTHOR to your
710 dbinit.py in your instance home.
713 0.3.x CGI script roundup.cgi
714 ----------------------------
715 There have been some structural changes to the roundup.cgi script - you will
716 need to install it again from the cgi-bin directory of the source
717 distribution. Make sure you update the ROUNDUP_INSTANCE_HOMES after the
718 copy.
721 .. _`customisation documentation`: customizing.html
722 .. _`security documentation`: security.html