Code

Proper handling of 'Create' permissions in both mail gateway (earlier
[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. Note that there is information about upgrade procedures in the
7 `administration guide`_.
9 If a specific version transition isn't mentioned here (eg. 0.6.7 to 0.6.8)
10 then you don't need to do anything. If you're upgrading from 0.5.6 to
11 0.6.8 though, you'll need to check the "0.5 to 0.6" and "0.6.x to 0.6.3"
12 steps.
14 .. contents::
16 Migrating from 1.4.x to 1.4.12
17 ==============================
19 Item creation now checks the "Create" permission instead of the "Edit"
20 permission for individual properties. If you have modified your tracker
21 permissions from the default distribution, you should check that
22 "Create" permissions exist for all properties you want users to be able
23 to create.
25 Migrating from 1.4.x to 1.4.11
26 ==============================
28 Close poential security hole
29 ----------------------------
31 If your tracker has untrusted users you should examine its ``schema.py``
32 file and look for the section granting the "Edit" permission to your users.
33 This should look something like::
35     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
36         description="User is allowed to edit their own user details")
38 and should be modified to restrict the list of properties they are allowed
39 to edit by adding the ``properties=`` section like::
41     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
42         properties=('username', 'password', 'address', 'realname', 'phone',
43             'organisation', 'alternate_addresses', 'queries', 'timezone'),
44         description="User is allowed to edit their own user details")
46 Most importantly the "roles" property should not be editable - thus not
47 appear in that list of properties.
50 Grant the "Register" permission to the Anonymous role
51 -----------------------------------------------------
53 A separate "Register" permission has been introduced to allow
54 anonymous users to register. This means you will need to add the
55 following to your tracker's ``schema.py`` to add the permission and
56 assign it to the Anonymous role (replacing any previously assigned
57 "Create user" permission for the Anonymous role):
59   +db.security.addPermission(name='Register', klass='user',
60   +                          description='User is allowed to register new user')
61  
62    # Assign the appropriate permissions to the anonymous user's Anonymous
63    # Role. Choices here are:
64    # - Allow anonymous users to register
65   -db.security.addPermissionToRole('Anonymous', 'Create', 'user')
66   +db.security.addPermissionToRole('Anonymous', 'Register', 'user')
68 The lines marked "+" should be added and lines marked "-" should be
69 deleted (minus the "+"/"-" signs).
72 Migrating from 1.4.x to 1.4.9
73 =============================
75 Customized MailGW Class
76 -----------------------
78 If you have customized the MailGW class in your tracker: The new MailGW
79 class opens the database for each message in the method handle_message
80 (instance.open) instead of passing the opened database as a parameter to
81 the MailGW constructor. The old handle_message has been renamed to
82 _handle_message. The new method opens the database and wraps the call to
83 the old method into a try/finally.
85 Your customized MailGW class needs to mirror this behavior.
87 Fix the "remove" button in issue files and messages lists
88 ---------------------------------------------------------
90 The "remove" button(s) in the issue messages list needs to be altered. Find
91 the following in your tracker's ``html/issue.item.html`` template::
93   <td>
94    <form style="padding:0" tal:condition="context/is_edit_ok"
95          tal:attributes="action string:issue${context/id}">
96     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
98 and add ``method="POST"`` as shown below::
100   <td>
101    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
102          tal:attributes="action string:issue${context/id}">
103     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
105 Then also find::
107   <td>
108    <form style="padding:0" tal:condition="context/is_edit_ok"
109          tal:attributes="action string:issue${context/id}">
110     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
112 and add ``method="POST"`` as shown below::
114   <td>
115    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
116          tal:attributes="action string:issue${context/id}">
117     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
120 Fixing the "retire" button in user management list
121 --------------------------------------------------
123 If you made the change to the "reture" link in the user management list as
124 listed below in `Migrating from 1.4.x to 1.4.7`_ then you'll need to fix that
125 change by adding ``method="POST"`` to the ``<form>`` tag::
127      <form style="padding:0" method="POST"
128            tal:attributes="action string:user${user/id}">
129       <input type="hidden" name="@template" value="index">
130       <input type="hidden" name="@action" value="retire">
131       <input type="submit" value="retire" i18n:attributes="value">
132      </form>
135 Migrating from 1.4.x to 1.4.7
136 =============================
138 Several security issues were addressed in this release. Some aspects of your
139 trackers may no longer function depending on your local customisations. Core
140 functionality that will need to be modified:
142 Grant the "retire" permission to users for their queries
143 --------------------------------------------------------
145 Users will no longer be able to retire their own queries. To remedy this you
146 will need to add the following to your tracker's ``schema.py`` just under the
147 line that grants them permission to edit their own queries::
149    p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
150       description="User is allowed to edit their queries")
151    db.security.addPermissionToRole('User', p)
152  + p = db.security.addPermission(name='Retire', klass='query', check=edit_query,
153  +    description="User is allowed to retire their queries")
154  + db.security.addPermissionToRole('User', p)
155    p = db.security.addPermission(name='Create', klass='query',
156       description="User is allowed to create queries")
157    db.security.addPermissionToRole('User', p)
159 The lines marked "+" should be added, minus the "+" sign.
162 Fix the "retire" link in the users list for admin users
163 -------------------------------------------------------
165 The "retire" link found in the file ``html/users.index.html``::
167   <td tal:condition="context/is_edit_ok">
168    <a tal:attributes="href string:user${user/id}?@action=retire&@template=index"
169     i18n:translate="">retire</a>
171 Should be replaced with::
173   <td tal:condition="context/is_retire_ok">
174      <form style="padding:0" method="POST"
175            tal:attributes="action string:user${user/id}">
176       <input type="hidden" name="@template" value="index">
177       <input type="hidden" name="@action" value="retire">
178       <input type="submit" value="retire" i18n:attributes="value">
179      </form>
182 Fix for Python 2.6+ users
183 -------------------------
185 If you use Python 2.6 you should edit your tracker's
186 ``detectors/nosyreaction.py`` file to change::
188    import sets
190 at the top to::
192    from roundup.anypy.sets_ import set
194 and then all instances of ``sets.Set()`` to ``set()`` in the later code.
198 Trackers currently allowing HTML file uploading
199 -----------------------------------------------
201 Trackers which wish to continue to allow uploading of HTML content against issues
202 will need to set a new configuration variable in the ``[web]`` section of the
203 tracker's ``config.ini`` file:
205    # Setting this option enables Roundup to serve uploaded HTML
206    # file content *as HTML*. This is a potential security risk
207    # and is therefore disabled by default. Set to 'yes' if you
208    # trust *all* users uploading content to your tracker.
209    # Allowed values: yes, no
210    # Default: no
211    allow_html_file = no
215 Migrating from 1.4.2 to 1.4.3
216 =============================
218 If you are using the MySQL backend you will need to replace some indexes
219 that may have been created by version 1.4.2.
221 You should to access your MySQL database directly and remove any indexes
222 with a name ending in "_key_retired_idx". You should then re-add them with
223 the same spec except the key column name needs a size. So an index on
224 "_user (__retired, _name)" should become "_user (__retired, _name(255))".
227 Migrating from 1.4.x to 1.4.2
228 =============================
230 You should run the "roundup-admin migrate" command for your tracker once
231 you've installed the latest codebase. 
233 Do this before you use the web, command-line or mail interface and before
234 any users access the tracker.
236 This command will respond with either "Tracker updated" (if you've not
237 previously run it on an RDBMS backend) or "No migration action required"
238 (if you have run it, or have used another interface to the tracker,
239 or are using anydbm).
241 It's safe to run this even if it's not required, so just get into the
242 habit.
245 Migrating from 1.3.3 to 1.4.0
246 =============================
248 Value of the "refwd_re" tracker configuration option (section "mailgw")
249 is treated as UTF-8 string.  In previous versions, it was ISO8859-1.
251 If you have running trackers based on the classic template, please
252 update the messagesummary detector as follows::
254     --- detectors/messagesummary.py 17 Apr 2003 03:26:38 -0000      1.1
255     +++ detectors/messagesummary.py 3 Apr 2007 06:47:21 -0000       1.2
256     @@ -8,7 +8,7 @@
257      if newvalues.has_key('summary') or not newvalues.has_key('content'):
258          return
260     -    summary, content = parseContent(newvalues['content'], 1, 1)
261     +    summary, content = parseContent(newvalues['content'], config=db.config)
262      newvalues['summary'] = summary
264 In the latest version we have added some database indexes to the
265 SQL-backends (mysql, postgresql, sqlite) for speeding up building the
266 roundup-index for full-text search. We recommend that you create the
267 following database indexes on the database by hand::
269  CREATE INDEX words_by_id ON __words (_textid)
270  CREATE UNIQUE INDEX __textids_by_props ON __textids (_class, _itemid, _prop)
272 Migrating from 1.2.x to 1.3.0
273 =============================
275 1.3.0 Web interface changes
276 ---------------------------
278 Some of the HTML files in the "classic" and "minimal" tracker templates
279 were changed to fix some bugs and clean them up. You may wish to compare
280 them to the HTML files in your tracker and apply any changes.
283 Migrating from 1.1.2 to 1.2.0
284 =============================
286 1.2.0 Sorting and grouping by multiple properties
287 -------------------------------------------------
289 Starting with this version, sorting and grouping by multiple properties
290 is possible. This means that request.sort and request.group are now
291 lists. This is reflected in several places:
293  * ``renderWith`` now has list attributes for ``sort`` and ``group``,
294    where you previously wrote::
295    
296     renderWith(... sort=('-', 'activity'), group=('+', 'priority')
298    you write now::
300     renderWith(... sort=[('-', 'activity')], group=[('+', 'priority')]
302  * In templates that permit to edit sorting/grouping, request.sort and
303    request.group are (possibly empty) lists. You can now sort and group
304    by multiple attributes. For an example, see the classic template. You
305    may want search for the variable ``n_sort`` which can be set to the
306    number of sort/group properties.
308  * Templates that diplay new headlines for each group of items with
309    equal group properties can now use the modified ``batch.propchanged``
310    method that can take several properties which are checked for
311    changes. See the example in the classic template which makes use of
312    ``batch.propchanged``.
314 Migrating from 1.1.0 to 1.1.1
315 =============================
317 1.1.1 "Clear this message"
318 --------------------------
320 In 1.1.1, the standard ``page.html`` template includes a "clear this message"
321 link in the green "ok" message bar that appears after a successful edit
322 (or other) action.
324 To include this in your tracker, change the following in your ``page.html``
325 template::
327  <p tal:condition="options/ok_message | nothing" class="ok-message"
328     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
330 to be::
332  <p tal:condition="options/ok_message | nothing" class="ok-message">
333    <span tal:repeat="m options/ok_message"
334       tal:content="structure string:$m <br/ > " />
335     <a class="form-small" tal:attributes="href request/current_url"
336        i18n:translate="">clear this message</a>
337  </p>
340 If you implemented the "clear this message" in your 1.1.0 tracker, then you
341 should change it to the above and it will work much better!
344 Migrating from 1.0.x to 1.1.0
345 =============================
347 1.1 Login "For Session Only"
348 ----------------------------
350 In 1.1, web logins are alive for the length of a session only, *unless* you
351 add the following to the login form in your tracker's ``page.html``::
353     <input type="checkbox" name="remember" id="remember">
354     <label for="remember" i18n:translate="">Remember me?</label><br>
356 See the classic tracker ``page.html`` if you're unsure where this should
357 go.
360 1.1 Query Display Name
361 ----------------------
363 The ``dispname`` web variable has been renamed ``@dispname`` to avoid
364 clashing with other variables of the same name. If you are using the
365 display name feature, you will need to edit your tracker's ``page.html``
366 and ``issue.index.html`` pages to change ``dispname`` to ``@dispname``.
368 A side-effect of this change is that the renderWith method used in the
369 ``home.html`` page may now take a dispname argument.
372 1.1 "Clear this message"
373 ------------------------
375 In 1.1, the standard ``page.html`` template includes a "clear this message"
376 link in the green "ok" message bar that appears after a successful edit
377 (or other) action.
379 To include this in your tracker, change the following in your ``page.html``
380 template::
382  <p tal:condition="options/ok_message | nothing" class="ok-message"
383     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
385 to be::
387  <p tal:condition="options/ok_message | nothing" class="ok-message">
388    <span tal:repeat="m options/ok_message"
389       tal:content="structure string:$m <br/ > " />
390     <a class="form-small" tal:attributes="href string:issue${context/id}"
391        i18n:translate="">clear this message</a>
392  </p>
395 Migrating from 0.8.x to 1.0
396 ===========================
398 1.0 New Query Permissions
399 -------------------------
401 New permissions are defined for query editing and viewing. To include these
402 in your tracker, you need to add these lines to your tracker's
403 ``schema.py``::
405  # Users should be able to edit and view their own queries. They should also
406  # be able to view any marked as not private. They should not be able to
407  # edit others' queries, even if they're not private
408  def view_query(db, userid, itemid):
409      private_for = db.query.get(itemid, 'private_for')
410      if not private_for: return True
411      return userid == private_for
412  def edit_query(db, userid, itemid):
413      return userid == db.query.get(itemid, 'creator')
414  p = db.security.addPermission(name='View', klass='query', check=view_query,
415      description="User is allowed to view their own and public queries")
416  db.security.addPermissionToRole('User', p)
417  p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
418      description="User is allowed to edit their queries")
419  db.security.addPermissionToRole('User', p)
420  p = db.security.addPermission(name='Create', klass='query',
421      description="User is allowed to create queries")
422  db.security.addPermissionToRole('User', p)
424 and then remove 'query' from the line::
426  # Assign the access and edit Permissions for issue, file and message
427  # to regular users now
428  for cl in 'issue', 'file', 'msg', 'query', 'keyword':
430 so it looks like::
432  for cl in 'issue', 'file', 'msg', 'keyword':
435 Migrating from 0.8.0 to 0.8.3
436 =============================
438 0.8.3 Nosy Handling Changes
439 ---------------------------
441 A change was made to fix a bug in the ``nosyreaction.py`` standard
442 detector. To incorporate this fix in your trackers, you will need to copy
443 the ``nosyreaction.py`` file from the ``templates/classic/detectors``
444 directory of the source to your tracker's ``templates`` directory.
446 If you have modified the ``nosyreaction.py`` file from the standard
447 version, you will need to roll your changes into the new file.
450 Migrating from 0.7.1 to 0.8.0
451 =============================
453 You *must* fully uninstall previous Roundup version before installing
454 Roundup 0.8.0.  If you don't do that, ``roundup-admin install``
455 command may fail to function properly.
457 0.8.0 Backend changes
458 ---------------------
460 Backends 'bsddb' and 'bsddb3' are removed.  If you are using one of these,
461 you *must* migrate to another backend before upgrading.
464 0.8.0 API changes
465 -----------------
467 Class.safeget() was removed from the API. Test your item ids before calling
468 Class.get() instead.
471 0.8.0 New tracker layout
472 ------------------------
474 The ``config.py`` file has been replaced by ``config.ini``. You may use the
475 roundup-admin command "genconfig" to generate a new config file::
477   roundup-admin genconfig <tracker home>/config.ini
479 and modify the values therein based on the contents of your old config.py.
480 In most cases, the names of the config variables are the same.
482 The ``select_db.py`` file has been replaced by a file in the ``db``
483 directory called ``backend_name``. As you might guess, this file contains
484 just the name of the backend. To figure what the contents of yours should
485 be, use the following table:
487   ================================ =========================
488   ``select_db.py`` contents        ``backend_name`` contents
489   ================================ =========================
490   from back_anydbm import ...      anydbm
491   from back_metakit import ...     metakit
492   from back_sqlite import ...      sqlite
493   from back_mysql import ...       mysql
494   from back_postgresql import ...  postgresql
495   ================================ =========================
497 The ``dbinit.py`` file has been split into two new files,
498 ``initial_data.py`` and ``schema.py``. The contents of this file are:
500 ``initial_data.py``
501   You don't need one of these as your tracker is already initialised.
503 ``schema.py``
504   Copy the body of the ``def open(name=None)`` function from your old
505   tracker's ``dbinit.py`` file to this file. As the lines you're copying
506   aren't part of a function definition anymore, one level of indentation
507   needs to be removed (remove only the leading four spaces on each
508   line). 
510   The first few lines -- those starting with ``from roundup.hyperdb
511   import ...`` and the ``db = Database(config, name)`` line -- don't
512   need to be copied. Neither do the last few lines -- those starting
513   with ``import detectors``, down to ``return db`` inclusive.
515 You may remove the ``__init__.py`` module from the "detectors" directory as
516 it is no longer used.
518 There's a new way to write extension code for Roundup. If you have code in
519 an ``interfaces.py`` file you should move it. See the `customisation
520 documentation`_ for information about how extensions are now written.
521 Note that some older trackers may use ``interfaces.py`` to customise the
522 mail gateway behaviour. You will need to keep your ``interfaces.py`` file
523 if this is the case.
526 0.8.0 Permissions Changes
527 -------------------------
529 The creation of a new item in the user interfaces is now controlled by the
530 "Create" Permission. You will need to add an assignment of this Permission
531 to your users who are allowed to create items. The most common form of this
532 is the following in your ``schema.py`` added just under the current
533 assignation of the Edit Permission::
535     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
536         p = db.security.getPermission('Create', cl)
537         db.security.addPermissionToRole('User', p)
539 You will need to explicitly let anonymous users access the web interface so
540 that regular users are able to see the login form. Note that almost all
541 trackers will need this Permission. The only situation where it's not
542 required is in a tracker that uses an HTTP Basic Authenticated front-end.
543 It's enabled by adding to your ``schema.py``::
545     p = db.security.getPermission('Web Access')
546     db.security.addPermissionToRole('Anonymous', p)
548 Finally, you will need to enable permission for your users to edit their
549 own details by adding the following to ``schema.py``::
551     # Users should be able to edit their own details. Note that this
552     # permission is limited to only the situation where the Viewed or
553     # Edited item is their own.
554     def own_record(db, userid, itemid):
555         '''Determine whether the userid matches the item being accessed.'''
556         return userid == itemid
557     p = db.security.addPermission(name='View', klass='user', check=own_record,
558         description="User is allowed to view their own user details")
559     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
560         description="User is allowed to edit their own user details")
561     db.security.addPermissionToRole('User', p)
564 0.8.0 Use of TemplatingUtils
565 ----------------------------
567 If you used custom python functions in TemplatingUtils, they must
568 be moved from interfaces.py to a new file in the ``extensions`` directory. 
570 Each Function that should be available through TAL needs to be defined
571 as a toplevel function in the newly created file. Furthermore you
572 add an inititialization function, that registers the functions with the 
573 tracker.
575 If you find this too tedious, donfu wrote an automatic init function that
576 takes an existing TemplatingUtils class, and registers all class methods
577 that do not start with an underscore. The following hack should be placed
578 in the ``extensions`` directory alongside other extensions::
580     class TemplatingUtils:
581          # copy from interfaces.py
583     def init(tracker):
584          util = TemplatingUtils()
586          def setClient(tu):
587              util.client = tu.client
588              return util
590          def execUtil(name):
591              return lambda tu, *args, **kwargs: \
592                      getattr(setClient(tu), name)(*args, **kwargs)
594          for name in dir(util):
595              if callable(getattr(util, name)) and not name.startswith('_'):
596                   tracker.registerUtil(name, execUtil(name))
599 0.8.0 Logging Configuration
600 ---------------------------
602 See the `administration guide`_ for information about configuring the new
603 logging implemented in 0.8.0.
606 Migrating from 0.7.2 to 0.7.3
607 =============================
609 0.7.3 Configuration
610 -------------------
612 If you choose, you may specify the directory from which static files are
613 served (those which use the URL component ``@@file``). Currently the
614 directory defaults to the ``TEMPLATES`` configuration variable. You may
615 define a new variable, ``STATIC_FILES`` which overrides this value for
616 static files.
619 Migrating from 0.7.0 to 0.7.2
620 =============================
622 0.7.2 DEFAULT_TIMEZONE is now required
623 --------------------------------------
625 The DEFAULT_TIMEZONE configuration variable is now required. Add the
626 following to your tracker's ``config.py`` file::
628     # You may specify a different default timezone, for use when users do not
629     # choose their own in their settings.
630     DEFAULT_TIMEZONE = 0            # specify as numeric hour offest
633 Migrating from 0.7.0 to 0.7.1
634 =============================
636 0.7.1 Permission assignments
637 ----------------------------
639 If you allow anonymous access to your tracker, you might need to assign
640 some additional View (or Edit if your tracker is that open) permissions
641 to the "anonymous" user. To do so, find the code in your ``dbinit.py`` that
642 says::
644     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
645         p = db.security.getPermission('View', cl)
646         db.security.addPermissionToRole('User', p)
647         p = db.security.getPermission('Edit', cl)
648         db.security.addPermissionToRole('User', p)
649     for cl in 'priority', 'status':
650         p = db.security.getPermission('View', cl)
651         db.security.addPermissionToRole('User', p)
653 Add add a line::
655         db.security.addPermissionToRole('Anonymous', p)
657 next to the existing ``'User'`` lines for the Permissions you wish to
658 assign to the anonymous user.
661 Migrating from 0.6 to 0.7
662 =========================
664 0.7.0 Permission assignments
665 ----------------------------
667 Due to a change in the rendering of web widgets, permissions are now
668 checked on Classes where they previously weren't (this is a good thing).
670 You will need to add some additional Permission assignments for your
671 regular users, or some displays will break. After the following in your 
672 tracker's ``dbinit.py``::
674     # Assign the access and edit Permissions for issue, file and message
675     # to regular users now
676     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
677         p = db.security.getPermission('View', cl)
678         db.security.addPermissionToRole('User', p)
679         p = db.security.getPermission('Edit', cl)
680         db.security.addPermissionToRole('User', p)
682 add::
684     for cl in 'priority', 'status':
685         p = db.security.getPermission('View', cl)
686         db.security.addPermissionToRole('User', p)
689 0.7.0 Getting the current user id
690 ---------------------------------
692 The Database.curuserid attribute has been removed.
694 Any code referencing this attribute should be replaced with a
695 call to Database.getuid().
698 0.7.0 ZRoundup changes
699 ----------------------
701 The templates in your tracker's html directory will need updating if you
702 wish to use ZRoundup. If you've not modified those files (or some of them),
703 you may just copy the new versions from the Roundup source in the
704 templates/classic/html directory.
706 If you have modified the html files, then you'll need to manually edit them
707 to change all occurances of special form variables from using the colon ":"
708 special character to the at "@" special character. That is, variables such
709 as::
711   :action :required :template :remove:messages ...
713 should become::
715   @action @required @template @remove@messages ...
717 Note that ``tal:`` statements are unaffected. So are TAL expression type
718 prefixes such as ``python:`` and ``string:``. Please ask on the
719 roundup-users mailing list for help if you're unsure.
722 0.7.0 Edit collision detection
723 ------------------------------
725 Roundup now detects collisions with editing in the web interface (that is,
726 two people editing the same item at the same time).
728 You must copy the ``_generic.collision.html`` file from Roundup source in
729 the ``templates/classic/html`` directory. to your tracker's ``html``
730 directory.
733 Migrating from 0.6.x to 0.6.3
734 =============================
736 0.6.3 Configuration
737 -------------------
739 You will need to copy the file::
741   templates/classic/detectors/__init__.py
743 to your tracker's ``detectors`` directory, replacing the one already there.
744 This fixes a couple of bugs in that file.
748 Migrating from 0.5 to 0.6
749 =========================
752 0.6.0 Configuration
753 -------------------
755 Introduced EMAIL_FROM_TAG config variable. This value is inserted into
756 the From: line of nosy email. If the sending user is "Foo Bar", the
757 From: line is usually::
759      "Foo Bar" <issue_tracker@tracker.example>
761 the EMAIL_FROM_TAG goes inside the "Foo Bar" quotes like so::
763      "Foo Bar EMAIL_FROM_TAG" <issue_tracker@tracker.example>
765 I've altered the mechanism in the detectors __init__.py module so that it
766 doesn't cross-import detectors from other trackers (if you run more than one
767 in a single roundup-server). This change means that you'll need to copy the
768 __init__.py from roundup/templates/classic/detectors/__init__.py to your
769 <tracker home>/detectors/__init__.py. Don't worry, the "classic" __init__ is a
770 one-size-fits-all, so it'll work even if you've added/removed detectors.
772 0.6.0 Templating changes
773 ------------------------
775 The ``user.item`` template (in the tracker home "templates" directory)
776 needs to have the following hidden variable added to its form (between the
777 ``<form...>`` and ``</form>`` tags::
779   <input type="hidden" name=":template" value="item">
782 0.6.0 Form handling changes
783 ---------------------------
785 Roundup's form handling capabilities have been significantly expanded. This
786 should not affect users of 0.5 installations - but if you find you're
787 getting errors from form submissions, please ask for help on the Roundup
788 users mailing list:
790   http://lists.sourceforge.net/lists/listinfo/roundup-users
792 See the customisation doc section on `Form Values`__ for documentation of the
793 new form variables possible.
795 __ customizing.html#form-values
798 0.6.0 Multilingual character set support
799 ----------------------------------------
801 Added internationalization support. This is done via encoding all data
802 stored in roundup database to utf-8 (unicode encoding). To support utf-8 in
803 web interface you should add the folowing line to your tracker's html/page
804 and html/_generic.help files inside <head> tag::
805   
806     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
808 Since latin characters in utf-8 have the same codes as in ASCII table, this
809 modification is optional for users who use only plain latin characters. 
811 After this modification, you will be able to see and enter any world
812 character via web interface. Data received via mail interface also converted
813 to utf-8, however only new messages will be converted. If your roundup
814 database contains some of non-ASCII characters in one of 8-bit encoding,
815 they will not be visible in new unicode environment. Some of such data (e.g.
816 user names, keywords, etc)  can be edited by administrator, the others
817 (e.g. messages' contents) is not editable via web interface. Currently there
818 is no tool for converting such data, the only solution is to close
819 appropriate old issues and create new ones with the same content.
822 0.6.0 User timezone support
823 ---------------------------
825 From version 0.6.0 roundup supports displaying of Date data in user' local
826 timezone if he/she has provided timezone information. To make it possible
827 some modification to tracker's schema and HTML templates are required.
828 First you must add string property 'timezone' to user class in dbinit.py
829 like this::
830   
831     user = Class(db, "user", 
832                     username=String(),   password=Password(),
833                     address=String(),    realname=String(), 
834                     phone=String(),      organisation=String(),
835                     alternate_addresses=String(),
836                     queries=Multilink('query'), roles=String(),
837                     timezone=String())
838   
839 And second - html interface. Add following lines to
840 $TRACKER_HOME/html/user.item template::
841   
842      <tr>
843       <th>Timezone</th>
844       <td tal:content="structure context/timezone/field">timezone</td>
845      </tr>
847 After that all users should be able to provide their timezone information.
848 Timezone should be a positive or negative integer - offset from GMT.
850 After providing timezone, roundup will show all dates values, found in web
851 and mail interfaces in local time. It will also accept any Date info in
852 local time, convert and store it in GMT.
855 0.6.0 Search page structure
856 ---------------------------
858 In order to accomodate query editing the search page has been restructured. If
859 you want to provide your users with query editing, you should update your
860 search page using the macros detailed in the customisation doc section
861 `Searching on categories`__.
863 __ customizing.html#searching-on-categories
865 Also, the url field in the query class no longer starts with a '?'. You'll need
866 to remove this question mark from the url field to support queries. There's
867 a script in the "tools" directory called ``migrate-queries.py`` that should
868 automatically change any existing queries for you. As always, make a backup
869 of your database before running such a script.
872 0.6.0 Notes for metakit backend users
873 -------------------------------------
875 Roundup 0.6.0 introduced searching on ranges of dates and intervals. To
876 support it, some modifications to interval storing routine were made. So if
877 your tracker uses metakit backend and your db schema contains intervals
878 property, searches on that property will not be accurate for db items that
879 was stored before roundup' upgrade. However all new records should be
880 searchable on intervals.
882 It is possible to convert your database to new format: you can export and
883 import back all your data (consult "Migrating backends" in "Maintenance"
884 documentation). After this operation all your interval properties should
885 become searchable.
887 Users of backends others than metakit should not worry about this issue.
890 Migrating from 0.4.x to 0.5.0
891 =============================
893 This has been a fairly major revision of Roundup:
895 1. Brand new, much more powerful, flexible, tasty and nutritious templating.
896    Unfortunately, this means all your current templates are useless. Hopefully
897    the new documentation and examples will be enough to help you make the
898    transition. Please don't hesitate to ask on roundup-users for help (or
899    complete conversions if you're completely stuck)!
900 2. The database backed got a lot more flexible, allowing Metakit and SQL
901    databases! The only decent SQL database implemented at present is sqlite,
902    but others shouldn't be a whole lot more work.
903 3. A brand new, highly flexible and much more robust security system including
904    a system of Permissions, Roles and Role assignments to users. You may now
905    define your own Permissions that may be checked in CGI transactions.
906 4. Journalling has been made less storage-hungry, so has been turned on
907    by default *except* for author, recipient and nosy link/unlink events. You
908    are advised to turn it off in your trackers too.
909 5. We've changed the terminology from "instance" to "tracker", to ease the
910    learning curve/impact for new users.
911 6. Because of the above changes, the tracker configuration has seen some
912    major changes. See below for the details.
914 Please, **back up your database** before you start the migration process. This
915 is as simple as copying the "db" directory and all its contents from your
916 tracker to somewhere safe.
919 0.5.0 Configuration
920 -------------------
922 First up, rename your ``instance_config.py`` file to just ``config.py``.
924 Then edit your tracker's ``__init__.py`` module. It'll currently look
925 like this::
927  from instance_config import *
928  try:
929      from dbinit import *
930  except ImportError:
931      pass # in installdir (probably :)
932  from interfaces import *
934 and it needs to be::
936  import config
937  from dbinit import open, init
938  from interfaces import Client, MailGW
940 Due to the new templating having a top-level ``page`` that defines links for
941 searching, indexes, adding items etc, the following variables are no longer
942 used:
944 - HEADER_INDEX_LINKS
945 - HEADER_ADD_LINKS
946 - HEADER_SEARCH_LINKS
947 - SEARCH_FILTERS
948 - DEFAULT_INDEX
949 - UNASSIGNED_INDEX
950 - USER_INDEX
951 - ISSUE_FILTER
953 The new security implementation will require additions to the dbinit module,
954 but also removes the need for the following tracker config variables:
956 - ANONYMOUS_ACCESS
957 - ANONYMOUS_REGISTER
959 but requires two new variables which define the Roles assigned to users who
960 register through the web and e-mail interfaces:
962 - NEW_WEB_USER_ROLES
963 - NEW_EMAIL_USER_ROLES
965 in both cases, 'User' is a good initial setting. To emulate
966 ``ANONYMOUS_ACCESS='deny'``, remove all "View" Permissions from the
967 "Anonymous" Role. To emulate ``ANONYMOUS_REGISTER='deny'``, remove the "Web
968 Registration" and/or the "Email Registration" Permission from the "Anonymous"
969 Role. See the section on customising security in the `customisation
970 documentation`_ for more information.
972 Finally, the following config variables have been renamed to make more sense:
974 - INSTANCE_HOME -> TRACKER_HOME
975 - INSTANCE_NAME -> TRACKER_NAME
976 - ISSUE_TRACKER_WEB -> TRACKER_WEB
977 - ISSUE_TRACKER_EMAIL -> TRACKER_EMAIL
980 0.5.0 Schema Specification
981 --------------------------
983 0.5.0 Database backend changes
984 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
986 Your select_db module in your tracker has changed a fair bit. Where it used
987 to contain::
989  # WARNING: DO NOT EDIT THIS FILE!!!
990  from roundup.backends.back_anydbm import Database
992 it must now contain::
994  # WARNING: DO NOT EDIT THIS FILE!!!
995  from roundup.backends.back_anydbm import Database, Class, FileClass, IssueClass
997 Yes, I realise the irony of the "DO NOT EDIT THIS FILE" statement :)
998 Note the addition of the Class, FileClass, IssueClass imports. These are very
999 important, as they're going to make the next change work too. You now need to
1000 modify the top of the dbinit module in your tracker from::
1002  import instance_config
1003  from roundup import roundupdb
1004  from select_db import Database
1006  from roundup.roundupdb import Class, FileClass
1008  class Database(roundupdb.Database, select_db.Database):
1009      ''' Creates a hybrid database from:
1010           . the selected database back-end from select_db
1011           . the roundup extensions from roundupdb
1012      '''
1013      pass
1015  class IssueClass(roundupdb.IssueClass):
1016      ''' issues need the email information
1017      '''
1018      pass
1020 to::
1022  import config
1023  from select_db import Database, Class, FileClass, IssueClass
1025 Yes, remove the Database and IssueClass definitions and those other imports.
1026 They're not needed any more!
1028 Look for places in dbinit.py where ``instance_config`` is used too, and
1029 rename them ``config``.
1032 0.5.0 Journalling changes
1033 ~~~~~~~~~~~~~~~~~~~~~~~~~
1035 Journalling has been optimised for storage. Journalling of links has been
1036 turned back on by default. If your tracker has a large user base, you may wish
1037 to turn off journalling of nosy list, message author and message recipient
1038 link and unlink events. You do this by adding ``do_journal='no'`` to the Class
1039 initialisation in your dbinit. For example, your *msg* class initialisation
1040 probably looks like this::
1042     msg = FileClass(db, "msg",
1043                     author=Link("user"), recipients=Multilink("user"),
1044                     date=Date(),         summary=String(),
1045                     files=Multilink("file"),
1046                     messageid=String(),  inreplyto=String())
1048 to turn off journalling of author and recipient link events, add
1049 ``do_journal='no'`` to the ``author=Link("user")`` part of the statement,
1050 like so::
1052     msg = FileClass(db, "msg",
1053                     author=Link("user", do_journal='no'),
1054                     recipients=Multilink("user", do_journal='no'),
1055                     date=Date(),         summary=String(),
1056                     files=Multilink("file"),
1057                     messageid=String(),  inreplyto=String())
1059 Nosy list link event journalling is actually turned off by default now. If you
1060 want to turn it on, change to your issue class' nosy list, change its
1061 definition from::
1063     issue = IssueClass(db, "issue",
1064                     assignedto=Link("user"), topic=Multilink("keyword"),
1065                     priority=Link("priority"), status=Link("status"))
1067 to::
1069     issue = IssueClass(db, "issue", nosy=Multilink("user", do_journal='yes'),
1070                     assignedto=Link("user"), topic=Multilink("keyword"),
1071                     priority=Link("priority"), status=Link("status"))
1073 noting that your definition of the nosy Multilink will override the normal one.
1076 0.5.0 User schema changes
1077 ~~~~~~~~~~~~~~~~~~~~~~~~~
1079 Users have two more properties, "queries" and "roles". You'll have something
1080 like this in your dbinit module now::
1082     user = Class(db, "user",
1083                     username=String(),   password=Password(),
1084                     address=String(),    realname=String(),
1085                     phone=String(),      organisation=String(),
1086                     alternate_addresses=String())
1087     user.setkey("username")
1089 and you'll need to add the new properties and the new "query" class to it
1090 like so::
1092     query = Class(db, "query",
1093                     klass=String(),     name=String(),
1094                     url=String())
1095     query.setkey("name")
1097     # Note: roles is a comma-separated string of Role names
1098     user = Class(db, "user",
1099                     username=String(),   password=Password(),
1100                     address=String(),    realname=String(),
1101                     phone=String(),      organisation=String(),
1102                     alternate_addresses=String(),
1103                     queries=Multilink('query'), roles=String())
1104     user.setkey("username")
1106 The "queries" property is used to store off the user's favourite database
1107 queries. The "roles" property is explained below in `0.5.0 Security
1108 Settings`_.
1111 0.5.0 Security Settings
1112 ~~~~~~~~~~~~~~~~~~~~~~~
1114 See the `security documentation`_ for an explanation of how the new security
1115 system works. In a nutshell though, the security is handled as a four step
1116 process:
1118 1. Permissions are defined as having a name and optionally a hyperdb class
1119    they're specific to,
1120 2. Roles are defined that have one or more Permissions,
1121 3. Users are assigned Roles in their "roles" property, and finally
1122 4. Roundup checks that users have appropriate Permissions at appropriate times
1123    (like editing issues).
1125 Your tracker dbinit module's *open* function now has to define any
1126 Permissions that are specific to your tracker, and also the assignment
1127 of Permissions to Roles. At the moment, your open function
1128 ends with::
1130     import detectors
1131     detectors.init(db)
1133     return db
1135 and what we need to do is insert some commands that will set up the security
1136 parameters. Right above the ``import detectors`` line, you'll want to insert
1137 these lines::
1139     #
1140     # SECURITY SETTINGS
1141     #
1142     # new permissions for this schema
1143     for cl in 'issue', 'file', 'msg', 'user':
1144         db.security.addPermission(name="Edit", klass=cl,
1145             description="User is allowed to edit "+cl)
1146         db.security.addPermission(name="View", klass=cl,
1147             description="User is allowed to access "+cl)
1149     # Assign the access and edit permissions for issue, file and message
1150     # to regular users now
1151     for cl in 'issue', 'file', 'msg':
1152         p = db.security.getPermission('View', cl)
1153         db.security.addPermissionToRole('User', p)
1154         p = db.security.getPermission('Edit', cl)
1155         db.security.addPermissionToRole('User', p)
1156     # and give the regular users access to the web and email interface
1157     p = db.security.getPermission('Web Access')
1158     db.security.addPermissionToRole('User', p)
1159     p = db.security.getPermission('Email Access')
1160     db.security.addPermissionToRole('User', p)
1162     # May users view other user information? Comment these lines out
1163     # if you don't want them to
1164     p = db.security.getPermission('View', 'user')
1165     db.security.addPermissionToRole('User', p)
1167     # Assign the appropriate permissions to the anonymous user's Anonymous
1168     # Role. Choices here are:
1169     # - Allow anonymous users to register through the web
1170     p = db.security.getPermission('Web Registration')
1171     db.security.addPermissionToRole('Anonymous', p)
1172     # - Allow anonymous (new) users to register through the email gateway
1173     p = db.security.getPermission('Email Registration')
1174     db.security.addPermissionToRole('Anonymous', p)
1175     # - Allow anonymous users access to the "issue" class of data
1176     #   Note: this also grants access to related information like files,
1177     #         messages, statuses etc that are linked to issues
1178     #p = db.security.getPermission('View', 'issue')
1179     #db.security.addPermissionToRole('Anonymous', p)
1180     # - Allow anonymous users access to edit the "issue" class of data
1181     #   Note: this also grants access to create related information like
1182     #         files and messages etc that are linked to issues
1183     #p = db.security.getPermission('Edit', 'issue')
1184     #db.security.addPermissionToRole('Anonymous', p)
1186     # oh, g'wan, let anonymous access the web interface too
1187     p = db.security.getPermission('Web Access')
1188     db.security.addPermissionToRole('Anonymous', p)
1190 Note in the comments there the places where you might change the permissions
1191 to restrict users or grant users more access. If you've created additional
1192 classes that users should be able to edit and view, then you should add them
1193 to the "new permissions for this schema" section at the start of the security
1194 block. Then add them to the "Assign the access and edit permissions" section
1195 too, so people actually have the new Permission you've created.
1197 One final change is needed that finishes off the security system's
1198 initialisation. We need to add a call to ``db.post_init()`` at the end of the
1199 dbinit open() function. Add it like this::
1201     import detectors
1202     detectors.init(db)
1204     # schema is set up - run any post-initialisation
1205     db.post_init()
1206     return db
1208 You may verify the setup of Permissions and Roles using the new
1209 "``roundup-admin security``" command.
1212 0.5.0 User changes
1213 ~~~~~~~~~~~~~~~~~~
1215 To support all those schema changes, you'll need to massage your user database
1216 a little too, to:
1218 1. make sure there's an "anonymous" user - this user is mandatory now and is
1219    the one that unknown users are logged in as.
1220 2. make sure all users have at least one Role.
1222 If you don't have the "anonymous" user, create it now with the command::
1224   roundup-admin create user username=anonymous roles=Anonymous
1226 making sure the capitalisation is the same as above. Once you've done that,
1227 you'll need to set the roles property on all users to a reasonable default.
1228 The admin user should get "Admin", the anonymous user "Anonymous"
1229 and all other users "User". The ``fixroles.py`` script in the tools directory
1230 will do this. Run it like so (where python is your python 2+ binary)::
1232   python tools/fixroles.py -i <tracker home> fixroles
1236 0.5.0 CGI interface changes
1237 ---------------------------
1239 The CGI interface code was completely reorganised and largely rewritten. The
1240 end result is that this section of your tracker interfaces module will need
1241 changing from::
1243  from roundup import cgi_client, mailgw
1244  from roundup.i18n import _
1245  
1246  class Client(cgi_client.Client):
1247      ''' derives basic CGI implementation from the standard module,
1248          with any specific extensions
1249      '''
1250      pass
1252 to::
1254  from roundup import mailgw
1255  from roundup.cgi import client
1256  
1257  class Client(client.Client): 
1258      ''' derives basic CGI implementation from the standard module,
1259          with any specific extensions
1260      '''
1261      pass
1263 You will also need to install the new version of roundup.cgi from the source
1264 cgi-bin directory if you're using it.
1267 0.5.0 HTML templating
1268 ---------------------
1270 You'll want to make a backup of your current tracker html directory. You
1271 should then copy the html directory from the Roundup source "classic" template
1272 and modify it according to your local schema changes.
1274 If you need help with the new templating system, please ask questions on the
1275 roundup-users mailing list (available through the roundup project page on
1276 sourceforge, http://roundup.sf.net/)
1279 0.5.0 Detectors
1280 ---------------
1282 The nosy reactor has been updated to handle the tracker not having an
1283 "assignedto" property on issues. You may want to copy it into your tracker's
1284 detectors directory. Chances are you've already fixed it though :)
1287 Migrating from 0.4.1 to 0.4.2
1288 =============================
1290 0.4.2 Configuration
1291 -------------------
1292 The USER_INDEX definition introduced in 0.4.1 was too restrictive in its
1293 allowing replacement of 'assignedto' with the user's userid. Users must change
1294 the None value of 'assignedto' to 'CURRENT USER' (the string, in quotes) for
1295 the replacement behaviour to occur now.
1297 The new configuration variables are:
1299 - EMAIL_KEEP_QUOTED_TEXT 
1300 - EMAIL_LEAVE_BODY_UNCHANGED
1301 - ADD_RECIPIENTS_TO_NOSY
1303 See the sample configuration files in::
1305  <roundup source>/roundup/templates/classic/instance_config.py
1307 and::
1309  <roundup source>/roundup/templates/extended/instance_config.py
1311 and the `customisation documentation`_ for information on how they're used.
1314 0.4.2 Changes to detectors
1315 --------------------------
1316 You will need to copy the detectors from the distribution into your instance
1317 home "detectors" directory. If you used the classic schema, the detectors
1318 are in::
1320  <roundup source>/roundup/templates/classic/detectors/
1322 If you used the extended schema, the detectors are in::
1324  <roundup source>/roundup/templates/extended/detectors/
1326 The change means that schema-specific code has been removed from the
1327 mail gateway and cgi interface and made into auditors:
1329 - nosyreactor.py has now got an updatenosy auditor which updates the nosy
1330   list with author, recipient and assignedto information.
1331 - statusauditor.py makes the unread or resolved -> chatting changes and
1332   presets the status of an issue to unread.
1334 There's also a bug or two fixed in the nosyreactor code.
1336 0.4.2 HTML templating changes
1337 -----------------------------
1338 The link() htmltemplate function now has a "showid" option for links and
1339 multilinks. When true, it only displays the linked item id as the anchor
1340 text. The link value is displayed as a tooltip using the title anchor
1341 attribute. To use in eg. the superseder field, have something like this::
1343    <td>
1344     <display call="field('superseder', showid=1)">
1345     <display call="classhelp('issue', 'id,title', label='list', width=500)">
1346     <property name="superseder">
1347      <br>View: <display call="link('superseder', showid=1)">
1348     </property>
1349    </td>
1351 The stylesheets have been cleaned up too. You may want to use the newer
1352 versions in::
1354  <roundup source>/roundup/templates/<template>/html/default.css
1358 Migrating from 0.4.0 to 0.4.1
1359 =============================
1361 0.4.1 Files storage
1362 -------------------
1364 Messages and files from newly created issues will be put into subdierectories
1365 in thousands e.g. msg123 will be put into files/msg/0/msg123, file2003
1366 will go into files/file/2/file2003. Previous messages are still found, but
1367 could be put into this structure.
1369 0.4.1 Configuration
1370 -------------------
1372 To allow more fine-grained access control, the variable used to check
1373 permission to auto-register users in the mail gateway is now called
1374 ANONYMOUS_REGISTER_MAIL rather than overloading ANONYMOUS_REGISTER. If the
1375 variable doesn't exist, then ANONYMOUS_REGISTER is tested as before.
1377 Configuring the links in the web header is now easier too. The following
1378 variables have been added to the classic instance_config.py::
1380   HEADER_INDEX_LINKS   - defines the "index" links to be made available
1381   HEADER_ADD_LINKS     - defines the "add" links
1382   DEFAULT_INDEX        - specifies the index view for DEFAULT
1383   UNASSIGNED_INDEX     - specifies the index view for UNASSIGNED
1384   USER_INDEX           - specifies the index view for USER
1386 See the <roundup source>/roundup/templates/classic/instance_config.py for more
1387 information - including how the variables are to be set up. Most users will
1388 just be able to copy the variables from the source to their instance home. If
1389 you've modified the header by changing the source of the interfaces.py file in
1390 the instance home, you'll need to remove that customisation and move it into
1391 the appropriate variables in instance_config.py.
1393 The extended schema has similar variables added too - see the source for more
1394 info.
1396 0.4.1 Alternate E-Mail Addresses
1397 --------------------------------
1399 If you add the property "alternate_addresses" to your user class, your users
1400 will be able to register alternate email addresses that they may use to
1401 communicate with roundup as. All email from roundup will continue to be sent
1402 to their primary address.
1404 If you have not edited the dbinit.py file in your instance home directory,
1405 you may simply copy the new dbinit.py file from the core code. If you used
1406 the classic schema, the interfaces file is in::
1408  <roundup source>/roundup/templates/classic/dbinit.py
1410 If you used the extended schema, the file is in::
1412  <roundup source>/roundup/templates/extended/dbinit.py 
1414 If you have modified your dbinit.py file, you need to edit the dbinit.py
1415 file in your instance home directory. Find the lines which define the user
1416 class::
1418     user = Class(db, "msg",
1419                     username=String(),   password=Password(),
1420                     address=String(),    realname=String(), 
1421                     phone=String(),      organisation=String(),
1422                     alternate_addresses=String())
1424 You will also want to add the property to the user's details page. The
1425 template for this is the "user.item" file in your instance home "html"
1426 directory. Similar to above, you may copy the file from the roundup source if
1427 you haven't modified it. Otherwise, add the following to the template::
1429    <display call="multiline('alternate_addresses')">
1431 with appropriate labelling etc. See the standard template for an idea.
1435 Migrating from 0.3.x to 0.4.0
1436 =============================
1438 0.4.0 Message-ID and In-Reply-To addition
1439 -----------------------------------------
1440 0.4.0 adds the tracking of messages by message-id and allows threading
1441 using in-reply-to. Most e-mail clients support threading using this
1442 feature, and we hope to add support for it to the web gateway. If you
1443 have not edited the dbinit.py file in your instance home directory, you may
1444 simply copy the new dbinit.py file from the core code. If you used the
1445 classic schema, the interfaces file is in::
1447  <roundup source>/roundup/templates/classic/dbinit.py
1449 If you used the extended schema, the file is in::
1451  <roundup source>/roundup/templates/extended/dbinit.py 
1453 If you have modified your dbinit.py file, you need to edit the dbinit.py
1454 file in your instance home directory. Find the lines which define the msg
1455 class::
1457     msg = FileClass(db, "msg",
1458                     author=Link("user"), recipients=Multilink("user"),
1459                     date=Date(),         summary=String(),
1460                     files=Multilink("file"))
1462 and add the messageid and inreplyto properties like so::
1464     msg = FileClass(db, "msg",
1465                     author=Link("user"), recipients=Multilink("user"),
1466                     date=Date(),         summary=String(),
1467                     files=Multilink("file"),
1468                     messageid=String(),  inreplyto=String())
1470 Also, configuration is being cleaned up. This means that your dbinit.py will
1471 also need to be changed in the open function. If you haven't changed your
1472 dbinit.py, the above copy will be enough. If you have, you'll need to change
1473 the line (round line 50)::
1475     db = Database(instance_config.DATABASE, name)
1477 to::
1479     db = Database(instance_config, name)
1482 0.4.0 Configuration
1483 --------------------
1484 ``TRACKER_NAME`` and ``EMAIL_SIGNATURE_POSITION`` have been added to the
1485 instance_config.py. The simplest solution is to copy the default values
1486 from template in the core source.
1488 The mail gateway now checks ``ANONYMOUS_REGISTER`` to see if unknown users
1489 are to be automatically registered with the tracker. If it is set to "deny"
1490 then unknown users will not have access. If it is set to "allow" they will be
1491 automatically registered with the tracker.
1494 0.4.0 CGI script roundup.cgi
1495 ----------------------------
1496 The CGI script has been updated with some features and a bugfix, so you should
1497 copy it from the roundup cgi-bin source directory again. Make sure you update
1498 the ROUNDUP_INSTANCE_HOMES after the copy.
1501 0.4.0 Nosy reactor
1502 ------------------
1503 The nosy reactor has also changed - copy the nosyreactor.py file from the core
1504 source::
1506    <roundup source>/roundup/templates/<template>/detectors/nosyreactor.py
1508 to your instance home "detectors" directory.
1511 0.4.0 HTML templating
1512 ---------------------
1513 The field() function was incorrectly implemented - links and multilinks now
1514 display as text fields when rendered using field(). To display a menu (drop-
1515 down or select box) you need to use the menu() function.
1519 Migrating from 0.2.x to 0.3.x
1520 =============================
1522 0.3.x Cookie Authentication changes
1523 -----------------------------------
1524 0.3.0 introduces cookie authentication - you will need to copy the
1525 interfaces.py file from the roundup source to your instance home to enable
1526 authentication. If you used the classic schema, the interfaces file is in::
1528  <roundup source>/roundup/templates/classic/interfaces.py
1530 If you used the extended schema, the file is in::
1532  <roundup source>/roundup/templates/extended/interfaces.py
1534 If you have modified your interfaces.Client class, you will need to take
1535 note of the login/logout functionality provided in roundup.cgi_client.Client
1536 (classic schema) or roundup.cgi_client.ExtendedClient (extended schema) and
1537 modify your instance code apropriately.
1540 0.3.x Password encoding
1541 -----------------------
1542 This release also introduces encoding of passwords in the database. If you
1543 have not edited the dbinit.py file in your instance home directory, you may
1544 simply copy the new dbinit.py file from the core code. If you used the
1545 classic schema, the interfaces file is in::
1547  <roundup source>/roundup/templates/classic/dbinit.py
1549 If you used the extended schema, the file is in::
1551  <roundup source>/roundup/templates/extended/dbinit.py
1554 If you have modified your dbinit.py file, you may use encoded passwords:
1556 1. Edit the dbinit.py file in your instance home directory
1557    a. At the first code line of the open() function::
1559        from roundup.hyperdb import String, Date, Link, Multilink
1561       alter to include Password, as so::
1563        from roundup.hyperdb import String, Password, Date, Link, Multilink
1565    b. Where the password property is defined (around line 66)::
1567        user = Class(db, "user", 
1568                        username=String(),   password=String(),
1569                        address=String(),    realname=String(), 
1570                        phone=String(),      organisation=String())
1571        user.setkey("username")
1573       alter the "password=String()" to "password=Password()"::
1575        user = Class(db, "user", 
1576                        username=String(),   password=Password(),
1577                        address=String(),    realname=String(), 
1578                        phone=String(),      organisation=String())
1579        user.setkey("username")
1581 2. Any existing passwords in the database will remain cleartext until they
1582    are edited. It is recommended that at a minimum the admin password be
1583    changed immediately::
1585       roundup-admin -i <instance home> set user1 password=<new password>
1588 0.3.x Configuration
1589 -------------------
1590 FILTER_POSITION, ANONYMOUS_ACCESS, ANONYMOUS_REGISTER have been added to
1591 the instance_config.py. Simplest solution is to copy the default values from
1592 template in the core source.
1594 MESSAGES_TO_AUTHOR has been added to the IssueClass in dbinit.py. Set to 'yes'
1595 to send nosy messages to the author. Default behaviour is to not send nosy
1596 messages to the author. You will need to add MESSAGES_TO_AUTHOR to your
1597 dbinit.py in your instance home.
1600 0.3.x CGI script roundup.cgi
1601 ----------------------------
1602 There have been some structural changes to the roundup.cgi script - you will
1603 need to install it again from the cgi-bin directory of the source
1604 distribution. Make sure you update the ROUNDUP_INSTANCE_HOMES after the
1605 copy.
1608 .. _`customisation documentation`: customizing.html
1609 .. _`security documentation`: security.html
1610 .. _`administration guide`: admin_guide.html