Code

more
[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 Fixing some potential security holes
26 ------------------------------------
28 Some HTML templates were found to have formatting security problems:
30 ``html/page.html``::
32   -tal:replace="request/user/username">username</span></b><br>
33   +tal:replace="python:request.user.username.plain(escape=1)">username</span></b><br>
35 ``html/_generic.help-list.html``::
37   -tal:content="structure python:item[prop]"></label>
38   +tal:content="python:item[prop]"></label>
40 The lines marked "+" should be added and lines marked "-" should be
41 deleted (minus the "+"/"-" signs).
44 Some HTML interface tweaks
45 --------------------------
47 You may wish to copy the ``user_utils.js`` and ``style.css` files from the
48 source distribution ``share/roundup/templates/classic/html/`` directory to the
49 ``html`` directory of your trackers as it includes a small improvement.
51 If you have made local changes to those files you'll need to manually work
52 the differences in to your versions or ignore the changes.
55 Migrating from 1.4.x to 1.4.11
56 ==============================
58 Close potential security hole
59 -----------------------------
61 If your tracker has untrusted users you should examine its ``schema.py``
62 file and look for the section granting the "Edit" permission to your users.
63 This should look something like::
65     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
66         description="User is allowed to edit their own user details")
68 and should be modified to restrict the list of properties they are allowed
69 to edit by adding the ``properties=`` section like::
71     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
72         properties=('username', 'password', 'address', 'realname', 'phone',
73             'organisation', 'alternate_addresses', 'queries', 'timezone'),
74         description="User is allowed to edit their own user details")
76 Most importantly the "roles" property should not be editable - thus not
77 appear in that list of properties.
80 Grant the "Register" permission to the Anonymous role
81 -----------------------------------------------------
83 A separate "Register" permission has been introduced to allow
84 anonymous users to register. This means you will need to add the
85 following to your tracker's ``schema.py`` to add the permission and
86 assign it to the Anonymous role (replacing any previously assigned
87 "Create user" permission for the Anonymous role)::
89   +db.security.addPermission(name='Register', klass='user',
90   +     description='User is allowed to register new user')
91  
92    # Assign the appropriate permissions to the anonymous user's Anonymous
93    # Role. Choices here are:
94    # - Allow anonymous users to register
95   -db.security.addPermissionToRole('Anonymous', 'Create', 'user')
96   +db.security.addPermissionToRole('Anonymous', 'Register', 'user')
98 The lines marked "+" should be added and lines marked "-" should be
99 deleted (minus the "+"/"-" signs).
101 You should also modify the ``html/page.py`` template to change the
102 permission tested there::
104    -tal:condition="python:request.user.hasPermission('Create', 'user')"
105    +tal:condition="python:request.user.hasPermission('Register', 'user')"
108 Generic class editor may now restore retired items
109 --------------------------------------------------
111 The instructions for doing so won't be present in your tracker unless you copy
112 the ``_generic.index.html`` template from the roundup distribution in
113 ``share/roundup/templates/classic/html`` to your tracker's ``html`` directory.
116 Migrating from 1.4.x to 1.4.9
117 =============================
119 Customized MailGW Class
120 -----------------------
122 If you have customized the MailGW class in your tracker: The new MailGW
123 class opens the database for each message in the method handle_message
124 (instance.open) instead of passing the opened database as a parameter to
125 the MailGW constructor. The old handle_message has been renamed to
126 _handle_message. The new method opens the database and wraps the call to
127 the old method into a try/finally.
129 Your customized MailGW class needs to mirror this behavior.
131 Fix the "remove" button in issue files and messages lists
132 ---------------------------------------------------------
134 The "remove" button(s) in the issue messages list needs to be altered. Find
135 the following in your tracker's ``html/issue.item.html`` template::
137   <td>
138    <form style="padding:0" tal:condition="context/is_edit_ok"
139          tal:attributes="action string:issue${context/id}">
140     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
142 and add ``method="POST"`` as shown below::
144   <td>
145    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
146          tal:attributes="action string:issue${context/id}">
147     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
149 Then also find::
151   <td>
152    <form style="padding:0" tal:condition="context/is_edit_ok"
153          tal:attributes="action string:issue${context/id}">
154     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
156 and add ``method="POST"`` as shown below::
158   <td>
159    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
160          tal:attributes="action string:issue${context/id}">
161     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
164 Fixing the "retire" button in user management list
165 --------------------------------------------------
167 If you made the change to the "reture" link in the user management list as
168 listed below in `Migrating from 1.4.x to 1.4.7`_ then you'll need to fix that
169 change by adding ``method="POST"`` to the ``<form>`` tag::
171      <form style="padding:0" method="POST"
172            tal:attributes="action string:user${user/id}">
173       <input type="hidden" name="@template" value="index">
174       <input type="hidden" name="@action" value="retire">
175       <input type="submit" value="retire" i18n:attributes="value">
176      </form>
179 Migrating from 1.4.x to 1.4.7
180 =============================
182 Several security issues were addressed in this release. Some aspects of your
183 trackers may no longer function depending on your local customisations. Core
184 functionality that will need to be modified:
186 Grant the "retire" permission to users for their queries
187 --------------------------------------------------------
189 Users will no longer be able to retire their own queries. To remedy this you
190 will need to add the following to your tracker's ``schema.py`` just under the
191 line that grants them permission to edit their own queries::
193    p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
194       description="User is allowed to edit their queries")
195    db.security.addPermissionToRole('User', p)
196  + p = db.security.addPermission(name='Retire', klass='query', check=edit_query,
197  +    description="User is allowed to retire their queries")
198  + db.security.addPermissionToRole('User', p)
199    p = db.security.addPermission(name='Create', klass='query',
200       description="User is allowed to create queries")
201    db.security.addPermissionToRole('User', p)
203 The lines marked "+" should be added, minus the "+" sign.
206 Fix the "retire" link in the users list for admin users
207 -------------------------------------------------------
209 The "retire" link found in the file ``html/users.index.html``::
211   <td tal:condition="context/is_edit_ok">
212    <a tal:attributes="href string:user${user/id}?@action=retire&@template=index"
213     i18n:translate="">retire</a>
215 Should be replaced with::
217   <td tal:condition="context/is_retire_ok">
218      <form style="padding:0" method="POST"
219            tal:attributes="action string:user${user/id}">
220       <input type="hidden" name="@template" value="index">
221       <input type="hidden" name="@action" value="retire">
222       <input type="submit" value="retire" i18n:attributes="value">
223      </form>
226 Fix for Python 2.6+ users
227 -------------------------
229 If you use Python 2.6 you should edit your tracker's
230 ``detectors/nosyreaction.py`` file to change::
232    import sets
234 at the top to::
236    from roundup.anypy.sets_ import set
238 and then all instances of ``sets.Set()`` to ``set()`` in the later code.
242 Trackers currently allowing HTML file uploading
243 -----------------------------------------------
245 Trackers which wish to continue to allow uploading of HTML content against issues
246 will need to set a new configuration variable in the ``[web]`` section of the
247 tracker's ``config.ini`` file:
249    # Setting this option enables Roundup to serve uploaded HTML
250    # file content *as HTML*. This is a potential security risk
251    # and is therefore disabled by default. Set to 'yes' if you
252    # trust *all* users uploading content to your tracker.
253    # Allowed values: yes, no
254    # Default: no
255    allow_html_file = no
259 Migrating from 1.4.2 to 1.4.3
260 =============================
262 If you are using the MySQL backend you will need to replace some indexes
263 that may have been created by version 1.4.2.
265 You should to access your MySQL database directly and remove any indexes
266 with a name ending in "_key_retired_idx". You should then re-add them with
267 the same spec except the key column name needs a size. So an index on
268 "_user (__retired, _name)" should become "_user (__retired, _name(255))".
271 Migrating from 1.4.x to 1.4.2
272 =============================
274 You should run the "roundup-admin migrate" command for your tracker once
275 you've installed the latest codebase. 
277 Do this before you use the web, command-line or mail interface and before
278 any users access the tracker.
280 This command will respond with either "Tracker updated" (if you've not
281 previously run it on an RDBMS backend) or "No migration action required"
282 (if you have run it, or have used another interface to the tracker,
283 or are using anydbm).
285 It's safe to run this even if it's not required, so just get into the
286 habit.
289 Migrating from 1.3.3 to 1.4.0
290 =============================
292 Value of the "refwd_re" tracker configuration option (section "mailgw")
293 is treated as UTF-8 string.  In previous versions, it was ISO8859-1.
295 If you have running trackers based on the classic template, please
296 update the messagesummary detector as follows::
298     --- detectors/messagesummary.py 17 Apr 2003 03:26:38 -0000      1.1
299     +++ detectors/messagesummary.py 3 Apr 2007 06:47:21 -0000       1.2
300     @@ -8,7 +8,7 @@
301      if newvalues.has_key('summary') or not newvalues.has_key('content'):
302          return
304     -    summary, content = parseContent(newvalues['content'], 1, 1)
305     +    summary, content = parseContent(newvalues['content'], config=db.config)
306      newvalues['summary'] = summary
308 In the latest version we have added some database indexes to the
309 SQL-backends (mysql, postgresql, sqlite) for speeding up building the
310 roundup-index for full-text search. We recommend that you create the
311 following database indexes on the database by hand::
313  CREATE INDEX words_by_id ON __words (_textid)
314  CREATE UNIQUE INDEX __textids_by_props ON __textids (_class, _itemid, _prop)
316 Migrating from 1.2.x to 1.3.0
317 =============================
319 1.3.0 Web interface changes
320 ---------------------------
322 Some of the HTML files in the "classic" and "minimal" tracker templates
323 were changed to fix some bugs and clean them up. You may wish to compare
324 them to the HTML files in your tracker and apply any changes.
327 Migrating from 1.1.2 to 1.2.0
328 =============================
330 1.2.0 Sorting and grouping by multiple properties
331 -------------------------------------------------
333 Starting with this version, sorting and grouping by multiple properties
334 is possible. This means that request.sort and request.group are now
335 lists. This is reflected in several places:
337  * ``renderWith`` now has list attributes for ``sort`` and ``group``,
338    where you previously wrote::
339    
340     renderWith(... sort=('-', 'activity'), group=('+', 'priority')
342    you write now::
344     renderWith(... sort=[('-', 'activity')], group=[('+', 'priority')]
346  * In templates that permit to edit sorting/grouping, request.sort and
347    request.group are (possibly empty) lists. You can now sort and group
348    by multiple attributes. For an example, see the classic template. You
349    may want search for the variable ``n_sort`` which can be set to the
350    number of sort/group properties.
352  * Templates that diplay new headlines for each group of items with
353    equal group properties can now use the modified ``batch.propchanged``
354    method that can take several properties which are checked for
355    changes. See the example in the classic template which makes use of
356    ``batch.propchanged``.
358 Migrating from 1.1.0 to 1.1.1
359 =============================
361 1.1.1 "Clear this message"
362 --------------------------
364 In 1.1.1, the standard ``page.html`` template includes a "clear this message"
365 link in the green "ok" message bar that appears after a successful edit
366 (or other) action.
368 To include this in your tracker, change the following in your ``page.html``
369 template::
371  <p tal:condition="options/ok_message | nothing" class="ok-message"
372     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
374 to be::
376  <p tal:condition="options/ok_message | nothing" class="ok-message">
377    <span tal:repeat="m options/ok_message"
378       tal:content="structure string:$m <br/ > " />
379     <a class="form-small" tal:attributes="href request/current_url"
380        i18n:translate="">clear this message</a>
381  </p>
384 If you implemented the "clear this message" in your 1.1.0 tracker, then you
385 should change it to the above and it will work much better!
388 Migrating from 1.0.x to 1.1.0
389 =============================
391 1.1 Login "For Session Only"
392 ----------------------------
394 In 1.1, web logins are alive for the length of a session only, *unless* you
395 add the following to the login form in your tracker's ``page.html``::
397     <input type="checkbox" name="remember" id="remember">
398     <label for="remember" i18n:translate="">Remember me?</label><br>
400 See the classic tracker ``page.html`` if you're unsure where this should
401 go.
404 1.1 Query Display Name
405 ----------------------
407 The ``dispname`` web variable has been renamed ``@dispname`` to avoid
408 clashing with other variables of the same name. If you are using the
409 display name feature, you will need to edit your tracker's ``page.html``
410 and ``issue.index.html`` pages to change ``dispname`` to ``@dispname``.
412 A side-effect of this change is that the renderWith method used in the
413 ``home.html`` page may now take a dispname argument.
416 1.1 "Clear this message"
417 ------------------------
419 In 1.1, the standard ``page.html`` template includes a "clear this message"
420 link in the green "ok" message bar that appears after a successful edit
421 (or other) action.
423 To include this in your tracker, change the following in your ``page.html``
424 template::
426  <p tal:condition="options/ok_message | nothing" class="ok-message"
427     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
429 to be::
431  <p tal:condition="options/ok_message | nothing" class="ok-message">
432    <span tal:repeat="m options/ok_message"
433       tal:content="structure string:$m <br/ > " />
434     <a class="form-small" tal:attributes="href string:issue${context/id}"
435        i18n:translate="">clear this message</a>
436  </p>
439 Migrating from 0.8.x to 1.0
440 ===========================
442 1.0 New Query Permissions
443 -------------------------
445 New permissions are defined for query editing and viewing. To include these
446 in your tracker, you need to add these lines to your tracker's
447 ``schema.py``::
449  # Users should be able to edit and view their own queries. They should also
450  # be able to view any marked as not private. They should not be able to
451  # edit others' queries, even if they're not private
452  def view_query(db, userid, itemid):
453      private_for = db.query.get(itemid, 'private_for')
454      if not private_for: return True
455      return userid == private_for
456  def edit_query(db, userid, itemid):
457      return userid == db.query.get(itemid, 'creator')
458  p = db.security.addPermission(name='View', klass='query', check=view_query,
459      description="User is allowed to view their own and public queries")
460  db.security.addPermissionToRole('User', p)
461  p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
462      description="User is allowed to edit their queries")
463  db.security.addPermissionToRole('User', p)
464  p = db.security.addPermission(name='Create', klass='query',
465      description="User is allowed to create queries")
466  db.security.addPermissionToRole('User', p)
468 and then remove 'query' from the line::
470  # Assign the access and edit Permissions for issue, file and message
471  # to regular users now
472  for cl in 'issue', 'file', 'msg', 'query', 'keyword':
474 so it looks like::
476  for cl in 'issue', 'file', 'msg', 'keyword':
479 Migrating from 0.8.0 to 0.8.3
480 =============================
482 0.8.3 Nosy Handling Changes
483 ---------------------------
485 A change was made to fix a bug in the ``nosyreaction.py`` standard
486 detector. To incorporate this fix in your trackers, you will need to copy
487 the ``nosyreaction.py`` file from the ``templates/classic/detectors``
488 directory of the source to your tracker's ``templates`` directory.
490 If you have modified the ``nosyreaction.py`` file from the standard
491 version, you will need to roll your changes into the new file.
494 Migrating from 0.7.1 to 0.8.0
495 =============================
497 You *must* fully uninstall previous Roundup version before installing
498 Roundup 0.8.0.  If you don't do that, ``roundup-admin install``
499 command may fail to function properly.
501 0.8.0 Backend changes
502 ---------------------
504 Backends 'bsddb' and 'bsddb3' are removed.  If you are using one of these,
505 you *must* migrate to another backend before upgrading.
508 0.8.0 API changes
509 -----------------
511 Class.safeget() was removed from the API. Test your item ids before calling
512 Class.get() instead.
515 0.8.0 New tracker layout
516 ------------------------
518 The ``config.py`` file has been replaced by ``config.ini``. You may use the
519 roundup-admin command "genconfig" to generate a new config file::
521   roundup-admin genconfig <tracker home>/config.ini
523 and modify the values therein based on the contents of your old config.py.
524 In most cases, the names of the config variables are the same.
526 The ``select_db.py`` file has been replaced by a file in the ``db``
527 directory called ``backend_name``. As you might guess, this file contains
528 just the name of the backend. To figure what the contents of yours should
529 be, use the following table:
531   ================================ =========================
532   ``select_db.py`` contents        ``backend_name`` contents
533   ================================ =========================
534   from back_anydbm import ...      anydbm
535   from back_metakit import ...     metakit
536   from back_sqlite import ...      sqlite
537   from back_mysql import ...       mysql
538   from back_postgresql import ...  postgresql
539   ================================ =========================
541 The ``dbinit.py`` file has been split into two new files,
542 ``initial_data.py`` and ``schema.py``. The contents of this file are:
544 ``initial_data.py``
545   You don't need one of these as your tracker is already initialised.
547 ``schema.py``
548   Copy the body of the ``def open(name=None)`` function from your old
549   tracker's ``dbinit.py`` file to this file. As the lines you're copying
550   aren't part of a function definition anymore, one level of indentation
551   needs to be removed (remove only the leading four spaces on each
552   line). 
554   The first few lines -- those starting with ``from roundup.hyperdb
555   import ...`` and the ``db = Database(config, name)`` line -- don't
556   need to be copied. Neither do the last few lines -- those starting
557   with ``import detectors``, down to ``return db`` inclusive.
559 You may remove the ``__init__.py`` module from the "detectors" directory as
560 it is no longer used.
562 There's a new way to write extension code for Roundup. If you have code in
563 an ``interfaces.py`` file you should move it. See the `customisation
564 documentation`_ for information about how extensions are now written.
565 Note that some older trackers may use ``interfaces.py`` to customise the
566 mail gateway behaviour. You will need to keep your ``interfaces.py`` file
567 if this is the case.
570 0.8.0 Permissions Changes
571 -------------------------
573 The creation of a new item in the user interfaces is now controlled by the
574 "Create" Permission. You will need to add an assignment of this Permission
575 to your users who are allowed to create items. The most common form of this
576 is the following in your ``schema.py`` added just under the current
577 assignation of the Edit Permission::
579     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
580         p = db.security.getPermission('Create', cl)
581         db.security.addPermissionToRole('User', p)
583 You will need to explicitly let anonymous users access the web interface so
584 that regular users are able to see the login form. Note that almost all
585 trackers will need this Permission. The only situation where it's not
586 required is in a tracker that uses an HTTP Basic Authenticated front-end.
587 It's enabled by adding to your ``schema.py``::
589     p = db.security.getPermission('Web Access')
590     db.security.addPermissionToRole('Anonymous', p)
592 Finally, you will need to enable permission for your users to edit their
593 own details by adding the following to ``schema.py``::
595     # Users should be able to edit their own details. Note that this
596     # permission is limited to only the situation where the Viewed or
597     # Edited item is their own.
598     def own_record(db, userid, itemid):
599         '''Determine whether the userid matches the item being accessed.'''
600         return userid == itemid
601     p = db.security.addPermission(name='View', klass='user', check=own_record,
602         description="User is allowed to view their own user details")
603     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
604         description="User is allowed to edit their own user details")
605     db.security.addPermissionToRole('User', p)
608 0.8.0 Use of TemplatingUtils
609 ----------------------------
611 If you used custom python functions in TemplatingUtils, they must
612 be moved from interfaces.py to a new file in the ``extensions`` directory. 
614 Each Function that should be available through TAL needs to be defined
615 as a toplevel function in the newly created file. Furthermore you
616 add an inititialization function, that registers the functions with the 
617 tracker.
619 If you find this too tedious, donfu wrote an automatic init function that
620 takes an existing TemplatingUtils class, and registers all class methods
621 that do not start with an underscore. The following hack should be placed
622 in the ``extensions`` directory alongside other extensions::
624     class TemplatingUtils:
625          # copy from interfaces.py
627     def init(tracker):
628          util = TemplatingUtils()
630          def setClient(tu):
631              util.client = tu.client
632              return util
634          def execUtil(name):
635              return lambda tu, *args, **kwargs: \
636                      getattr(setClient(tu), name)(*args, **kwargs)
638          for name in dir(util):
639              if callable(getattr(util, name)) and not name.startswith('_'):
640                   tracker.registerUtil(name, execUtil(name))
643 0.8.0 Logging Configuration
644 ---------------------------
646 See the `administration guide`_ for information about configuring the new
647 logging implemented in 0.8.0.
650 Migrating from 0.7.2 to 0.7.3
651 =============================
653 0.7.3 Configuration
654 -------------------
656 If you choose, you may specify the directory from which static files are
657 served (those which use the URL component ``@@file``). Currently the
658 directory defaults to the ``TEMPLATES`` configuration variable. You may
659 define a new variable, ``STATIC_FILES`` which overrides this value for
660 static files.
663 Migrating from 0.7.0 to 0.7.2
664 =============================
666 0.7.2 DEFAULT_TIMEZONE is now required
667 --------------------------------------
669 The DEFAULT_TIMEZONE configuration variable is now required. Add the
670 following to your tracker's ``config.py`` file::
672     # You may specify a different default timezone, for use when users do not
673     # choose their own in their settings.
674     DEFAULT_TIMEZONE = 0            # specify as numeric hour offest
677 Migrating from 0.7.0 to 0.7.1
678 =============================
680 0.7.1 Permission assignments
681 ----------------------------
683 If you allow anonymous access to your tracker, you might need to assign
684 some additional View (or Edit if your tracker is that open) permissions
685 to the "anonymous" user. To do so, find the code in your ``dbinit.py`` that
686 says::
688     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
689         p = db.security.getPermission('View', cl)
690         db.security.addPermissionToRole('User', p)
691         p = db.security.getPermission('Edit', cl)
692         db.security.addPermissionToRole('User', p)
693     for cl in 'priority', 'status':
694         p = db.security.getPermission('View', cl)
695         db.security.addPermissionToRole('User', p)
697 Add add a line::
699         db.security.addPermissionToRole('Anonymous', p)
701 next to the existing ``'User'`` lines for the Permissions you wish to
702 assign to the anonymous user.
705 Migrating from 0.6 to 0.7
706 =========================
708 0.7.0 Permission assignments
709 ----------------------------
711 Due to a change in the rendering of web widgets, permissions are now
712 checked on Classes where they previously weren't (this is a good thing).
714 You will need to add some additional Permission assignments for your
715 regular users, or some displays will break. After the following in your 
716 tracker's ``dbinit.py``::
718     # Assign the access and edit Permissions for issue, file and message
719     # to regular users now
720     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
721         p = db.security.getPermission('View', cl)
722         db.security.addPermissionToRole('User', p)
723         p = db.security.getPermission('Edit', cl)
724         db.security.addPermissionToRole('User', p)
726 add::
728     for cl in 'priority', 'status':
729         p = db.security.getPermission('View', cl)
730         db.security.addPermissionToRole('User', p)
733 0.7.0 Getting the current user id
734 ---------------------------------
736 The Database.curuserid attribute has been removed.
738 Any code referencing this attribute should be replaced with a
739 call to Database.getuid().
742 0.7.0 ZRoundup changes
743 ----------------------
745 The templates in your tracker's html directory will need updating if you
746 wish to use ZRoundup. If you've not modified those files (or some of them),
747 you may just copy the new versions from the Roundup source in the
748 templates/classic/html directory.
750 If you have modified the html files, then you'll need to manually edit them
751 to change all occurances of special form variables from using the colon ":"
752 special character to the at "@" special character. That is, variables such
753 as::
755   :action :required :template :remove:messages ...
757 should become::
759   @action @required @template @remove@messages ...
761 Note that ``tal:`` statements are unaffected. So are TAL expression type
762 prefixes such as ``python:`` and ``string:``. Please ask on the
763 roundup-users mailing list for help if you're unsure.
766 0.7.0 Edit collision detection
767 ------------------------------
769 Roundup now detects collisions with editing in the web interface (that is,
770 two people editing the same item at the same time).
772 You must copy the ``_generic.collision.html`` file from Roundup source in
773 the ``templates/classic/html`` directory. to your tracker's ``html``
774 directory.
777 Migrating from 0.6.x to 0.6.3
778 =============================
780 0.6.3 Configuration
781 -------------------
783 You will need to copy the file::
785   templates/classic/detectors/__init__.py
787 to your tracker's ``detectors`` directory, replacing the one already there.
788 This fixes a couple of bugs in that file.
792 Migrating from 0.5 to 0.6
793 =========================
796 0.6.0 Configuration
797 -------------------
799 Introduced EMAIL_FROM_TAG config variable. This value is inserted into
800 the From: line of nosy email. If the sending user is "Foo Bar", the
801 From: line is usually::
803      "Foo Bar" <issue_tracker@tracker.example>
805 the EMAIL_FROM_TAG goes inside the "Foo Bar" quotes like so::
807      "Foo Bar EMAIL_FROM_TAG" <issue_tracker@tracker.example>
809 I've altered the mechanism in the detectors __init__.py module so that it
810 doesn't cross-import detectors from other trackers (if you run more than one
811 in a single roundup-server). This change means that you'll need to copy the
812 __init__.py from roundup/templates/classic/detectors/__init__.py to your
813 <tracker home>/detectors/__init__.py. Don't worry, the "classic" __init__ is a
814 one-size-fits-all, so it'll work even if you've added/removed detectors.
816 0.6.0 Templating changes
817 ------------------------
819 The ``user.item`` template (in the tracker home "templates" directory)
820 needs to have the following hidden variable added to its form (between the
821 ``<form...>`` and ``</form>`` tags::
823   <input type="hidden" name=":template" value="item">
826 0.6.0 Form handling changes
827 ---------------------------
829 Roundup's form handling capabilities have been significantly expanded. This
830 should not affect users of 0.5 installations - but if you find you're
831 getting errors from form submissions, please ask for help on the Roundup
832 users mailing list:
834   http://lists.sourceforge.net/lists/listinfo/roundup-users
836 See the customisation doc section on `Form Values`__ for documentation of the
837 new form variables possible.
839 __ customizing.html#form-values
842 0.6.0 Multilingual character set support
843 ----------------------------------------
845 Added internationalization support. This is done via encoding all data
846 stored in roundup database to utf-8 (unicode encoding). To support utf-8 in
847 web interface you should add the folowing line to your tracker's html/page
848 and html/_generic.help files inside <head> tag::
849   
850     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
852 Since latin characters in utf-8 have the same codes as in ASCII table, this
853 modification is optional for users who use only plain latin characters. 
855 After this modification, you will be able to see and enter any world
856 character via web interface. Data received via mail interface also converted
857 to utf-8, however only new messages will be converted. If your roundup
858 database contains some of non-ASCII characters in one of 8-bit encoding,
859 they will not be visible in new unicode environment. Some of such data (e.g.
860 user names, keywords, etc)  can be edited by administrator, the others
861 (e.g. messages' contents) is not editable via web interface. Currently there
862 is no tool for converting such data, the only solution is to close
863 appropriate old issues and create new ones with the same content.
866 0.6.0 User timezone support
867 ---------------------------
869 From version 0.6.0 roundup supports displaying of Date data in user' local
870 timezone if he/she has provided timezone information. To make it possible
871 some modification to tracker's schema and HTML templates are required.
872 First you must add string property 'timezone' to user class in dbinit.py
873 like this::
874   
875     user = Class(db, "user", 
876                     username=String(),   password=Password(),
877                     address=String(),    realname=String(), 
878                     phone=String(),      organisation=String(),
879                     alternate_addresses=String(),
880                     queries=Multilink('query'), roles=String(),
881                     timezone=String())
882   
883 And second - html interface. Add following lines to
884 $TRACKER_HOME/html/user.item template::
885   
886      <tr>
887       <th>Timezone</th>
888       <td tal:content="structure context/timezone/field">timezone</td>
889      </tr>
891 After that all users should be able to provide their timezone information.
892 Timezone should be a positive or negative integer - offset from GMT.
894 After providing timezone, roundup will show all dates values, found in web
895 and mail interfaces in local time. It will also accept any Date info in
896 local time, convert and store it in GMT.
899 0.6.0 Search page structure
900 ---------------------------
902 In order to accomodate query editing the search page has been restructured. If
903 you want to provide your users with query editing, you should update your
904 search page using the macros detailed in the customisation doc section
905 `Searching on categories`__.
907 __ customizing.html#searching-on-categories
909 Also, the url field in the query class no longer starts with a '?'. You'll need
910 to remove this question mark from the url field to support queries. There's
911 a script in the "tools" directory called ``migrate-queries.py`` that should
912 automatically change any existing queries for you. As always, make a backup
913 of your database before running such a script.
916 0.6.0 Notes for metakit backend users
917 -------------------------------------
919 Roundup 0.6.0 introduced searching on ranges of dates and intervals. To
920 support it, some modifications to interval storing routine were made. So if
921 your tracker uses metakit backend and your db schema contains intervals
922 property, searches on that property will not be accurate for db items that
923 was stored before roundup' upgrade. However all new records should be
924 searchable on intervals.
926 It is possible to convert your database to new format: you can export and
927 import back all your data (consult "Migrating backends" in "Maintenance"
928 documentation). After this operation all your interval properties should
929 become searchable.
931 Users of backends others than metakit should not worry about this issue.
934 Migrating from 0.4.x to 0.5.0
935 =============================
937 This has been a fairly major revision of Roundup:
939 1. Brand new, much more powerful, flexible, tasty and nutritious templating.
940    Unfortunately, this means all your current templates are useless. Hopefully
941    the new documentation and examples will be enough to help you make the
942    transition. Please don't hesitate to ask on roundup-users for help (or
943    complete conversions if you're completely stuck)!
944 2. The database backed got a lot more flexible, allowing Metakit and SQL
945    databases! The only decent SQL database implemented at present is sqlite,
946    but others shouldn't be a whole lot more work.
947 3. A brand new, highly flexible and much more robust security system including
948    a system of Permissions, Roles and Role assignments to users. You may now
949    define your own Permissions that may be checked in CGI transactions.
950 4. Journalling has been made less storage-hungry, so has been turned on
951    by default *except* for author, recipient and nosy link/unlink events. You
952    are advised to turn it off in your trackers too.
953 5. We've changed the terminology from "instance" to "tracker", to ease the
954    learning curve/impact for new users.
955 6. Because of the above changes, the tracker configuration has seen some
956    major changes. See below for the details.
958 Please, **back up your database** before you start the migration process. This
959 is as simple as copying the "db" directory and all its contents from your
960 tracker to somewhere safe.
963 0.5.0 Configuration
964 -------------------
966 First up, rename your ``instance_config.py`` file to just ``config.py``.
968 Then edit your tracker's ``__init__.py`` module. It'll currently look
969 like this::
971  from instance_config import *
972  try:
973      from dbinit import *
974  except ImportError:
975      pass # in installdir (probably :)
976  from interfaces import *
978 and it needs to be::
980  import config
981  from dbinit import open, init
982  from interfaces import Client, MailGW
984 Due to the new templating having a top-level ``page`` that defines links for
985 searching, indexes, adding items etc, the following variables are no longer
986 used:
988 - HEADER_INDEX_LINKS
989 - HEADER_ADD_LINKS
990 - HEADER_SEARCH_LINKS
991 - SEARCH_FILTERS
992 - DEFAULT_INDEX
993 - UNASSIGNED_INDEX
994 - USER_INDEX
995 - ISSUE_FILTER
997 The new security implementation will require additions to the dbinit module,
998 but also removes the need for the following tracker config variables:
1000 - ANONYMOUS_ACCESS
1001 - ANONYMOUS_REGISTER
1003 but requires two new variables which define the Roles assigned to users who
1004 register through the web and e-mail interfaces:
1006 - NEW_WEB_USER_ROLES
1007 - NEW_EMAIL_USER_ROLES
1009 in both cases, 'User' is a good initial setting. To emulate
1010 ``ANONYMOUS_ACCESS='deny'``, remove all "View" Permissions from the
1011 "Anonymous" Role. To emulate ``ANONYMOUS_REGISTER='deny'``, remove the "Web
1012 Registration" and/or the "Email Registration" Permission from the "Anonymous"
1013 Role. See the section on customising security in the `customisation
1014 documentation`_ for more information.
1016 Finally, the following config variables have been renamed to make more sense:
1018 - INSTANCE_HOME -> TRACKER_HOME
1019 - INSTANCE_NAME -> TRACKER_NAME
1020 - ISSUE_TRACKER_WEB -> TRACKER_WEB
1021 - ISSUE_TRACKER_EMAIL -> TRACKER_EMAIL
1024 0.5.0 Schema Specification
1025 --------------------------
1027 0.5.0 Database backend changes
1028 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1030 Your select_db module in your tracker has changed a fair bit. Where it used
1031 to contain::
1033  # WARNING: DO NOT EDIT THIS FILE!!!
1034  from roundup.backends.back_anydbm import Database
1036 it must now contain::
1038  # WARNING: DO NOT EDIT THIS FILE!!!
1039  from roundup.backends.back_anydbm import Database, Class, FileClass, IssueClass
1041 Yes, I realise the irony of the "DO NOT EDIT THIS FILE" statement :)
1042 Note the addition of the Class, FileClass, IssueClass imports. These are very
1043 important, as they're going to make the next change work too. You now need to
1044 modify the top of the dbinit module in your tracker from::
1046  import instance_config
1047  from roundup import roundupdb
1048  from select_db import Database
1050  from roundup.roundupdb import Class, FileClass
1052  class Database(roundupdb.Database, select_db.Database):
1053      ''' Creates a hybrid database from:
1054           . the selected database back-end from select_db
1055           . the roundup extensions from roundupdb
1056      '''
1057      pass
1059  class IssueClass(roundupdb.IssueClass):
1060      ''' issues need the email information
1061      '''
1062      pass
1064 to::
1066  import config
1067  from select_db import Database, Class, FileClass, IssueClass
1069 Yes, remove the Database and IssueClass definitions and those other imports.
1070 They're not needed any more!
1072 Look for places in dbinit.py where ``instance_config`` is used too, and
1073 rename them ``config``.
1076 0.5.0 Journalling changes
1077 ~~~~~~~~~~~~~~~~~~~~~~~~~
1079 Journalling has been optimised for storage. Journalling of links has been
1080 turned back on by default. If your tracker has a large user base, you may wish
1081 to turn off journalling of nosy list, message author and message recipient
1082 link and unlink events. You do this by adding ``do_journal='no'`` to the Class
1083 initialisation in your dbinit. For example, your *msg* class initialisation
1084 probably looks like this::
1086     msg = FileClass(db, "msg",
1087                     author=Link("user"), recipients=Multilink("user"),
1088                     date=Date(),         summary=String(),
1089                     files=Multilink("file"),
1090                     messageid=String(),  inreplyto=String())
1092 to turn off journalling of author and recipient link events, add
1093 ``do_journal='no'`` to the ``author=Link("user")`` part of the statement,
1094 like so::
1096     msg = FileClass(db, "msg",
1097                     author=Link("user", do_journal='no'),
1098                     recipients=Multilink("user", do_journal='no'),
1099                     date=Date(),         summary=String(),
1100                     files=Multilink("file"),
1101                     messageid=String(),  inreplyto=String())
1103 Nosy list link event journalling is actually turned off by default now. If you
1104 want to turn it on, change to your issue class' nosy list, change its
1105 definition from::
1107     issue = IssueClass(db, "issue",
1108                     assignedto=Link("user"), topic=Multilink("keyword"),
1109                     priority=Link("priority"), status=Link("status"))
1111 to::
1113     issue = IssueClass(db, "issue", nosy=Multilink("user", do_journal='yes'),
1114                     assignedto=Link("user"), topic=Multilink("keyword"),
1115                     priority=Link("priority"), status=Link("status"))
1117 noting that your definition of the nosy Multilink will override the normal one.
1120 0.5.0 User schema changes
1121 ~~~~~~~~~~~~~~~~~~~~~~~~~
1123 Users have two more properties, "queries" and "roles". You'll have something
1124 like this in your dbinit module now::
1126     user = Class(db, "user",
1127                     username=String(),   password=Password(),
1128                     address=String(),    realname=String(),
1129                     phone=String(),      organisation=String(),
1130                     alternate_addresses=String())
1131     user.setkey("username")
1133 and you'll need to add the new properties and the new "query" class to it
1134 like so::
1136     query = Class(db, "query",
1137                     klass=String(),     name=String(),
1138                     url=String())
1139     query.setkey("name")
1141     # Note: roles is a comma-separated string of Role names
1142     user = Class(db, "user",
1143                     username=String(),   password=Password(),
1144                     address=String(),    realname=String(),
1145                     phone=String(),      organisation=String(),
1146                     alternate_addresses=String(),
1147                     queries=Multilink('query'), roles=String())
1148     user.setkey("username")
1150 The "queries" property is used to store off the user's favourite database
1151 queries. The "roles" property is explained below in `0.5.0 Security
1152 Settings`_.
1155 0.5.0 Security Settings
1156 ~~~~~~~~~~~~~~~~~~~~~~~
1158 See the `security documentation`_ for an explanation of how the new security
1159 system works. In a nutshell though, the security is handled as a four step
1160 process:
1162 1. Permissions are defined as having a name and optionally a hyperdb class
1163    they're specific to,
1164 2. Roles are defined that have one or more Permissions,
1165 3. Users are assigned Roles in their "roles" property, and finally
1166 4. Roundup checks that users have appropriate Permissions at appropriate times
1167    (like editing issues).
1169 Your tracker dbinit module's *open* function now has to define any
1170 Permissions that are specific to your tracker, and also the assignment
1171 of Permissions to Roles. At the moment, your open function
1172 ends with::
1174     import detectors
1175     detectors.init(db)
1177     return db
1179 and what we need to do is insert some commands that will set up the security
1180 parameters. Right above the ``import detectors`` line, you'll want to insert
1181 these lines::
1183     #
1184     # SECURITY SETTINGS
1185     #
1186     # new permissions for this schema
1187     for cl in 'issue', 'file', 'msg', 'user':
1188         db.security.addPermission(name="Edit", klass=cl,
1189             description="User is allowed to edit "+cl)
1190         db.security.addPermission(name="View", klass=cl,
1191             description="User is allowed to access "+cl)
1193     # Assign the access and edit permissions for issue, file and message
1194     # to regular users now
1195     for cl in 'issue', 'file', 'msg':
1196         p = db.security.getPermission('View', cl)
1197         db.security.addPermissionToRole('User', p)
1198         p = db.security.getPermission('Edit', cl)
1199         db.security.addPermissionToRole('User', p)
1200     # and give the regular users access to the web and email interface
1201     p = db.security.getPermission('Web Access')
1202     db.security.addPermissionToRole('User', p)
1203     p = db.security.getPermission('Email Access')
1204     db.security.addPermissionToRole('User', p)
1206     # May users view other user information? Comment these lines out
1207     # if you don't want them to
1208     p = db.security.getPermission('View', 'user')
1209     db.security.addPermissionToRole('User', p)
1211     # Assign the appropriate permissions to the anonymous user's Anonymous
1212     # Role. Choices here are:
1213     # - Allow anonymous users to register through the web
1214     p = db.security.getPermission('Web Registration')
1215     db.security.addPermissionToRole('Anonymous', p)
1216     # - Allow anonymous (new) users to register through the email gateway
1217     p = db.security.getPermission('Email Registration')
1218     db.security.addPermissionToRole('Anonymous', p)
1219     # - Allow anonymous users access to the "issue" class of data
1220     #   Note: this also grants access to related information like files,
1221     #         messages, statuses etc that are linked to issues
1222     #p = db.security.getPermission('View', 'issue')
1223     #db.security.addPermissionToRole('Anonymous', p)
1224     # - Allow anonymous users access to edit the "issue" class of data
1225     #   Note: this also grants access to create related information like
1226     #         files and messages etc that are linked to issues
1227     #p = db.security.getPermission('Edit', 'issue')
1228     #db.security.addPermissionToRole('Anonymous', p)
1230     # oh, g'wan, let anonymous access the web interface too
1231     p = db.security.getPermission('Web Access')
1232     db.security.addPermissionToRole('Anonymous', p)
1234 Note in the comments there the places where you might change the permissions
1235 to restrict users or grant users more access. If you've created additional
1236 classes that users should be able to edit and view, then you should add them
1237 to the "new permissions for this schema" section at the start of the security
1238 block. Then add them to the "Assign the access and edit permissions" section
1239 too, so people actually have the new Permission you've created.
1241 One final change is needed that finishes off the security system's
1242 initialisation. We need to add a call to ``db.post_init()`` at the end of the
1243 dbinit open() function. Add it like this::
1245     import detectors
1246     detectors.init(db)
1248     # schema is set up - run any post-initialisation
1249     db.post_init()
1250     return db
1252 You may verify the setup of Permissions and Roles using the new
1253 "``roundup-admin security``" command.
1256 0.5.0 User changes
1257 ~~~~~~~~~~~~~~~~~~
1259 To support all those schema changes, you'll need to massage your user database
1260 a little too, to:
1262 1. make sure there's an "anonymous" user - this user is mandatory now and is
1263    the one that unknown users are logged in as.
1264 2. make sure all users have at least one Role.
1266 If you don't have the "anonymous" user, create it now with the command::
1268   roundup-admin create user username=anonymous roles=Anonymous
1270 making sure the capitalisation is the same as above. Once you've done that,
1271 you'll need to set the roles property on all users to a reasonable default.
1272 The admin user should get "Admin", the anonymous user "Anonymous"
1273 and all other users "User". The ``fixroles.py`` script in the tools directory
1274 will do this. Run it like so (where python is your python 2+ binary)::
1276   python tools/fixroles.py -i <tracker home> fixroles
1280 0.5.0 CGI interface changes
1281 ---------------------------
1283 The CGI interface code was completely reorganised and largely rewritten. The
1284 end result is that this section of your tracker interfaces module will need
1285 changing from::
1287  from roundup import cgi_client, mailgw
1288  from roundup.i18n import _
1289  
1290  class Client(cgi_client.Client):
1291      ''' derives basic CGI implementation from the standard module,
1292          with any specific extensions
1293      '''
1294      pass
1296 to::
1298  from roundup import mailgw
1299  from roundup.cgi import client
1300  
1301  class Client(client.Client): 
1302      ''' derives basic CGI implementation from the standard module,
1303          with any specific extensions
1304      '''
1305      pass
1307 You will also need to install the new version of roundup.cgi from the source
1308 cgi-bin directory if you're using it.
1311 0.5.0 HTML templating
1312 ---------------------
1314 You'll want to make a backup of your current tracker html directory. You
1315 should then copy the html directory from the Roundup source "classic" template
1316 and modify it according to your local schema changes.
1318 If you need help with the new templating system, please ask questions on the
1319 roundup-users mailing list (available through the roundup project page on
1320 sourceforge, http://roundup.sf.net/)
1323 0.5.0 Detectors
1324 ---------------
1326 The nosy reactor has been updated to handle the tracker not having an
1327 "assignedto" property on issues. You may want to copy it into your tracker's
1328 detectors directory. Chances are you've already fixed it though :)
1331 Migrating from 0.4.1 to 0.4.2
1332 =============================
1334 0.4.2 Configuration
1335 -------------------
1336 The USER_INDEX definition introduced in 0.4.1 was too restrictive in its
1337 allowing replacement of 'assignedto' with the user's userid. Users must change
1338 the None value of 'assignedto' to 'CURRENT USER' (the string, in quotes) for
1339 the replacement behaviour to occur now.
1341 The new configuration variables are:
1343 - EMAIL_KEEP_QUOTED_TEXT 
1344 - EMAIL_LEAVE_BODY_UNCHANGED
1345 - ADD_RECIPIENTS_TO_NOSY
1347 See the sample configuration files in::
1349  <roundup source>/roundup/templates/classic/instance_config.py
1351 and::
1353  <roundup source>/roundup/templates/extended/instance_config.py
1355 and the `customisation documentation`_ for information on how they're used.
1358 0.4.2 Changes to detectors
1359 --------------------------
1360 You will need to copy the detectors from the distribution into your instance
1361 home "detectors" directory. If you used the classic schema, the detectors
1362 are in::
1364  <roundup source>/roundup/templates/classic/detectors/
1366 If you used the extended schema, the detectors are in::
1368  <roundup source>/roundup/templates/extended/detectors/
1370 The change means that schema-specific code has been removed from the
1371 mail gateway and cgi interface and made into auditors:
1373 - nosyreactor.py has now got an updatenosy auditor which updates the nosy
1374   list with author, recipient and assignedto information.
1375 - statusauditor.py makes the unread or resolved -> chatting changes and
1376   presets the status of an issue to unread.
1378 There's also a bug or two fixed in the nosyreactor code.
1380 0.4.2 HTML templating changes
1381 -----------------------------
1382 The link() htmltemplate function now has a "showid" option for links and
1383 multilinks. When true, it only displays the linked item id as the anchor
1384 text. The link value is displayed as a tooltip using the title anchor
1385 attribute. To use in eg. the superseder field, have something like this::
1387    <td>
1388     <display call="field('superseder', showid=1)">
1389     <display call="classhelp('issue', 'id,title', label='list', width=500)">
1390     <property name="superseder">
1391      <br>View: <display call="link('superseder', showid=1)">
1392     </property>
1393    </td>
1395 The stylesheets have been cleaned up too. You may want to use the newer
1396 versions in::
1398  <roundup source>/roundup/templates/<template>/html/default.css
1402 Migrating from 0.4.0 to 0.4.1
1403 =============================
1405 0.4.1 Files storage
1406 -------------------
1408 Messages and files from newly created issues will be put into subdierectories
1409 in thousands e.g. msg123 will be put into files/msg/0/msg123, file2003
1410 will go into files/file/2/file2003. Previous messages are still found, but
1411 could be put into this structure.
1413 0.4.1 Configuration
1414 -------------------
1416 To allow more fine-grained access control, the variable used to check
1417 permission to auto-register users in the mail gateway is now called
1418 ANONYMOUS_REGISTER_MAIL rather than overloading ANONYMOUS_REGISTER. If the
1419 variable doesn't exist, then ANONYMOUS_REGISTER is tested as before.
1421 Configuring the links in the web header is now easier too. The following
1422 variables have been added to the classic instance_config.py::
1424   HEADER_INDEX_LINKS   - defines the "index" links to be made available
1425   HEADER_ADD_LINKS     - defines the "add" links
1426   DEFAULT_INDEX        - specifies the index view for DEFAULT
1427   UNASSIGNED_INDEX     - specifies the index view for UNASSIGNED
1428   USER_INDEX           - specifies the index view for USER
1430 See the <roundup source>/roundup/templates/classic/instance_config.py for more
1431 information - including how the variables are to be set up. Most users will
1432 just be able to copy the variables from the source to their instance home. If
1433 you've modified the header by changing the source of the interfaces.py file in
1434 the instance home, you'll need to remove that customisation and move it into
1435 the appropriate variables in instance_config.py.
1437 The extended schema has similar variables added too - see the source for more
1438 info.
1440 0.4.1 Alternate E-Mail Addresses
1441 --------------------------------
1443 If you add the property "alternate_addresses" to your user class, your users
1444 will be able to register alternate email addresses that they may use to
1445 communicate with roundup as. All email from roundup will continue to be sent
1446 to their primary address.
1448 If you have not edited the dbinit.py file in your instance home directory,
1449 you may simply copy the new dbinit.py file from the core code. If you used
1450 the classic schema, the interfaces file is in::
1452  <roundup source>/roundup/templates/classic/dbinit.py
1454 If you used the extended schema, the file is in::
1456  <roundup source>/roundup/templates/extended/dbinit.py 
1458 If you have modified your dbinit.py file, you need to edit the dbinit.py
1459 file in your instance home directory. Find the lines which define the user
1460 class::
1462     user = Class(db, "msg",
1463                     username=String(),   password=Password(),
1464                     address=String(),    realname=String(), 
1465                     phone=String(),      organisation=String(),
1466                     alternate_addresses=String())
1468 You will also want to add the property to the user's details page. The
1469 template for this is the "user.item" file in your instance home "html"
1470 directory. Similar to above, you may copy the file from the roundup source if
1471 you haven't modified it. Otherwise, add the following to the template::
1473    <display call="multiline('alternate_addresses')">
1475 with appropriate labelling etc. See the standard template for an idea.
1479 Migrating from 0.3.x to 0.4.0
1480 =============================
1482 0.4.0 Message-ID and In-Reply-To addition
1483 -----------------------------------------
1484 0.4.0 adds the tracking of messages by message-id and allows threading
1485 using in-reply-to. Most e-mail clients support threading using this
1486 feature, and we hope to add support for it to the web gateway. If you
1487 have not edited the dbinit.py file in your instance home directory, you may
1488 simply copy the new dbinit.py file from the core code. If you used the
1489 classic schema, the interfaces file is in::
1491  <roundup source>/roundup/templates/classic/dbinit.py
1493 If you used the extended schema, the file is in::
1495  <roundup source>/roundup/templates/extended/dbinit.py 
1497 If you have modified your dbinit.py file, you need to edit the dbinit.py
1498 file in your instance home directory. Find the lines which define the msg
1499 class::
1501     msg = FileClass(db, "msg",
1502                     author=Link("user"), recipients=Multilink("user"),
1503                     date=Date(),         summary=String(),
1504                     files=Multilink("file"))
1506 and add the messageid and inreplyto properties like so::
1508     msg = FileClass(db, "msg",
1509                     author=Link("user"), recipients=Multilink("user"),
1510                     date=Date(),         summary=String(),
1511                     files=Multilink("file"),
1512                     messageid=String(),  inreplyto=String())
1514 Also, configuration is being cleaned up. This means that your dbinit.py will
1515 also need to be changed in the open function. If you haven't changed your
1516 dbinit.py, the above copy will be enough. If you have, you'll need to change
1517 the line (round line 50)::
1519     db = Database(instance_config.DATABASE, name)
1521 to::
1523     db = Database(instance_config, name)
1526 0.4.0 Configuration
1527 --------------------
1528 ``TRACKER_NAME`` and ``EMAIL_SIGNATURE_POSITION`` have been added to the
1529 instance_config.py. The simplest solution is to copy the default values
1530 from template in the core source.
1532 The mail gateway now checks ``ANONYMOUS_REGISTER`` to see if unknown users
1533 are to be automatically registered with the tracker. If it is set to "deny"
1534 then unknown users will not have access. If it is set to "allow" they will be
1535 automatically registered with the tracker.
1538 0.4.0 CGI script roundup.cgi
1539 ----------------------------
1540 The CGI script has been updated with some features and a bugfix, so you should
1541 copy it from the roundup cgi-bin source directory again. Make sure you update
1542 the ROUNDUP_INSTANCE_HOMES after the copy.
1545 0.4.0 Nosy reactor
1546 ------------------
1547 The nosy reactor has also changed - copy the nosyreactor.py file from the core
1548 source::
1550    <roundup source>/roundup/templates/<template>/detectors/nosyreactor.py
1552 to your instance home "detectors" directory.
1555 0.4.0 HTML templating
1556 ---------------------
1557 The field() function was incorrectly implemented - links and multilinks now
1558 display as text fields when rendered using field(). To display a menu (drop-
1559 down or select box) you need to use the menu() function.
1563 Migrating from 0.2.x to 0.3.x
1564 =============================
1566 0.3.x Cookie Authentication changes
1567 -----------------------------------
1568 0.3.0 introduces cookie authentication - you will need to copy the
1569 interfaces.py file from the roundup source to your instance home to enable
1570 authentication. If you used the classic schema, the interfaces file is in::
1572  <roundup source>/roundup/templates/classic/interfaces.py
1574 If you used the extended schema, the file is in::
1576  <roundup source>/roundup/templates/extended/interfaces.py
1578 If you have modified your interfaces.Client class, you will need to take
1579 note of the login/logout functionality provided in roundup.cgi_client.Client
1580 (classic schema) or roundup.cgi_client.ExtendedClient (extended schema) and
1581 modify your instance code apropriately.
1584 0.3.x Password encoding
1585 -----------------------
1586 This release also introduces encoding of passwords in the database. If you
1587 have not edited the dbinit.py file in your instance home directory, you may
1588 simply copy the new dbinit.py file from the core code. If you used the
1589 classic schema, the interfaces file is in::
1591  <roundup source>/roundup/templates/classic/dbinit.py
1593 If you used the extended schema, the file is in::
1595  <roundup source>/roundup/templates/extended/dbinit.py
1598 If you have modified your dbinit.py file, you may use encoded passwords:
1600 1. Edit the dbinit.py file in your instance home directory
1601    a. At the first code line of the open() function::
1603        from roundup.hyperdb import String, Date, Link, Multilink
1605       alter to include Password, as so::
1607        from roundup.hyperdb import String, Password, Date, Link, Multilink
1609    b. Where the password property is defined (around line 66)::
1611        user = Class(db, "user", 
1612                        username=String(),   password=String(),
1613                        address=String(),    realname=String(), 
1614                        phone=String(),      organisation=String())
1615        user.setkey("username")
1617       alter the "password=String()" to "password=Password()"::
1619        user = Class(db, "user", 
1620                        username=String(),   password=Password(),
1621                        address=String(),    realname=String(), 
1622                        phone=String(),      organisation=String())
1623        user.setkey("username")
1625 2. Any existing passwords in the database will remain cleartext until they
1626    are edited. It is recommended that at a minimum the admin password be
1627    changed immediately::
1629       roundup-admin -i <instance home> set user1 password=<new password>
1632 0.3.x Configuration
1633 -------------------
1634 FILTER_POSITION, ANONYMOUS_ACCESS, ANONYMOUS_REGISTER have been added to
1635 the instance_config.py. Simplest solution is to copy the default values from
1636 template in the core source.
1638 MESSAGES_TO_AUTHOR has been added to the IssueClass in dbinit.py. Set to 'yes'
1639 to send nosy messages to the author. Default behaviour is to not send nosy
1640 messages to the author. You will need to add MESSAGES_TO_AUTHOR to your
1641 dbinit.py in your instance home.
1644 0.3.x CGI script roundup.cgi
1645 ----------------------------
1646 There have been some structural changes to the roundup.cgi script - you will
1647 need to install it again from the cgi-bin directory of the source
1648 distribution. Make sure you update the ROUNDUP_INSTANCE_HOMES after the
1649 copy.
1652 .. _`customisation documentation`: customizing.html
1653 .. _`security documentation`: security.html
1654 .. _`administration guide`: admin_guide.html