Code

- release preparation
[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.16 to 1.4.17
17 ===============================
19 There was a bug in 1.4.16 where files were unlinked from issues if a
20 mail without attachment was received via the mail interface. The
21 following script will list likely issues being affected by the bug.
22 The date in the script is the date of the 1.4.16 release. If you have
23 installed 1.4.16 later than this date, you can change the date
24 appropriately to your installation date. Run the script in the directory
25 of your tracker.
27 #!/usr/bin/python
28 import os
29 from roundup import instance
30 from roundup.date import Date
31 dir     = os.getcwd ()
32 tracker = instance.open (dir)
33 db      = tracker.open ('admin')
34 # you may want to change this to your install date to find less candidates
35 last_release = Date('2011-05-13')
36 affected = {}
37 for i in db.issue.getnodeids():
38     for j in db.issue.history(i):
39         if i in affected:
40             break
41         if j[1] < last_release or j[3] != 'set' or 'files' not in j[4]:
42             continue
43         for op, p in j[4]['files']:
44             if op == '-':
45                 affected [i] = 1
46                 break
47 print ', '.join(sorted(affected.iterkeys()))
49 To find out which files where attached before you can look in the
50 history of the affected issue.  For fixing issues you can re-attach the
51 files in question using the "set" command of roundup-admin, e.g., if the
52 list of files attached to an issue should be files 5, 17, 23 for issue42
53 you will set this using
55 roundup-admin -i /path/to/your/tracker set issue42 files=5,17,23
57 Migrating from 1.4.x to 1.4.17
58 ==============================
60 There is a new config-option `migrate_passwords` in section `web` to
61 auto-migrate passwords at web-login time to a more secure storage
62 scheme. Default for the new option is "yes" so if you don't want that
63 passwords are auto-migrated to a more secure password scheme on user
64 login, set this to "no" before running your tracker(s) after the
65 upgrade.
67 The standalone roundup-server now defaults to listening on localhost (no
68 longer on all network interfaces). This will not affect you if you're
69 already using a configuration file for roundup-server. If you are using
70 an empty setting for the `host` parameter in the config-file you should
71 explicitly put 0.0.0.0 there as the use of an empty string to specify
72 listening to all interfaces is deprecated and will go away in a future
73 version.  If you are starting the server without a configuration file
74 and want to explicitly listen to all network interface, you should
75 specify the -n option with the address `0.0.0.0`.
77 Searching now requires either read-permission without a check method, or
78 you will have to add a "Search" permission for a class or a list of
79 properties for a class (if you want to allow searching). For the classic
80 template (or other templates derived from it) you want to add the
81 following lines to your `schema.py` file::
83   p = db.security.addPermission(name='Search', klass='query')
84   db.security.addPermissionToRole('User', p)
86 This is needed, because for the `query` class users may view only their
87 own queries (or public queries). This is implemented with a `check`
88 method, therefore the default search permissions will not allow
89 searching and you'll have to add an explicit search permission.
90 If you have modified your schema, you can check if you're missing any
91 search permissions with the following script, run it in your tracker
92 directory, it will list for each Class and Property the roles that may
93 search for this property::
95     #!/usr/bin/python
96     import os
97     from roundup import instance
98     
99     tracker = instance.open(os.getcwd ())
100     db = tracker.open('admin')
101     
102     for cl in sorted(db.getclasses()):
103         print "Class:", cl
104         for p in sorted(db.getclass(cl).properties.keys()):
105             print "    Property:", p
106             roles = []
107             for role in sorted(db.security.role.iterkeys()):
108                 if db.security.roleHasSearchPermission(cl,p,role):
109                     roles.append(role)
110             print "        roles may search:", ', '.join(roles)
113 Migrating from 1.4.x to 1.4.12
114 ==============================
116 Item creation now checks the "Create" permission instead of the "Edit"
117 permission for individual properties. If you have modified your tracker
118 permissions from the default distribution, you should check that
119 "Create" permissions exist for all properties you want users to be able
120 to create.
123 Fixing some potential security holes
124 ------------------------------------
126 Enhanced checking was added to the user registration auditor. If you
127 run a public tracker you should update your tracker's
128 ``detectors/userauditor.py`` using the new code from
129 ``share/roundup/templates/classic/detectors/userauditor.py``. In most
130 cases you may just copy the file over, but if you've made changes to
131 the auditor in your tracker then you'll need to manually integrate
132 the new code.
134 Some HTML templates were found to have formatting security problems:
136 ``html/page.html``::
138   -tal:replace="request/user/username">username</span></b><br>
139   +tal:replace="python:request.user.username.plain(escape=1)">username</span></b><br>
141 ``html/_generic.help-list.html``::
143   -tal:content="structure python:item[prop]"></label>
144   +tal:content="python:item[prop]"></label>
146 The lines marked "+" should be added and lines marked "-" should be
147 deleted (minus the "+"/"-" signs).
150 Some HTML interface tweaks
151 --------------------------
153 You may wish to copy the ``user_utils.js`` and ``style.css` files from the
154 source distribution ``share/roundup/templates/classic/html/`` directory to the
155 ``html`` directory of your trackers as it includes a small improvement.
157 If you have made local changes to those files you'll need to manually work
158 the differences in to your versions or ignore the changes.
161 Migrating from 1.4.x to 1.4.11
162 ==============================
164 Close potential security hole
165 -----------------------------
167 If your tracker has untrusted users you should examine its ``schema.py``
168 file and look for the section granting the "Edit" permission to your users.
169 This should look something like::
171     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
172         description="User is allowed to edit their own user details")
174 and should be modified to restrict the list of properties they are allowed
175 to edit by adding the ``properties=`` section like::
177     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
178         properties=('username', 'password', 'address', 'realname', 'phone',
179             'organisation', 'alternate_addresses', 'queries', 'timezone'),
180         description="User is allowed to edit their own user details")
182 Most importantly the "roles" property should not be editable - thus not
183 appear in that list of properties.
186 Grant the "Register" permission to the Anonymous role
187 -----------------------------------------------------
189 A separate "Register" permission has been introduced to allow
190 anonymous users to register. This means you will need to add the
191 following to your tracker's ``schema.py`` to add the permission and
192 assign it to the Anonymous role (replacing any previously assigned
193 "Create user" permission for the Anonymous role)::
195   +db.security.addPermission(name='Register', klass='user',
196   +     description='User is allowed to register new user')
197  
198    # Assign the appropriate permissions to the anonymous user's Anonymous
199    # Role. Choices here are:
200    # - Allow anonymous users to register
201   -db.security.addPermissionToRole('Anonymous', 'Create', 'user')
202   +db.security.addPermissionToRole('Anonymous', 'Register', 'user')
204 The lines marked "+" should be added and lines marked "-" should be
205 deleted (minus the "+"/"-" signs).
207 You should also modify the ``html/page.html`` template to change the
208 permission tested there::
210    -tal:condition="python:request.user.hasPermission('Create', 'user')"
211    +tal:condition="python:request.user.hasPermission('Register', 'user')"
214 Generic class editor may now restore retired items
215 --------------------------------------------------
217 The instructions for doing so won't be present in your tracker unless you copy
218 the ``_generic.index.html`` template from the roundup distribution in
219 ``share/roundup/templates/classic/html`` to your tracker's ``html`` directory.
222 Migrating from 1.4.x to 1.4.9
223 =============================
225 Customized MailGW Class
226 -----------------------
228 If you have customized the MailGW class in your tracker: The new MailGW
229 class opens the database for each message in the method handle_message
230 (instance.open) instead of passing the opened database as a parameter to
231 the MailGW constructor. The old handle_message has been renamed to
232 _handle_message. The new method opens the database and wraps the call to
233 the old method into a try/finally.
235 Your customized MailGW class needs to mirror this behavior.
237 Fix the "remove" button in issue files and messages lists
238 ---------------------------------------------------------
240 The "remove" button(s) in the issue messages list needs to be altered. Find
241 the following in your tracker's ``html/issue.item.html`` template::
243   <td>
244    <form style="padding:0" tal:condition="context/is_edit_ok"
245          tal:attributes="action string:issue${context/id}">
246     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
248 and add ``method="POST"`` as shown below::
250   <td>
251    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
252          tal:attributes="action string:issue${context/id}">
253     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
255 Then also find::
257   <td>
258    <form style="padding:0" tal:condition="context/is_edit_ok"
259          tal:attributes="action string:issue${context/id}">
260     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
262 and add ``method="POST"`` as shown below::
264   <td>
265    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
266          tal:attributes="action string:issue${context/id}">
267     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
270 Fixing the "retire" button in user management list
271 --------------------------------------------------
273 If you made the change to the "reture" link in the user management list as
274 listed below in `Migrating from 1.4.x to 1.4.7`_ then you'll need to fix that
275 change by adding ``method="POST"`` to the ``<form>`` tag::
277      <form style="padding:0" method="POST"
278            tal:attributes="action string:user${user/id}">
279       <input type="hidden" name="@template" value="index">
280       <input type="hidden" name="@action" value="retire">
281       <input type="submit" value="retire" i18n:attributes="value">
282      </form>
285 Migrating from 1.4.x to 1.4.7
286 =============================
288 Several security issues were addressed in this release. Some aspects of your
289 trackers may no longer function depending on your local customisations. Core
290 functionality that will need to be modified:
292 Grant the "retire" permission to users for their queries
293 --------------------------------------------------------
295 Users will no longer be able to retire their own queries. To remedy this you
296 will need to add the following to your tracker's ``schema.py`` just under the
297 line that grants them permission to edit their own queries::
299    p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
300       description="User is allowed to edit their queries")
301    db.security.addPermissionToRole('User', p)
302  + p = db.security.addPermission(name='Retire', klass='query', check=edit_query,
303  +    description="User is allowed to retire their queries")
304  + db.security.addPermissionToRole('User', p)
305    p = db.security.addPermission(name='Create', klass='query',
306       description="User is allowed to create queries")
307    db.security.addPermissionToRole('User', p)
309 The lines marked "+" should be added, minus the "+" sign.
312 Fix the "retire" link in the users list for admin users
313 -------------------------------------------------------
315 The "retire" link found in the file ``html/user.index.html``::
317   <td tal:condition="context/is_edit_ok">
318    <a tal:attributes="href string:user${user/id}?@action=retire&@template=index"
319     i18n:translate="">retire</a>
321 Should be replaced with::
323   <td tal:condition="context/is_retire_ok">
324      <form style="padding:0" method="POST"
325            tal:attributes="action string:user${user/id}">
326       <input type="hidden" name="@template" value="index">
327       <input type="hidden" name="@action" value="retire">
328       <input type="submit" value="retire" i18n:attributes="value">
329      </form>
332 Fix for Python 2.6+ users
333 -------------------------
335 If you use Python 2.6 you should edit your tracker's
336 ``detectors/nosyreaction.py`` file to change::
338    import sets
340 at the top to::
342    from roundup.anypy.sets_ import set
344 and then all instances of ``sets.Set()`` to ``set()`` in the later code.
348 Trackers currently allowing HTML file uploading
349 -----------------------------------------------
351 Trackers which wish to continue to allow uploading of HTML content against issues
352 will need to set a new configuration variable in the ``[web]`` section of the
353 tracker's ``config.ini`` file:
355    # Setting this option enables Roundup to serve uploaded HTML
356    # file content *as HTML*. This is a potential security risk
357    # and is therefore disabled by default. Set to 'yes' if you
358    # trust *all* users uploading content to your tracker.
359    # Allowed values: yes, no
360    # Default: no
361    allow_html_file = no
365 Migrating from 1.4.2 to 1.4.3
366 =============================
368 If you are using the MySQL backend you will need to replace some indexes
369 that may have been created by version 1.4.2.
371 You should to access your MySQL database directly and remove any indexes
372 with a name ending in "_key_retired_idx". You should then re-add them with
373 the same spec except the key column name needs a size. So an index on
374 "_user (__retired, _name)" should become "_user (__retired, _name(255))".
377 Migrating from 1.4.x to 1.4.2
378 =============================
380 You should run the "roundup-admin migrate" command for your tracker once
381 you've installed the latest codebase. 
383 Do this before you use the web, command-line or mail interface and before
384 any users access the tracker.
386 This command will respond with either "Tracker updated" (if you've not
387 previously run it on an RDBMS backend) or "No migration action required"
388 (if you have run it, or have used another interface to the tracker,
389 or are using anydbm).
391 It's safe to run this even if it's not required, so just get into the
392 habit.
395 Migrating from 1.3.3 to 1.4.0
396 =============================
398 Value of the "refwd_re" tracker configuration option (section "mailgw")
399 is treated as UTF-8 string.  In previous versions, it was ISO8859-1.
401 If you have running trackers based on the classic template, please
402 update the messagesummary detector as follows::
404     --- detectors/messagesummary.py 17 Apr 2003 03:26:38 -0000      1.1
405     +++ detectors/messagesummary.py 3 Apr 2007 06:47:21 -0000       1.2
406     @@ -8,7 +8,7 @@
407      if newvalues.has_key('summary') or not newvalues.has_key('content'):
408          return
410     -    summary, content = parseContent(newvalues['content'], 1, 1)
411     +    summary, content = parseContent(newvalues['content'], config=db.config)
412      newvalues['summary'] = summary
414 In the latest version we have added some database indexes to the
415 SQL-backends (mysql, postgresql, sqlite) for speeding up building the
416 roundup-index for full-text search. We recommend that you create the
417 following database indexes on the database by hand::
419  CREATE INDEX words_by_id ON __words (_textid);
420  CREATE UNIQUE INDEX __textids_by_props ON __textids (_class, _itemid, _prop);
422 Migrating from 1.2.x to 1.3.0
423 =============================
425 1.3.0 Web interface changes
426 ---------------------------
428 Some of the HTML files in the "classic" and "minimal" tracker templates
429 were changed to fix some bugs and clean them up. You may wish to compare
430 them to the HTML files in your tracker and apply any changes.
433 Migrating from 1.1.2 to 1.2.0
434 =============================
436 1.2.0 Sorting and grouping by multiple properties
437 -------------------------------------------------
439 Starting with this version, sorting and grouping by multiple properties
440 is possible. This means that request.sort and request.group are now
441 lists. This is reflected in several places:
443  * ``renderWith`` now has list attributes for ``sort`` and ``group``,
444    where you previously wrote::
445    
446     renderWith(... sort=('-', 'activity'), group=('+', 'priority')
448    you write now::
450     renderWith(... sort=[('-', 'activity')], group=[('+', 'priority')]
452  * In templates that permit to edit sorting/grouping, request.sort and
453    request.group are (possibly empty) lists. You can now sort and group
454    by multiple attributes. For an example, see the classic template. You
455    may want search for the variable ``n_sort`` which can be set to the
456    number of sort/group properties.
458  * Templates that diplay new headlines for each group of items with
459    equal group properties can now use the modified ``batch.propchanged``
460    method that can take several properties which are checked for
461    changes. See the example in the classic template which makes use of
462    ``batch.propchanged``.
464 Migrating from 1.1.0 to 1.1.1
465 =============================
467 1.1.1 "Clear this message"
468 --------------------------
470 In 1.1.1, the standard ``page.html`` template includes a "clear this message"
471 link in the green "ok" message bar that appears after a successful edit
472 (or other) action.
474 To include this in your tracker, change the following in your ``page.html``
475 template::
477  <p tal:condition="options/ok_message | nothing" class="ok-message"
478     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
480 to be::
482  <p tal:condition="options/ok_message | nothing" class="ok-message">
483    <span tal:repeat="m options/ok_message"
484       tal:content="structure string:$m <br/ > " />
485     <a class="form-small" tal:attributes="href request/current_url"
486        i18n:translate="">clear this message</a>
487  </p>
490 If you implemented the "clear this message" in your 1.1.0 tracker, then you
491 should change it to the above and it will work much better!
494 Migrating from 1.0.x to 1.1.0
495 =============================
497 1.1 Login "For Session Only"
498 ----------------------------
500 In 1.1, web logins are alive for the length of a session only, *unless* you
501 add the following to the login form in your tracker's ``page.html``::
503     <input type="checkbox" name="remember" id="remember">
504     <label for="remember" i18n:translate="">Remember me?</label><br>
506 See the classic tracker ``page.html`` if you're unsure where this should
507 go.
510 1.1 Query Display Name
511 ----------------------
513 The ``dispname`` web variable has been renamed ``@dispname`` to avoid
514 clashing with other variables of the same name. If you are using the
515 display name feature, you will need to edit your tracker's ``page.html``
516 and ``issue.index.html`` pages to change ``dispname`` to ``@dispname``.
518 A side-effect of this change is that the renderWith method used in the
519 ``home.html`` page may now take a dispname argument.
522 1.1 "Clear this message"
523 ------------------------
525 In 1.1, the standard ``page.html`` template includes a "clear this message"
526 link in the green "ok" message bar that appears after a successful edit
527 (or other) action.
529 To include this in your tracker, change the following in your ``page.html``
530 template::
532  <p tal:condition="options/ok_message | nothing" class="ok-message"
533     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
535 to be::
537  <p tal:condition="options/ok_message | nothing" class="ok-message">
538    <span tal:repeat="m options/ok_message"
539       tal:content="structure string:$m <br/ > " />
540     <a class="form-small" tal:attributes="href string:issue${context/id}"
541        i18n:translate="">clear this message</a>
542  </p>
545 Migrating from 0.8.x to 1.0
546 ===========================
548 1.0 New Query Permissions
549 -------------------------
551 New permissions are defined for query editing and viewing. To include these
552 in your tracker, you need to add these lines to your tracker's
553 ``schema.py``::
555  # Users should be able to edit and view their own queries. They should also
556  # be able to view any marked as not private. They should not be able to
557  # edit others' queries, even if they're not private
558  def view_query(db, userid, itemid):
559      private_for = db.query.get(itemid, 'private_for')
560      if not private_for: return True
561      return userid == private_for
562  def edit_query(db, userid, itemid):
563      return userid == db.query.get(itemid, 'creator')
564  p = db.security.addPermission(name='View', klass='query', check=view_query,
565      description="User is allowed to view their own and public queries")
566  db.security.addPermissionToRole('User', p)
567  p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
568      description="User is allowed to edit their queries")
569  db.security.addPermissionToRole('User', p)
570  p = db.security.addPermission(name='Create', klass='query',
571      description="User is allowed to create queries")
572  db.security.addPermissionToRole('User', p)
574 and then remove 'query' from the line::
576  # Assign the access and edit Permissions for issue, file and message
577  # to regular users now
578  for cl in 'issue', 'file', 'msg', 'query', 'keyword':
580 so it looks like::
582  for cl in 'issue', 'file', 'msg', 'keyword':
585 Migrating from 0.8.0 to 0.8.3
586 =============================
588 0.8.3 Nosy Handling Changes
589 ---------------------------
591 A change was made to fix a bug in the ``nosyreaction.py`` standard
592 detector. To incorporate this fix in your trackers, you will need to copy
593 the ``nosyreaction.py`` file from the ``templates/classic/detectors``
594 directory of the source to your tracker's ``templates`` directory.
596 If you have modified the ``nosyreaction.py`` file from the standard
597 version, you will need to roll your changes into the new file.
600 Migrating from 0.7.1 to 0.8.0
601 =============================
603 You *must* fully uninstall previous Roundup version before installing
604 Roundup 0.8.0.  If you don't do that, ``roundup-admin install``
605 command may fail to function properly.
607 0.8.0 Backend changes
608 ---------------------
610 Backends 'bsddb' and 'bsddb3' are removed.  If you are using one of these,
611 you *must* migrate to another backend before upgrading.
614 0.8.0 API changes
615 -----------------
617 Class.safeget() was removed from the API. Test your item ids before calling
618 Class.get() instead.
621 0.8.0 New tracker layout
622 ------------------------
624 The ``config.py`` file has been replaced by ``config.ini``. You may use the
625 roundup-admin command "genconfig" to generate a new config file::
627   roundup-admin genconfig <tracker home>/config.ini
629 and modify the values therein based on the contents of your old config.py.
630 In most cases, the names of the config variables are the same.
632 The ``select_db.py`` file has been replaced by a file in the ``db``
633 directory called ``backend_name``. As you might guess, this file contains
634 just the name of the backend. To figure what the contents of yours should
635 be, use the following table:
637   ================================ =========================
638   ``select_db.py`` contents        ``backend_name`` contents
639   ================================ =========================
640   from back_anydbm import ...      anydbm
641   from back_metakit import ...     metakit
642   from back_sqlite import ...      sqlite
643   from back_mysql import ...       mysql
644   from back_postgresql import ...  postgresql
645   ================================ =========================
647 The ``dbinit.py`` file has been split into two new files,
648 ``initial_data.py`` and ``schema.py``. The contents of this file are:
650 ``initial_data.py``
651   You don't need one of these as your tracker is already initialised.
653 ``schema.py``
654   Copy the body of the ``def open(name=None)`` function from your old
655   tracker's ``dbinit.py`` file to this file. As the lines you're copying
656   aren't part of a function definition anymore, one level of indentation
657   needs to be removed (remove only the leading four spaces on each
658   line). 
660   The first few lines -- those starting with ``from roundup.hyperdb
661   import ...`` and the ``db = Database(config, name)`` line -- don't
662   need to be copied. Neither do the last few lines -- those starting
663   with ``import detectors``, down to ``return db`` inclusive.
665 You may remove the ``__init__.py`` module from the "detectors" directory as
666 it is no longer used.
668 There's a new way to write extension code for Roundup. If you have code in
669 an ``interfaces.py`` file you should move it. See the `customisation
670 documentation`_ for information about how extensions are now written.
671 Note that some older trackers may use ``interfaces.py`` to customise the
672 mail gateway behaviour. You will need to keep your ``interfaces.py`` file
673 if this is the case.
676 0.8.0 Permissions Changes
677 -------------------------
679 The creation of a new item in the user interfaces is now controlled by the
680 "Create" Permission. You will need to add an assignment of this Permission
681 to your users who are allowed to create items. The most common form of this
682 is the following in your ``schema.py`` added just under the current
683 assignation of the Edit Permission::
685     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
686         p = db.security.getPermission('Create', cl)
687         db.security.addPermissionToRole('User', p)
689 You will need to explicitly let anonymous users access the web interface so
690 that regular users are able to see the login form. Note that almost all
691 trackers will need this Permission. The only situation where it's not
692 required is in a tracker that uses an HTTP Basic Authenticated front-end.
693 It's enabled by adding to your ``schema.py``::
695     p = db.security.getPermission('Web Access')
696     db.security.addPermissionToRole('Anonymous', p)
698 Finally, you will need to enable permission for your users to edit their
699 own details by adding the following to ``schema.py``::
701     # Users should be able to edit their own details. Note that this
702     # permission is limited to only the situation where the Viewed or
703     # Edited item is their own.
704     def own_record(db, userid, itemid):
705         '''Determine whether the userid matches the item being accessed.'''
706         return userid == itemid
707     p = db.security.addPermission(name='View', klass='user', check=own_record,
708         description="User is allowed to view their own user details")
709     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
710         description="User is allowed to edit their own user details")
711     db.security.addPermissionToRole('User', p)
714 0.8.0 Use of TemplatingUtils
715 ----------------------------
717 If you used custom python functions in TemplatingUtils, they must
718 be moved from interfaces.py to a new file in the ``extensions`` directory. 
720 Each Function that should be available through TAL needs to be defined
721 as a toplevel function in the newly created file. Furthermore you
722 add an inititialization function, that registers the functions with the 
723 tracker.
725 If you find this too tedious, donfu wrote an automatic init function that
726 takes an existing TemplatingUtils class, and registers all class methods
727 that do not start with an underscore. The following hack should be placed
728 in the ``extensions`` directory alongside other extensions::
730     class TemplatingUtils:
731          # copy from interfaces.py
733     def init(tracker):
734          util = TemplatingUtils()
736          def setClient(tu):
737              util.client = tu.client
738              return util
740          def execUtil(name):
741              return lambda tu, *args, **kwargs: \
742                      getattr(setClient(tu), name)(*args, **kwargs)
744          for name in dir(util):
745              if callable(getattr(util, name)) and not name.startswith('_'):
746                   tracker.registerUtil(name, execUtil(name))
749 0.8.0 Logging Configuration
750 ---------------------------
752 See the `administration guide`_ for information about configuring the new
753 logging implemented in 0.8.0.
756 Migrating from 0.7.2 to 0.7.3
757 =============================
759 0.7.3 Configuration
760 -------------------
762 If you choose, you may specify the directory from which static files are
763 served (those which use the URL component ``@@file``). Currently the
764 directory defaults to the ``TEMPLATES`` configuration variable. You may
765 define a new variable, ``STATIC_FILES`` which overrides this value for
766 static files.
769 Migrating from 0.7.0 to 0.7.2
770 =============================
772 0.7.2 DEFAULT_TIMEZONE is now required
773 --------------------------------------
775 The DEFAULT_TIMEZONE configuration variable is now required. Add the
776 following to your tracker's ``config.py`` file::
778     # You may specify a different default timezone, for use when users do not
779     # choose their own in their settings.
780     DEFAULT_TIMEZONE = 0            # specify as numeric hour offest
783 Migrating from 0.7.0 to 0.7.1
784 =============================
786 0.7.1 Permission assignments
787 ----------------------------
789 If you allow anonymous access to your tracker, you might need to assign
790 some additional View (or Edit if your tracker is that open) permissions
791 to the "anonymous" user. To do so, find the code in your ``dbinit.py`` that
792 says::
794     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
795         p = db.security.getPermission('View', cl)
796         db.security.addPermissionToRole('User', p)
797         p = db.security.getPermission('Edit', cl)
798         db.security.addPermissionToRole('User', p)
799     for cl in 'priority', 'status':
800         p = db.security.getPermission('View', cl)
801         db.security.addPermissionToRole('User', p)
803 Add add a line::
805         db.security.addPermissionToRole('Anonymous', p)
807 next to the existing ``'User'`` lines for the Permissions you wish to
808 assign to the anonymous user.
811 Migrating from 0.6 to 0.7
812 =========================
814 0.7.0 Permission assignments
815 ----------------------------
817 Due to a change in the rendering of web widgets, permissions are now
818 checked on Classes where they previously weren't (this is a good thing).
820 You will need to add some additional Permission assignments for your
821 regular users, or some displays will break. After the following in your 
822 tracker's ``dbinit.py``::
824     # Assign the access and edit Permissions for issue, file and message
825     # to regular users now
826     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
827         p = db.security.getPermission('View', cl)
828         db.security.addPermissionToRole('User', p)
829         p = db.security.getPermission('Edit', cl)
830         db.security.addPermissionToRole('User', p)
832 add::
834     for cl in 'priority', 'status':
835         p = db.security.getPermission('View', cl)
836         db.security.addPermissionToRole('User', p)
839 0.7.0 Getting the current user id
840 ---------------------------------
842 The Database.curuserid attribute has been removed.
844 Any code referencing this attribute should be replaced with a
845 call to Database.getuid().
848 0.7.0 ZRoundup changes
849 ----------------------
851 The templates in your tracker's html directory will need updating if you
852 wish to use ZRoundup. If you've not modified those files (or some of them),
853 you may just copy the new versions from the Roundup source in the
854 templates/classic/html directory.
856 If you have modified the html files, then you'll need to manually edit them
857 to change all occurances of special form variables from using the colon ":"
858 special character to the at "@" special character. That is, variables such
859 as::
861   :action :required :template :remove:messages ...
863 should become::
865   @action @required @template @remove@messages ...
867 Note that ``tal:`` statements are unaffected. So are TAL expression type
868 prefixes such as ``python:`` and ``string:``. Please ask on the
869 roundup-users mailing list for help if you're unsure.
872 0.7.0 Edit collision detection
873 ------------------------------
875 Roundup now detects collisions with editing in the web interface (that is,
876 two people editing the same item at the same time).
878 You must copy the ``_generic.collision.html`` file from Roundup source in
879 the ``templates/classic/html`` directory. to your tracker's ``html``
880 directory.
883 Migrating from 0.6.x to 0.6.3
884 =============================
886 0.6.3 Configuration
887 -------------------
889 You will need to copy the file::
891   templates/classic/detectors/__init__.py
893 to your tracker's ``detectors`` directory, replacing the one already there.
894 This fixes a couple of bugs in that file.
898 Migrating from 0.5 to 0.6
899 =========================
902 0.6.0 Configuration
903 -------------------
905 Introduced EMAIL_FROM_TAG config variable. This value is inserted into
906 the From: line of nosy email. If the sending user is "Foo Bar", the
907 From: line is usually::
909      "Foo Bar" <issue_tracker@tracker.example>
911 the EMAIL_FROM_TAG goes inside the "Foo Bar" quotes like so::
913      "Foo Bar EMAIL_FROM_TAG" <issue_tracker@tracker.example>
915 I've altered the mechanism in the detectors __init__.py module so that it
916 doesn't cross-import detectors from other trackers (if you run more than one
917 in a single roundup-server). This change means that you'll need to copy the
918 __init__.py from roundup/templates/classic/detectors/__init__.py to your
919 <tracker home>/detectors/__init__.py. Don't worry, the "classic" __init__ is a
920 one-size-fits-all, so it'll work even if you've added/removed detectors.
922 0.6.0 Templating changes
923 ------------------------
925 The ``user.item`` template (in the tracker home "templates" directory)
926 needs to have the following hidden variable added to its form (between the
927 ``<form...>`` and ``</form>`` tags::
929   <input type="hidden" name=":template" value="item">
932 0.6.0 Form handling changes
933 ---------------------------
935 Roundup's form handling capabilities have been significantly expanded. This
936 should not affect users of 0.5 installations - but if you find you're
937 getting errors from form submissions, please ask for help on the Roundup
938 users mailing list:
940   http://lists.sourceforge.net/lists/listinfo/roundup-users
942 See the customisation doc section on `Form Values`__ for documentation of the
943 new form variables possible.
945 __ customizing.html#form-values
948 0.6.0 Multilingual character set support
949 ----------------------------------------
951 Added internationalization support. This is done via encoding all data
952 stored in roundup database to utf-8 (unicode encoding). To support utf-8 in
953 web interface you should add the folowing line to your tracker's html/page
954 and html/_generic.help files inside <head> tag::
955   
956     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
958 Since latin characters in utf-8 have the same codes as in ASCII table, this
959 modification is optional for users who use only plain latin characters. 
961 After this modification, you will be able to see and enter any world
962 character via web interface. Data received via mail interface also converted
963 to utf-8, however only new messages will be converted. If your roundup
964 database contains some of non-ASCII characters in one of 8-bit encoding,
965 they will not be visible in new unicode environment. Some of such data (e.g.
966 user names, keywords, etc)  can be edited by administrator, the others
967 (e.g. messages' contents) is not editable via web interface. Currently there
968 is no tool for converting such data, the only solution is to close
969 appropriate old issues and create new ones with the same content.
972 0.6.0 User timezone support
973 ---------------------------
975 From version 0.6.0 roundup supports displaying of Date data in user' local
976 timezone if he/she has provided timezone information. To make it possible
977 some modification to tracker's schema and HTML templates are required.
978 First you must add string property 'timezone' to user class in dbinit.py
979 like this::
980   
981     user = Class(db, "user", 
982                     username=String(),   password=Password(),
983                     address=String(),    realname=String(), 
984                     phone=String(),      organisation=String(),
985                     alternate_addresses=String(),
986                     queries=Multilink('query'), roles=String(),
987                     timezone=String())
988   
989 And second - html interface. Add following lines to
990 $TRACKER_HOME/html/user.item template::
991   
992      <tr>
993       <th>Timezone</th>
994       <td tal:content="structure context/timezone/field">timezone</td>
995      </tr>
997 After that all users should be able to provide their timezone information.
998 Timezone should be a positive or negative integer - offset from GMT.
1000 After providing timezone, roundup will show all dates values, found in web
1001 and mail interfaces in local time. It will also accept any Date info in
1002 local time, convert and store it in GMT.
1005 0.6.0 Search page structure
1006 ---------------------------
1008 In order to accomodate query editing the search page has been restructured. If
1009 you want to provide your users with query editing, you should update your
1010 search page using the macros detailed in the customisation doc section
1011 `Searching on categories`__.
1013 __ customizing.html#searching-on-categories
1015 Also, the url field in the query class no longer starts with a '?'. You'll need
1016 to remove this question mark from the url field to support queries. There's
1017 a script in the "tools" directory called ``migrate-queries.py`` that should
1018 automatically change any existing queries for you. As always, make a backup
1019 of your database before running such a script.
1022 0.6.0 Notes for metakit backend users
1023 -------------------------------------
1025 Roundup 0.6.0 introduced searching on ranges of dates and intervals. To
1026 support it, some modifications to interval storing routine were made. So if
1027 your tracker uses metakit backend and your db schema contains intervals
1028 property, searches on that property will not be accurate for db items that
1029 was stored before roundup' upgrade. However all new records should be
1030 searchable on intervals.
1032 It is possible to convert your database to new format: you can export and
1033 import back all your data (consult "Migrating backends" in "Maintenance"
1034 documentation). After this operation all your interval properties should
1035 become searchable.
1037 Users of backends others than metakit should not worry about this issue.
1040 Migrating from 0.4.x to 0.5.0
1041 =============================
1043 This has been a fairly major revision of Roundup:
1045 1. Brand new, much more powerful, flexible, tasty and nutritious templating.
1046    Unfortunately, this means all your current templates are useless. Hopefully
1047    the new documentation and examples will be enough to help you make the
1048    transition. Please don't hesitate to ask on roundup-users for help (or
1049    complete conversions if you're completely stuck)!
1050 2. The database backed got a lot more flexible, allowing Metakit and SQL
1051    databases! The only decent SQL database implemented at present is sqlite,
1052    but others shouldn't be a whole lot more work.
1053 3. A brand new, highly flexible and much more robust security system including
1054    a system of Permissions, Roles and Role assignments to users. You may now
1055    define your own Permissions that may be checked in CGI transactions.
1056 4. Journalling has been made less storage-hungry, so has been turned on
1057    by default *except* for author, recipient and nosy link/unlink events. You
1058    are advised to turn it off in your trackers too.
1059 5. We've changed the terminology from "instance" to "tracker", to ease the
1060    learning curve/impact for new users.
1061 6. Because of the above changes, the tracker configuration has seen some
1062    major changes. See below for the details.
1064 Please, **back up your database** before you start the migration process. This
1065 is as simple as copying the "db" directory and all its contents from your
1066 tracker to somewhere safe.
1069 0.5.0 Configuration
1070 -------------------
1072 First up, rename your ``instance_config.py`` file to just ``config.py``.
1074 Then edit your tracker's ``__init__.py`` module. It'll currently look
1075 like this::
1077  from instance_config import *
1078  try:
1079      from dbinit import *
1080  except ImportError:
1081      pass # in installdir (probably :)
1082  from interfaces import *
1084 and it needs to be::
1086  import config
1087  from dbinit import open, init
1088  from interfaces import Client, MailGW
1090 Due to the new templating having a top-level ``page`` that defines links for
1091 searching, indexes, adding items etc, the following variables are no longer
1092 used:
1094 - HEADER_INDEX_LINKS
1095 - HEADER_ADD_LINKS
1096 - HEADER_SEARCH_LINKS
1097 - SEARCH_FILTERS
1098 - DEFAULT_INDEX
1099 - UNASSIGNED_INDEX
1100 - USER_INDEX
1101 - ISSUE_FILTER
1103 The new security implementation will require additions to the dbinit module,
1104 but also removes the need for the following tracker config variables:
1106 - ANONYMOUS_ACCESS
1107 - ANONYMOUS_REGISTER
1109 but requires two new variables which define the Roles assigned to users who
1110 register through the web and e-mail interfaces:
1112 - NEW_WEB_USER_ROLES
1113 - NEW_EMAIL_USER_ROLES
1115 in both cases, 'User' is a good initial setting. To emulate
1116 ``ANONYMOUS_ACCESS='deny'``, remove all "View" Permissions from the
1117 "Anonymous" Role. To emulate ``ANONYMOUS_REGISTER='deny'``, remove the "Web
1118 Registration" and/or the "Email Registration" Permission from the "Anonymous"
1119 Role. See the section on customising security in the `customisation
1120 documentation`_ for more information.
1122 Finally, the following config variables have been renamed to make more sense:
1124 - INSTANCE_HOME -> TRACKER_HOME
1125 - INSTANCE_NAME -> TRACKER_NAME
1126 - ISSUE_TRACKER_WEB -> TRACKER_WEB
1127 - ISSUE_TRACKER_EMAIL -> TRACKER_EMAIL
1130 0.5.0 Schema Specification
1131 --------------------------
1133 0.5.0 Database backend changes
1134 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1136 Your select_db module in your tracker has changed a fair bit. Where it used
1137 to contain::
1139  # WARNING: DO NOT EDIT THIS FILE!!!
1140  from roundup.backends.back_anydbm import Database
1142 it must now contain::
1144  # WARNING: DO NOT EDIT THIS FILE!!!
1145  from roundup.backends.back_anydbm import Database, Class, FileClass, IssueClass
1147 Yes, I realise the irony of the "DO NOT EDIT THIS FILE" statement :)
1148 Note the addition of the Class, FileClass, IssueClass imports. These are very
1149 important, as they're going to make the next change work too. You now need to
1150 modify the top of the dbinit module in your tracker from::
1152  import instance_config
1153  from roundup import roundupdb
1154  from select_db import Database
1156  from roundup.roundupdb import Class, FileClass
1158  class Database(roundupdb.Database, select_db.Database):
1159      ''' Creates a hybrid database from:
1160           . the selected database back-end from select_db
1161           . the roundup extensions from roundupdb
1162      '''
1163      pass
1165  class IssueClass(roundupdb.IssueClass):
1166      ''' issues need the email information
1167      '''
1168      pass
1170 to::
1172  import config
1173  from select_db import Database, Class, FileClass, IssueClass
1175 Yes, remove the Database and IssueClass definitions and those other imports.
1176 They're not needed any more!
1178 Look for places in dbinit.py where ``instance_config`` is used too, and
1179 rename them ``config``.
1182 0.5.0 Journalling changes
1183 ~~~~~~~~~~~~~~~~~~~~~~~~~
1185 Journalling has been optimised for storage. Journalling of links has been
1186 turned back on by default. If your tracker has a large user base, you may wish
1187 to turn off journalling of nosy list, message author and message recipient
1188 link and unlink events. You do this by adding ``do_journal='no'`` to the Class
1189 initialisation in your dbinit. For example, your *msg* class initialisation
1190 probably looks like this::
1192     msg = FileClass(db, "msg",
1193                     author=Link("user"), recipients=Multilink("user"),
1194                     date=Date(),         summary=String(),
1195                     files=Multilink("file"),
1196                     messageid=String(),  inreplyto=String())
1198 to turn off journalling of author and recipient link events, add
1199 ``do_journal='no'`` to the ``author=Link("user")`` part of the statement,
1200 like so::
1202     msg = FileClass(db, "msg",
1203                     author=Link("user", do_journal='no'),
1204                     recipients=Multilink("user", do_journal='no'),
1205                     date=Date(),         summary=String(),
1206                     files=Multilink("file"),
1207                     messageid=String(),  inreplyto=String())
1209 Nosy list link event journalling is actually turned off by default now. If you
1210 want to turn it on, change to your issue class' nosy list, change its
1211 definition from::
1213     issue = IssueClass(db, "issue",
1214                     assignedto=Link("user"), topic=Multilink("keyword"),
1215                     priority=Link("priority"), status=Link("status"))
1217 to::
1219     issue = IssueClass(db, "issue", nosy=Multilink("user", do_journal='yes'),
1220                     assignedto=Link("user"), topic=Multilink("keyword"),
1221                     priority=Link("priority"), status=Link("status"))
1223 noting that your definition of the nosy Multilink will override the normal one.
1226 0.5.0 User schema changes
1227 ~~~~~~~~~~~~~~~~~~~~~~~~~
1229 Users have two more properties, "queries" and "roles". You'll have something
1230 like this in your dbinit module now::
1232     user = Class(db, "user",
1233                     username=String(),   password=Password(),
1234                     address=String(),    realname=String(),
1235                     phone=String(),      organisation=String(),
1236                     alternate_addresses=String())
1237     user.setkey("username")
1239 and you'll need to add the new properties and the new "query" class to it
1240 like so::
1242     query = Class(db, "query",
1243                     klass=String(),     name=String(),
1244                     url=String())
1245     query.setkey("name")
1247     # Note: roles is a comma-separated string of Role names
1248     user = Class(db, "user",
1249                     username=String(),   password=Password(),
1250                     address=String(),    realname=String(),
1251                     phone=String(),      organisation=String(),
1252                     alternate_addresses=String(),
1253                     queries=Multilink('query'), roles=String())
1254     user.setkey("username")
1256 The "queries" property is used to store off the user's favourite database
1257 queries. The "roles" property is explained below in `0.5.0 Security
1258 Settings`_.
1261 0.5.0 Security Settings
1262 ~~~~~~~~~~~~~~~~~~~~~~~
1264 See the `security documentation`_ for an explanation of how the new security
1265 system works. In a nutshell though, the security is handled as a four step
1266 process:
1268 1. Permissions are defined as having a name and optionally a hyperdb class
1269    they're specific to,
1270 2. Roles are defined that have one or more Permissions,
1271 3. Users are assigned Roles in their "roles" property, and finally
1272 4. Roundup checks that users have appropriate Permissions at appropriate times
1273    (like editing issues).
1275 Your tracker dbinit module's *open* function now has to define any
1276 Permissions that are specific to your tracker, and also the assignment
1277 of Permissions to Roles. At the moment, your open function
1278 ends with::
1280     import detectors
1281     detectors.init(db)
1283     return db
1285 and what we need to do is insert some commands that will set up the security
1286 parameters. Right above the ``import detectors`` line, you'll want to insert
1287 these lines::
1289     #
1290     # SECURITY SETTINGS
1291     #
1292     # new permissions for this schema
1293     for cl in 'issue', 'file', 'msg', 'user':
1294         db.security.addPermission(name="Edit", klass=cl,
1295             description="User is allowed to edit "+cl)
1296         db.security.addPermission(name="View", klass=cl,
1297             description="User is allowed to access "+cl)
1299     # Assign the access and edit permissions for issue, file and message
1300     # to regular users now
1301     for cl in 'issue', 'file', 'msg':
1302         p = db.security.getPermission('View', cl)
1303         db.security.addPermissionToRole('User', p)
1304         p = db.security.getPermission('Edit', cl)
1305         db.security.addPermissionToRole('User', p)
1306     # and give the regular users access to the web and email interface
1307     p = db.security.getPermission('Web Access')
1308     db.security.addPermissionToRole('User', p)
1309     p = db.security.getPermission('Email Access')
1310     db.security.addPermissionToRole('User', p)
1312     # May users view other user information? Comment these lines out
1313     # if you don't want them to
1314     p = db.security.getPermission('View', 'user')
1315     db.security.addPermissionToRole('User', p)
1317     # Assign the appropriate permissions to the anonymous user's Anonymous
1318     # Role. Choices here are:
1319     # - Allow anonymous users to register through the web
1320     p = db.security.getPermission('Web Registration')
1321     db.security.addPermissionToRole('Anonymous', p)
1322     # - Allow anonymous (new) users to register through the email gateway
1323     p = db.security.getPermission('Email Registration')
1324     db.security.addPermissionToRole('Anonymous', p)
1325     # - Allow anonymous users access to the "issue" class of data
1326     #   Note: this also grants access to related information like files,
1327     #         messages, statuses etc that are linked to issues
1328     #p = db.security.getPermission('View', 'issue')
1329     #db.security.addPermissionToRole('Anonymous', p)
1330     # - Allow anonymous users access to edit the "issue" class of data
1331     #   Note: this also grants access to create related information like
1332     #         files and messages etc that are linked to issues
1333     #p = db.security.getPermission('Edit', 'issue')
1334     #db.security.addPermissionToRole('Anonymous', p)
1336     # oh, g'wan, let anonymous access the web interface too
1337     p = db.security.getPermission('Web Access')
1338     db.security.addPermissionToRole('Anonymous', p)
1340 Note in the comments there the places where you might change the permissions
1341 to restrict users or grant users more access. If you've created additional
1342 classes that users should be able to edit and view, then you should add them
1343 to the "new permissions for this schema" section at the start of the security
1344 block. Then add them to the "Assign the access and edit permissions" section
1345 too, so people actually have the new Permission you've created.
1347 One final change is needed that finishes off the security system's
1348 initialisation. We need to add a call to ``db.post_init()`` at the end of the
1349 dbinit open() function. Add it like this::
1351     import detectors
1352     detectors.init(db)
1354     # schema is set up - run any post-initialisation
1355     db.post_init()
1356     return db
1358 You may verify the setup of Permissions and Roles using the new
1359 "``roundup-admin security``" command.
1362 0.5.0 User changes
1363 ~~~~~~~~~~~~~~~~~~
1365 To support all those schema changes, you'll need to massage your user database
1366 a little too, to:
1368 1. make sure there's an "anonymous" user - this user is mandatory now and is
1369    the one that unknown users are logged in as.
1370 2. make sure all users have at least one Role.
1372 If you don't have the "anonymous" user, create it now with the command::
1374   roundup-admin create user username=anonymous roles=Anonymous
1376 making sure the capitalisation is the same as above. Once you've done that,
1377 you'll need to set the roles property on all users to a reasonable default.
1378 The admin user should get "Admin", the anonymous user "Anonymous"
1379 and all other users "User". The ``fixroles.py`` script in the tools directory
1380 will do this. Run it like so (where python is your python 2+ binary)::
1382   python tools/fixroles.py -i <tracker home> fixroles
1386 0.5.0 CGI interface changes
1387 ---------------------------
1389 The CGI interface code was completely reorganised and largely rewritten. The
1390 end result is that this section of your tracker interfaces module will need
1391 changing from::
1393  from roundup import cgi_client, mailgw
1394  from roundup.i18n import _
1395  
1396  class Client(cgi_client.Client):
1397      ''' derives basic CGI implementation from the standard module,
1398          with any specific extensions
1399      '''
1400      pass
1402 to::
1404  from roundup import mailgw
1405  from roundup.cgi import client
1406  
1407  class Client(client.Client): 
1408      ''' derives basic CGI implementation from the standard module,
1409          with any specific extensions
1410      '''
1411      pass
1413 You will also need to install the new version of roundup.cgi from the source
1414 cgi-bin directory if you're using it.
1417 0.5.0 HTML templating
1418 ---------------------
1420 You'll want to make a backup of your current tracker html directory. You
1421 should then copy the html directory from the Roundup source "classic" template
1422 and modify it according to your local schema changes.
1424 If you need help with the new templating system, please ask questions on the
1425 roundup-users mailing list (available through the roundup project page on
1426 sourceforge, http://roundup.sf.net/)
1429 0.5.0 Detectors
1430 ---------------
1432 The nosy reactor has been updated to handle the tracker not having an
1433 "assignedto" property on issues. You may want to copy it into your tracker's
1434 detectors directory. Chances are you've already fixed it though :)
1437 Migrating from 0.4.1 to 0.4.2
1438 =============================
1440 0.4.2 Configuration
1441 -------------------
1442 The USER_INDEX definition introduced in 0.4.1 was too restrictive in its
1443 allowing replacement of 'assignedto' with the user's userid. Users must change
1444 the None value of 'assignedto' to 'CURRENT USER' (the string, in quotes) for
1445 the replacement behaviour to occur now.
1447 The new configuration variables are:
1449 - EMAIL_KEEP_QUOTED_TEXT 
1450 - EMAIL_LEAVE_BODY_UNCHANGED
1451 - ADD_RECIPIENTS_TO_NOSY
1453 See the sample configuration files in::
1455  <roundup source>/roundup/templates/classic/instance_config.py
1457 and::
1459  <roundup source>/roundup/templates/extended/instance_config.py
1461 and the `customisation documentation`_ for information on how they're used.
1464 0.4.2 Changes to detectors
1465 --------------------------
1466 You will need to copy the detectors from the distribution into your instance
1467 home "detectors" directory. If you used the classic schema, the detectors
1468 are in::
1470  <roundup source>/roundup/templates/classic/detectors/
1472 If you used the extended schema, the detectors are in::
1474  <roundup source>/roundup/templates/extended/detectors/
1476 The change means that schema-specific code has been removed from the
1477 mail gateway and cgi interface and made into auditors:
1479 - nosyreactor.py has now got an updatenosy auditor which updates the nosy
1480   list with author, recipient and assignedto information.
1481 - statusauditor.py makes the unread or resolved -> chatting changes and
1482   presets the status of an issue to unread.
1484 There's also a bug or two fixed in the nosyreactor code.
1486 0.4.2 HTML templating changes
1487 -----------------------------
1488 The link() htmltemplate function now has a "showid" option for links and
1489 multilinks. When true, it only displays the linked item id as the anchor
1490 text. The link value is displayed as a tooltip using the title anchor
1491 attribute. To use in eg. the superseder field, have something like this::
1493    <td>
1494     <display call="field('superseder', showid=1)">
1495     <display call="classhelp('issue', 'id,title', label='list', width=500)">
1496     <property name="superseder">
1497      <br>View: <display call="link('superseder', showid=1)">
1498     </property>
1499    </td>
1501 The stylesheets have been cleaned up too. You may want to use the newer
1502 versions in::
1504  <roundup source>/roundup/templates/<template>/html/default.css
1508 Migrating from 0.4.0 to 0.4.1
1509 =============================
1511 0.4.1 Files storage
1512 -------------------
1514 Messages and files from newly created issues will be put into subdierectories
1515 in thousands e.g. msg123 will be put into files/msg/0/msg123, file2003
1516 will go into files/file/2/file2003. Previous messages are still found, but
1517 could be put into this structure.
1519 0.4.1 Configuration
1520 -------------------
1522 To allow more fine-grained access control, the variable used to check
1523 permission to auto-register users in the mail gateway is now called
1524 ANONYMOUS_REGISTER_MAIL rather than overloading ANONYMOUS_REGISTER. If the
1525 variable doesn't exist, then ANONYMOUS_REGISTER is tested as before.
1527 Configuring the links in the web header is now easier too. The following
1528 variables have been added to the classic instance_config.py::
1530   HEADER_INDEX_LINKS   - defines the "index" links to be made available
1531   HEADER_ADD_LINKS     - defines the "add" links
1532   DEFAULT_INDEX        - specifies the index view for DEFAULT
1533   UNASSIGNED_INDEX     - specifies the index view for UNASSIGNED
1534   USER_INDEX           - specifies the index view for USER
1536 See the <roundup source>/roundup/templates/classic/instance_config.py for more
1537 information - including how the variables are to be set up. Most users will
1538 just be able to copy the variables from the source to their instance home. If
1539 you've modified the header by changing the source of the interfaces.py file in
1540 the instance home, you'll need to remove that customisation and move it into
1541 the appropriate variables in instance_config.py.
1543 The extended schema has similar variables added too - see the source for more
1544 info.
1546 0.4.1 Alternate E-Mail Addresses
1547 --------------------------------
1549 If you add the property "alternate_addresses" to your user class, your users
1550 will be able to register alternate email addresses that they may use to
1551 communicate with roundup as. All email from roundup will continue to be sent
1552 to their primary address.
1554 If you have not edited the dbinit.py file in your instance home directory,
1555 you may simply copy the new dbinit.py file from the core code. If you used
1556 the classic schema, the interfaces file is in::
1558  <roundup source>/roundup/templates/classic/dbinit.py
1560 If you used the extended schema, the file is in::
1562  <roundup source>/roundup/templates/extended/dbinit.py 
1564 If you have modified your dbinit.py file, you need to edit the dbinit.py
1565 file in your instance home directory. Find the lines which define the user
1566 class::
1568     user = Class(db, "msg",
1569                     username=String(),   password=Password(),
1570                     address=String(),    realname=String(), 
1571                     phone=String(),      organisation=String(),
1572                     alternate_addresses=String())
1574 You will also want to add the property to the user's details page. The
1575 template for this is the "user.item" file in your instance home "html"
1576 directory. Similar to above, you may copy the file from the roundup source if
1577 you haven't modified it. Otherwise, add the following to the template::
1579    <display call="multiline('alternate_addresses')">
1581 with appropriate labelling etc. See the standard template for an idea.
1585 Migrating from 0.3.x to 0.4.0
1586 =============================
1588 0.4.0 Message-ID and In-Reply-To addition
1589 -----------------------------------------
1590 0.4.0 adds the tracking of messages by message-id and allows threading
1591 using in-reply-to. Most e-mail clients support threading using this
1592 feature, and we hope to add support for it to the web gateway. If you
1593 have not edited the dbinit.py file in your instance home directory, you may
1594 simply copy the new dbinit.py file from the core code. If you used the
1595 classic schema, the interfaces file is in::
1597  <roundup source>/roundup/templates/classic/dbinit.py
1599 If you used the extended schema, the file is in::
1601  <roundup source>/roundup/templates/extended/dbinit.py 
1603 If you have modified your dbinit.py file, you need to edit the dbinit.py
1604 file in your instance home directory. Find the lines which define the msg
1605 class::
1607     msg = FileClass(db, "msg",
1608                     author=Link("user"), recipients=Multilink("user"),
1609                     date=Date(),         summary=String(),
1610                     files=Multilink("file"))
1612 and add the messageid and inreplyto properties like so::
1614     msg = FileClass(db, "msg",
1615                     author=Link("user"), recipients=Multilink("user"),
1616                     date=Date(),         summary=String(),
1617                     files=Multilink("file"),
1618                     messageid=String(),  inreplyto=String())
1620 Also, configuration is being cleaned up. This means that your dbinit.py will
1621 also need to be changed in the open function. If you haven't changed your
1622 dbinit.py, the above copy will be enough. If you have, you'll need to change
1623 the line (round line 50)::
1625     db = Database(instance_config.DATABASE, name)
1627 to::
1629     db = Database(instance_config, name)
1632 0.4.0 Configuration
1633 --------------------
1634 ``TRACKER_NAME`` and ``EMAIL_SIGNATURE_POSITION`` have been added to the
1635 instance_config.py. The simplest solution is to copy the default values
1636 from template in the core source.
1638 The mail gateway now checks ``ANONYMOUS_REGISTER`` to see if unknown users
1639 are to be automatically registered with the tracker. If it is set to "deny"
1640 then unknown users will not have access. If it is set to "allow" they will be
1641 automatically registered with the tracker.
1644 0.4.0 CGI script roundup.cgi
1645 ----------------------------
1646 The CGI script has been updated with some features and a bugfix, so you should
1647 copy it from the roundup cgi-bin source directory again. Make sure you update
1648 the ROUNDUP_INSTANCE_HOMES after the copy.
1651 0.4.0 Nosy reactor
1652 ------------------
1653 The nosy reactor has also changed - copy the nosyreactor.py file from the core
1654 source::
1656    <roundup source>/roundup/templates/<template>/detectors/nosyreactor.py
1658 to your instance home "detectors" directory.
1661 0.4.0 HTML templating
1662 ---------------------
1663 The field() function was incorrectly implemented - links and multilinks now
1664 display as text fields when rendered using field(). To display a menu (drop-
1665 down or select box) you need to use the menu() function.
1669 Migrating from 0.2.x to 0.3.x
1670 =============================
1672 0.3.x Cookie Authentication changes
1673 -----------------------------------
1674 0.3.0 introduces cookie authentication - you will need to copy the
1675 interfaces.py file from the roundup source to your instance home to enable
1676 authentication. If you used the classic schema, the interfaces file is in::
1678  <roundup source>/roundup/templates/classic/interfaces.py
1680 If you used the extended schema, the file is in::
1682  <roundup source>/roundup/templates/extended/interfaces.py
1684 If you have modified your interfaces.Client class, you will need to take
1685 note of the login/logout functionality provided in roundup.cgi_client.Client
1686 (classic schema) or roundup.cgi_client.ExtendedClient (extended schema) and
1687 modify your instance code apropriately.
1690 0.3.x Password encoding
1691 -----------------------
1692 This release also introduces encoding of passwords in the database. If you
1693 have not edited the dbinit.py file in your instance home directory, you may
1694 simply copy the new dbinit.py file from the core code. If you used the
1695 classic schema, the interfaces file is in::
1697  <roundup source>/roundup/templates/classic/dbinit.py
1699 If you used the extended schema, the file is in::
1701  <roundup source>/roundup/templates/extended/dbinit.py
1704 If you have modified your dbinit.py file, you may use encoded passwords:
1706 1. Edit the dbinit.py file in your instance home directory
1707    a. At the first code line of the open() function::
1709        from roundup.hyperdb import String, Date, Link, Multilink
1711       alter to include Password, as so::
1713        from roundup.hyperdb import String, Password, Date, Link, Multilink
1715    b. Where the password property is defined (around line 66)::
1717        user = Class(db, "user", 
1718                        username=String(),   password=String(),
1719                        address=String(),    realname=String(), 
1720                        phone=String(),      organisation=String())
1721        user.setkey("username")
1723       alter the "password=String()" to "password=Password()"::
1725        user = Class(db, "user", 
1726                        username=String(),   password=Password(),
1727                        address=String(),    realname=String(), 
1728                        phone=String(),      organisation=String())
1729        user.setkey("username")
1731 2. Any existing passwords in the database will remain cleartext until they
1732    are edited. It is recommended that at a minimum the admin password be
1733    changed immediately::
1735       roundup-admin -i <instance home> set user1 password=<new password>
1738 0.3.x Configuration
1739 -------------------
1740 FILTER_POSITION, ANONYMOUS_ACCESS, ANONYMOUS_REGISTER have been added to
1741 the instance_config.py. Simplest solution is to copy the default values from
1742 template in the core source.
1744 MESSAGES_TO_AUTHOR has been added to the IssueClass in dbinit.py. Set to 'yes'
1745 to send nosy messages to the author. Default behaviour is to not send nosy
1746 messages to the author. You will need to add MESSAGES_TO_AUTHOR to your
1747 dbinit.py in your instance home.
1750 0.3.x CGI script roundup.cgi
1751 ----------------------------
1752 There have been some structural changes to the roundup.cgi script - you will
1753 need to install it again from the cgi-bin directory of the source
1754 distribution. Make sure you update the ROUNDUP_INSTANCE_HOMES after the
1755 copy.
1758 .. _`customisation documentation`: customizing.html
1759 .. _`security documentation`: security.html
1760 .. _`administration guide`: admin_guide.html