Code

- Add explicit "Search" permissions, see Security Fix below.
[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.17
17 ==============================
19 Searching now requires either read-permission without a check method, or
20 you will have to add a "Search" permission for a class or a list of
21 properties for a class (if you want to allow searching). For the classic
22 template (or other templates derived from it) you want to add the
23 following lines to your `schema.py` file::
25   p = db.security.addPermission(name='Search', klass='query')
26   db.security.addPermissionToRole('User', p)
28 This is needed, because for the `query` class users may view only their
29 own queries (or public queries). This is implemented with a `check`
30 method, therefore the default search permissions will not allow
31 searching and you'll have to add an explicit search permission.
32 If you have modified your schema, you can check if you're missing any
33 search permissions with the following script, run it in your tracker
34 directory, it will list for each Class and Property the roles that may
35 search for this property::
37     #!/usr/bin/python
38     import os
39     from roundup import instance
40     
41     tracker = instance.open(os.getcwd ())
42     db = tracker.open('admin')
43     
44     for cl in sorted(db.getclasses()):
45         print "Class:", cl
46         for p in sorted(db.getclass(cl).properties.keys()):
47             print "    Property:", p
48             roles = []
49             for role in sorted(db.security.role.iterkeys()):
50                 if db.security.roleHasSearchPermission(role,cl,p):
51                     roles.append(role)
52             print "        roles may search:", ', '.join(roles)
55 Migrating from 1.4.x to 1.4.12
56 ==============================
58 Item creation now checks the "Create" permission instead of the "Edit"
59 permission for individual properties. If you have modified your tracker
60 permissions from the default distribution, you should check that
61 "Create" permissions exist for all properties you want users to be able
62 to create.
65 Fixing some potential security holes
66 ------------------------------------
68 Enhanced checking was added to the user registration auditor. If you
69 run a public tracker you should update your tracker's
70 ``detectors/userauditor.py`` using the new code from
71 ``share/roundup/templates/classic/detectors/userauditor.py``. In most
72 cases you may just copy the file over, but if you've made changes to
73 the auditor in your tracker then you'll need to manually integrate
74 the new code.
76 Some HTML templates were found to have formatting security problems:
78 ``html/page.html``::
80   -tal:replace="request/user/username">username</span></b><br>
81   +tal:replace="python:request.user.username.plain(escape=1)">username</span></b><br>
83 ``html/_generic.help-list.html``::
85   -tal:content="structure python:item[prop]"></label>
86   +tal:content="python:item[prop]"></label>
88 The lines marked "+" should be added and lines marked "-" should be
89 deleted (minus the "+"/"-" signs).
92 Some HTML interface tweaks
93 --------------------------
95 You may wish to copy the ``user_utils.js`` and ``style.css` files from the
96 source distribution ``share/roundup/templates/classic/html/`` directory to the
97 ``html`` directory of your trackers as it includes a small improvement.
99 If you have made local changes to those files you'll need to manually work
100 the differences in to your versions or ignore the changes.
103 Migrating from 1.4.x to 1.4.11
104 ==============================
106 Close potential security hole
107 -----------------------------
109 If your tracker has untrusted users you should examine its ``schema.py``
110 file and look for the section granting the "Edit" permission to your users.
111 This should look something like::
113     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
114         description="User is allowed to edit their own user details")
116 and should be modified to restrict the list of properties they are allowed
117 to edit by adding the ``properties=`` section like::
119     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
120         properties=('username', 'password', 'address', 'realname', 'phone',
121             'organisation', 'alternate_addresses', 'queries', 'timezone'),
122         description="User is allowed to edit their own user details")
124 Most importantly the "roles" property should not be editable - thus not
125 appear in that list of properties.
128 Grant the "Register" permission to the Anonymous role
129 -----------------------------------------------------
131 A separate "Register" permission has been introduced to allow
132 anonymous users to register. This means you will need to add the
133 following to your tracker's ``schema.py`` to add the permission and
134 assign it to the Anonymous role (replacing any previously assigned
135 "Create user" permission for the Anonymous role)::
137   +db.security.addPermission(name='Register', klass='user',
138   +     description='User is allowed to register new user')
139  
140    # Assign the appropriate permissions to the anonymous user's Anonymous
141    # Role. Choices here are:
142    # - Allow anonymous users to register
143   -db.security.addPermissionToRole('Anonymous', 'Create', 'user')
144   +db.security.addPermissionToRole('Anonymous', 'Register', 'user')
146 The lines marked "+" should be added and lines marked "-" should be
147 deleted (minus the "+"/"-" signs).
149 You should also modify the ``html/page.html`` template to change the
150 permission tested there::
152    -tal:condition="python:request.user.hasPermission('Create', 'user')"
153    +tal:condition="python:request.user.hasPermission('Register', 'user')"
156 Generic class editor may now restore retired items
157 --------------------------------------------------
159 The instructions for doing so won't be present in your tracker unless you copy
160 the ``_generic.index.html`` template from the roundup distribution in
161 ``share/roundup/templates/classic/html`` to your tracker's ``html`` directory.
164 Migrating from 1.4.x to 1.4.9
165 =============================
167 Customized MailGW Class
168 -----------------------
170 If you have customized the MailGW class in your tracker: The new MailGW
171 class opens the database for each message in the method handle_message
172 (instance.open) instead of passing the opened database as a parameter to
173 the MailGW constructor. The old handle_message has been renamed to
174 _handle_message. The new method opens the database and wraps the call to
175 the old method into a try/finally.
177 Your customized MailGW class needs to mirror this behavior.
179 Fix the "remove" button in issue files and messages lists
180 ---------------------------------------------------------
182 The "remove" button(s) in the issue messages list needs to be altered. Find
183 the following in your tracker's ``html/issue.item.html`` template::
185   <td>
186    <form style="padding:0" tal:condition="context/is_edit_ok"
187          tal:attributes="action string:issue${context/id}">
188     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
190 and add ``method="POST"`` as shown below::
192   <td>
193    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
194          tal:attributes="action string:issue${context/id}">
195     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
197 Then also find::
199   <td>
200    <form style="padding:0" tal:condition="context/is_edit_ok"
201          tal:attributes="action string:issue${context/id}">
202     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
204 and add ``method="POST"`` as shown below::
206   <td>
207    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
208          tal:attributes="action string:issue${context/id}">
209     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
212 Fixing the "retire" button in user management list
213 --------------------------------------------------
215 If you made the change to the "reture" link in the user management list as
216 listed below in `Migrating from 1.4.x to 1.4.7`_ then you'll need to fix that
217 change by adding ``method="POST"`` to the ``<form>`` tag::
219      <form style="padding:0" method="POST"
220            tal:attributes="action string:user${user/id}">
221       <input type="hidden" name="@template" value="index">
222       <input type="hidden" name="@action" value="retire">
223       <input type="submit" value="retire" i18n:attributes="value">
224      </form>
227 Migrating from 1.4.x to 1.4.7
228 =============================
230 Several security issues were addressed in this release. Some aspects of your
231 trackers may no longer function depending on your local customisations. Core
232 functionality that will need to be modified:
234 Grant the "retire" permission to users for their queries
235 --------------------------------------------------------
237 Users will no longer be able to retire their own queries. To remedy this you
238 will need to add the following to your tracker's ``schema.py`` just under the
239 line that grants them permission to edit their own queries::
241    p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
242       description="User is allowed to edit their queries")
243    db.security.addPermissionToRole('User', p)
244  + p = db.security.addPermission(name='Retire', klass='query', check=edit_query,
245  +    description="User is allowed to retire their queries")
246  + db.security.addPermissionToRole('User', p)
247    p = db.security.addPermission(name='Create', klass='query',
248       description="User is allowed to create queries")
249    db.security.addPermissionToRole('User', p)
251 The lines marked "+" should be added, minus the "+" sign.
254 Fix the "retire" link in the users list for admin users
255 -------------------------------------------------------
257 The "retire" link found in the file ``html/user.index.html``::
259   <td tal:condition="context/is_edit_ok">
260    <a tal:attributes="href string:user${user/id}?@action=retire&@template=index"
261     i18n:translate="">retire</a>
263 Should be replaced with::
265   <td tal:condition="context/is_retire_ok">
266      <form style="padding:0" method="POST"
267            tal:attributes="action string:user${user/id}">
268       <input type="hidden" name="@template" value="index">
269       <input type="hidden" name="@action" value="retire">
270       <input type="submit" value="retire" i18n:attributes="value">
271      </form>
274 Fix for Python 2.6+ users
275 -------------------------
277 If you use Python 2.6 you should edit your tracker's
278 ``detectors/nosyreaction.py`` file to change::
280    import sets
282 at the top to::
284    from roundup.anypy.sets_ import set
286 and then all instances of ``sets.Set()`` to ``set()`` in the later code.
290 Trackers currently allowing HTML file uploading
291 -----------------------------------------------
293 Trackers which wish to continue to allow uploading of HTML content against issues
294 will need to set a new configuration variable in the ``[web]`` section of the
295 tracker's ``config.ini`` file:
297    # Setting this option enables Roundup to serve uploaded HTML
298    # file content *as HTML*. This is a potential security risk
299    # and is therefore disabled by default. Set to 'yes' if you
300    # trust *all* users uploading content to your tracker.
301    # Allowed values: yes, no
302    # Default: no
303    allow_html_file = no
307 Migrating from 1.4.2 to 1.4.3
308 =============================
310 If you are using the MySQL backend you will need to replace some indexes
311 that may have been created by version 1.4.2.
313 You should to access your MySQL database directly and remove any indexes
314 with a name ending in "_key_retired_idx". You should then re-add them with
315 the same spec except the key column name needs a size. So an index on
316 "_user (__retired, _name)" should become "_user (__retired, _name(255))".
319 Migrating from 1.4.x to 1.4.2
320 =============================
322 You should run the "roundup-admin migrate" command for your tracker once
323 you've installed the latest codebase. 
325 Do this before you use the web, command-line or mail interface and before
326 any users access the tracker.
328 This command will respond with either "Tracker updated" (if you've not
329 previously run it on an RDBMS backend) or "No migration action required"
330 (if you have run it, or have used another interface to the tracker,
331 or are using anydbm).
333 It's safe to run this even if it's not required, so just get into the
334 habit.
337 Migrating from 1.3.3 to 1.4.0
338 =============================
340 Value of the "refwd_re" tracker configuration option (section "mailgw")
341 is treated as UTF-8 string.  In previous versions, it was ISO8859-1.
343 If you have running trackers based on the classic template, please
344 update the messagesummary detector as follows::
346     --- detectors/messagesummary.py 17 Apr 2003 03:26:38 -0000      1.1
347     +++ detectors/messagesummary.py 3 Apr 2007 06:47:21 -0000       1.2
348     @@ -8,7 +8,7 @@
349      if newvalues.has_key('summary') or not newvalues.has_key('content'):
350          return
352     -    summary, content = parseContent(newvalues['content'], 1, 1)
353     +    summary, content = parseContent(newvalues['content'], config=db.config)
354      newvalues['summary'] = summary
356 In the latest version we have added some database indexes to the
357 SQL-backends (mysql, postgresql, sqlite) for speeding up building the
358 roundup-index for full-text search. We recommend that you create the
359 following database indexes on the database by hand::
361  CREATE INDEX words_by_id ON __words (_textid);
362  CREATE UNIQUE INDEX __textids_by_props ON __textids (_class, _itemid, _prop);
364 Migrating from 1.2.x to 1.3.0
365 =============================
367 1.3.0 Web interface changes
368 ---------------------------
370 Some of the HTML files in the "classic" and "minimal" tracker templates
371 were changed to fix some bugs and clean them up. You may wish to compare
372 them to the HTML files in your tracker and apply any changes.
375 Migrating from 1.1.2 to 1.2.0
376 =============================
378 1.2.0 Sorting and grouping by multiple properties
379 -------------------------------------------------
381 Starting with this version, sorting and grouping by multiple properties
382 is possible. This means that request.sort and request.group are now
383 lists. This is reflected in several places:
385  * ``renderWith`` now has list attributes for ``sort`` and ``group``,
386    where you previously wrote::
387    
388     renderWith(... sort=('-', 'activity'), group=('+', 'priority')
390    you write now::
392     renderWith(... sort=[('-', 'activity')], group=[('+', 'priority')]
394  * In templates that permit to edit sorting/grouping, request.sort and
395    request.group are (possibly empty) lists. You can now sort and group
396    by multiple attributes. For an example, see the classic template. You
397    may want search for the variable ``n_sort`` which can be set to the
398    number of sort/group properties.
400  * Templates that diplay new headlines for each group of items with
401    equal group properties can now use the modified ``batch.propchanged``
402    method that can take several properties which are checked for
403    changes. See the example in the classic template which makes use of
404    ``batch.propchanged``.
406 Migrating from 1.1.0 to 1.1.1
407 =============================
409 1.1.1 "Clear this message"
410 --------------------------
412 In 1.1.1, the standard ``page.html`` template includes a "clear this message"
413 link in the green "ok" message bar that appears after a successful edit
414 (or other) action.
416 To include this in your tracker, change the following in your ``page.html``
417 template::
419  <p tal:condition="options/ok_message | nothing" class="ok-message"
420     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
422 to be::
424  <p tal:condition="options/ok_message | nothing" class="ok-message">
425    <span tal:repeat="m options/ok_message"
426       tal:content="structure string:$m <br/ > " />
427     <a class="form-small" tal:attributes="href request/current_url"
428        i18n:translate="">clear this message</a>
429  </p>
432 If you implemented the "clear this message" in your 1.1.0 tracker, then you
433 should change it to the above and it will work much better!
436 Migrating from 1.0.x to 1.1.0
437 =============================
439 1.1 Login "For Session Only"
440 ----------------------------
442 In 1.1, web logins are alive for the length of a session only, *unless* you
443 add the following to the login form in your tracker's ``page.html``::
445     <input type="checkbox" name="remember" id="remember">
446     <label for="remember" i18n:translate="">Remember me?</label><br>
448 See the classic tracker ``page.html`` if you're unsure where this should
449 go.
452 1.1 Query Display Name
453 ----------------------
455 The ``dispname`` web variable has been renamed ``@dispname`` to avoid
456 clashing with other variables of the same name. If you are using the
457 display name feature, you will need to edit your tracker's ``page.html``
458 and ``issue.index.html`` pages to change ``dispname`` to ``@dispname``.
460 A side-effect of this change is that the renderWith method used in the
461 ``home.html`` page may now take a dispname argument.
464 1.1 "Clear this message"
465 ------------------------
467 In 1.1, the standard ``page.html`` template includes a "clear this message"
468 link in the green "ok" message bar that appears after a successful edit
469 (or other) action.
471 To include this in your tracker, change the following in your ``page.html``
472 template::
474  <p tal:condition="options/ok_message | nothing" class="ok-message"
475     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
477 to be::
479  <p tal:condition="options/ok_message | nothing" class="ok-message">
480    <span tal:repeat="m options/ok_message"
481       tal:content="structure string:$m <br/ > " />
482     <a class="form-small" tal:attributes="href string:issue${context/id}"
483        i18n:translate="">clear this message</a>
484  </p>
487 Migrating from 0.8.x to 1.0
488 ===========================
490 1.0 New Query Permissions
491 -------------------------
493 New permissions are defined for query editing and viewing. To include these
494 in your tracker, you need to add these lines to your tracker's
495 ``schema.py``::
497  # Users should be able to edit and view their own queries. They should also
498  # be able to view any marked as not private. They should not be able to
499  # edit others' queries, even if they're not private
500  def view_query(db, userid, itemid):
501      private_for = db.query.get(itemid, 'private_for')
502      if not private_for: return True
503      return userid == private_for
504  def edit_query(db, userid, itemid):
505      return userid == db.query.get(itemid, 'creator')
506  p = db.security.addPermission(name='View', klass='query', check=view_query,
507      description="User is allowed to view their own and public queries")
508  db.security.addPermissionToRole('User', p)
509  p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
510      description="User is allowed to edit their queries")
511  db.security.addPermissionToRole('User', p)
512  p = db.security.addPermission(name='Create', klass='query',
513      description="User is allowed to create queries")
514  db.security.addPermissionToRole('User', p)
516 and then remove 'query' from the line::
518  # Assign the access and edit Permissions for issue, file and message
519  # to regular users now
520  for cl in 'issue', 'file', 'msg', 'query', 'keyword':
522 so it looks like::
524  for cl in 'issue', 'file', 'msg', 'keyword':
527 Migrating from 0.8.0 to 0.8.3
528 =============================
530 0.8.3 Nosy Handling Changes
531 ---------------------------
533 A change was made to fix a bug in the ``nosyreaction.py`` standard
534 detector. To incorporate this fix in your trackers, you will need to copy
535 the ``nosyreaction.py`` file from the ``templates/classic/detectors``
536 directory of the source to your tracker's ``templates`` directory.
538 If you have modified the ``nosyreaction.py`` file from the standard
539 version, you will need to roll your changes into the new file.
542 Migrating from 0.7.1 to 0.8.0
543 =============================
545 You *must* fully uninstall previous Roundup version before installing
546 Roundup 0.8.0.  If you don't do that, ``roundup-admin install``
547 command may fail to function properly.
549 0.8.0 Backend changes
550 ---------------------
552 Backends 'bsddb' and 'bsddb3' are removed.  If you are using one of these,
553 you *must* migrate to another backend before upgrading.
556 0.8.0 API changes
557 -----------------
559 Class.safeget() was removed from the API. Test your item ids before calling
560 Class.get() instead.
563 0.8.0 New tracker layout
564 ------------------------
566 The ``config.py`` file has been replaced by ``config.ini``. You may use the
567 roundup-admin command "genconfig" to generate a new config file::
569   roundup-admin genconfig <tracker home>/config.ini
571 and modify the values therein based on the contents of your old config.py.
572 In most cases, the names of the config variables are the same.
574 The ``select_db.py`` file has been replaced by a file in the ``db``
575 directory called ``backend_name``. As you might guess, this file contains
576 just the name of the backend. To figure what the contents of yours should
577 be, use the following table:
579   ================================ =========================
580   ``select_db.py`` contents        ``backend_name`` contents
581   ================================ =========================
582   from back_anydbm import ...      anydbm
583   from back_metakit import ...     metakit
584   from back_sqlite import ...      sqlite
585   from back_mysql import ...       mysql
586   from back_postgresql import ...  postgresql
587   ================================ =========================
589 The ``dbinit.py`` file has been split into two new files,
590 ``initial_data.py`` and ``schema.py``. The contents of this file are:
592 ``initial_data.py``
593   You don't need one of these as your tracker is already initialised.
595 ``schema.py``
596   Copy the body of the ``def open(name=None)`` function from your old
597   tracker's ``dbinit.py`` file to this file. As the lines you're copying
598   aren't part of a function definition anymore, one level of indentation
599   needs to be removed (remove only the leading four spaces on each
600   line). 
602   The first few lines -- those starting with ``from roundup.hyperdb
603   import ...`` and the ``db = Database(config, name)`` line -- don't
604   need to be copied. Neither do the last few lines -- those starting
605   with ``import detectors``, down to ``return db`` inclusive.
607 You may remove the ``__init__.py`` module from the "detectors" directory as
608 it is no longer used.
610 There's a new way to write extension code for Roundup. If you have code in
611 an ``interfaces.py`` file you should move it. See the `customisation
612 documentation`_ for information about how extensions are now written.
613 Note that some older trackers may use ``interfaces.py`` to customise the
614 mail gateway behaviour. You will need to keep your ``interfaces.py`` file
615 if this is the case.
618 0.8.0 Permissions Changes
619 -------------------------
621 The creation of a new item in the user interfaces is now controlled by the
622 "Create" Permission. You will need to add an assignment of this Permission
623 to your users who are allowed to create items. The most common form of this
624 is the following in your ``schema.py`` added just under the current
625 assignation of the Edit Permission::
627     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
628         p = db.security.getPermission('Create', cl)
629         db.security.addPermissionToRole('User', p)
631 You will need to explicitly let anonymous users access the web interface so
632 that regular users are able to see the login form. Note that almost all
633 trackers will need this Permission. The only situation where it's not
634 required is in a tracker that uses an HTTP Basic Authenticated front-end.
635 It's enabled by adding to your ``schema.py``::
637     p = db.security.getPermission('Web Access')
638     db.security.addPermissionToRole('Anonymous', p)
640 Finally, you will need to enable permission for your users to edit their
641 own details by adding the following to ``schema.py``::
643     # Users should be able to edit their own details. Note that this
644     # permission is limited to only the situation where the Viewed or
645     # Edited item is their own.
646     def own_record(db, userid, itemid):
647         '''Determine whether the userid matches the item being accessed.'''
648         return userid == itemid
649     p = db.security.addPermission(name='View', klass='user', check=own_record,
650         description="User is allowed to view their own user details")
651     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
652         description="User is allowed to edit their own user details")
653     db.security.addPermissionToRole('User', p)
656 0.8.0 Use of TemplatingUtils
657 ----------------------------
659 If you used custom python functions in TemplatingUtils, they must
660 be moved from interfaces.py to a new file in the ``extensions`` directory. 
662 Each Function that should be available through TAL needs to be defined
663 as a toplevel function in the newly created file. Furthermore you
664 add an inititialization function, that registers the functions with the 
665 tracker.
667 If you find this too tedious, donfu wrote an automatic init function that
668 takes an existing TemplatingUtils class, and registers all class methods
669 that do not start with an underscore. The following hack should be placed
670 in the ``extensions`` directory alongside other extensions::
672     class TemplatingUtils:
673          # copy from interfaces.py
675     def init(tracker):
676          util = TemplatingUtils()
678          def setClient(tu):
679              util.client = tu.client
680              return util
682          def execUtil(name):
683              return lambda tu, *args, **kwargs: \
684                      getattr(setClient(tu), name)(*args, **kwargs)
686          for name in dir(util):
687              if callable(getattr(util, name)) and not name.startswith('_'):
688                   tracker.registerUtil(name, execUtil(name))
691 0.8.0 Logging Configuration
692 ---------------------------
694 See the `administration guide`_ for information about configuring the new
695 logging implemented in 0.8.0.
698 Migrating from 0.7.2 to 0.7.3
699 =============================
701 0.7.3 Configuration
702 -------------------
704 If you choose, you may specify the directory from which static files are
705 served (those which use the URL component ``@@file``). Currently the
706 directory defaults to the ``TEMPLATES`` configuration variable. You may
707 define a new variable, ``STATIC_FILES`` which overrides this value for
708 static files.
711 Migrating from 0.7.0 to 0.7.2
712 =============================
714 0.7.2 DEFAULT_TIMEZONE is now required
715 --------------------------------------
717 The DEFAULT_TIMEZONE configuration variable is now required. Add the
718 following to your tracker's ``config.py`` file::
720     # You may specify a different default timezone, for use when users do not
721     # choose their own in their settings.
722     DEFAULT_TIMEZONE = 0            # specify as numeric hour offest
725 Migrating from 0.7.0 to 0.7.1
726 =============================
728 0.7.1 Permission assignments
729 ----------------------------
731 If you allow anonymous access to your tracker, you might need to assign
732 some additional View (or Edit if your tracker is that open) permissions
733 to the "anonymous" user. To do so, find the code in your ``dbinit.py`` that
734 says::
736     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
737         p = db.security.getPermission('View', cl)
738         db.security.addPermissionToRole('User', p)
739         p = db.security.getPermission('Edit', cl)
740         db.security.addPermissionToRole('User', p)
741     for cl in 'priority', 'status':
742         p = db.security.getPermission('View', cl)
743         db.security.addPermissionToRole('User', p)
745 Add add a line::
747         db.security.addPermissionToRole('Anonymous', p)
749 next to the existing ``'User'`` lines for the Permissions you wish to
750 assign to the anonymous user.
753 Migrating from 0.6 to 0.7
754 =========================
756 0.7.0 Permission assignments
757 ----------------------------
759 Due to a change in the rendering of web widgets, permissions are now
760 checked on Classes where they previously weren't (this is a good thing).
762 You will need to add some additional Permission assignments for your
763 regular users, or some displays will break. After the following in your 
764 tracker's ``dbinit.py``::
766     # Assign the access and edit Permissions for issue, file and message
767     # to regular users now
768     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
769         p = db.security.getPermission('View', cl)
770         db.security.addPermissionToRole('User', p)
771         p = db.security.getPermission('Edit', cl)
772         db.security.addPermissionToRole('User', p)
774 add::
776     for cl in 'priority', 'status':
777         p = db.security.getPermission('View', cl)
778         db.security.addPermissionToRole('User', p)
781 0.7.0 Getting the current user id
782 ---------------------------------
784 The Database.curuserid attribute has been removed.
786 Any code referencing this attribute should be replaced with a
787 call to Database.getuid().
790 0.7.0 ZRoundup changes
791 ----------------------
793 The templates in your tracker's html directory will need updating if you
794 wish to use ZRoundup. If you've not modified those files (or some of them),
795 you may just copy the new versions from the Roundup source in the
796 templates/classic/html directory.
798 If you have modified the html files, then you'll need to manually edit them
799 to change all occurances of special form variables from using the colon ":"
800 special character to the at "@" special character. That is, variables such
801 as::
803   :action :required :template :remove:messages ...
805 should become::
807   @action @required @template @remove@messages ...
809 Note that ``tal:`` statements are unaffected. So are TAL expression type
810 prefixes such as ``python:`` and ``string:``. Please ask on the
811 roundup-users mailing list for help if you're unsure.
814 0.7.0 Edit collision detection
815 ------------------------------
817 Roundup now detects collisions with editing in the web interface (that is,
818 two people editing the same item at the same time).
820 You must copy the ``_generic.collision.html`` file from Roundup source in
821 the ``templates/classic/html`` directory. to your tracker's ``html``
822 directory.
825 Migrating from 0.6.x to 0.6.3
826 =============================
828 0.6.3 Configuration
829 -------------------
831 You will need to copy the file::
833   templates/classic/detectors/__init__.py
835 to your tracker's ``detectors`` directory, replacing the one already there.
836 This fixes a couple of bugs in that file.
840 Migrating from 0.5 to 0.6
841 =========================
844 0.6.0 Configuration
845 -------------------
847 Introduced EMAIL_FROM_TAG config variable. This value is inserted into
848 the From: line of nosy email. If the sending user is "Foo Bar", the
849 From: line is usually::
851      "Foo Bar" <issue_tracker@tracker.example>
853 the EMAIL_FROM_TAG goes inside the "Foo Bar" quotes like so::
855      "Foo Bar EMAIL_FROM_TAG" <issue_tracker@tracker.example>
857 I've altered the mechanism in the detectors __init__.py module so that it
858 doesn't cross-import detectors from other trackers (if you run more than one
859 in a single roundup-server). This change means that you'll need to copy the
860 __init__.py from roundup/templates/classic/detectors/__init__.py to your
861 <tracker home>/detectors/__init__.py. Don't worry, the "classic" __init__ is a
862 one-size-fits-all, so it'll work even if you've added/removed detectors.
864 0.6.0 Templating changes
865 ------------------------
867 The ``user.item`` template (in the tracker home "templates" directory)
868 needs to have the following hidden variable added to its form (between the
869 ``<form...>`` and ``</form>`` tags::
871   <input type="hidden" name=":template" value="item">
874 0.6.0 Form handling changes
875 ---------------------------
877 Roundup's form handling capabilities have been significantly expanded. This
878 should not affect users of 0.5 installations - but if you find you're
879 getting errors from form submissions, please ask for help on the Roundup
880 users mailing list:
882   http://lists.sourceforge.net/lists/listinfo/roundup-users
884 See the customisation doc section on `Form Values`__ for documentation of the
885 new form variables possible.
887 __ customizing.html#form-values
890 0.6.0 Multilingual character set support
891 ----------------------------------------
893 Added internationalization support. This is done via encoding all data
894 stored in roundup database to utf-8 (unicode encoding). To support utf-8 in
895 web interface you should add the folowing line to your tracker's html/page
896 and html/_generic.help files inside <head> tag::
897   
898     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
900 Since latin characters in utf-8 have the same codes as in ASCII table, this
901 modification is optional for users who use only plain latin characters. 
903 After this modification, you will be able to see and enter any world
904 character via web interface. Data received via mail interface also converted
905 to utf-8, however only new messages will be converted. If your roundup
906 database contains some of non-ASCII characters in one of 8-bit encoding,
907 they will not be visible in new unicode environment. Some of such data (e.g.
908 user names, keywords, etc)  can be edited by administrator, the others
909 (e.g. messages' contents) is not editable via web interface. Currently there
910 is no tool for converting such data, the only solution is to close
911 appropriate old issues and create new ones with the same content.
914 0.6.0 User timezone support
915 ---------------------------
917 From version 0.6.0 roundup supports displaying of Date data in user' local
918 timezone if he/she has provided timezone information. To make it possible
919 some modification to tracker's schema and HTML templates are required.
920 First you must add string property 'timezone' to user class in dbinit.py
921 like this::
922   
923     user = Class(db, "user", 
924                     username=String(),   password=Password(),
925                     address=String(),    realname=String(), 
926                     phone=String(),      organisation=String(),
927                     alternate_addresses=String(),
928                     queries=Multilink('query'), roles=String(),
929                     timezone=String())
930   
931 And second - html interface. Add following lines to
932 $TRACKER_HOME/html/user.item template::
933   
934      <tr>
935       <th>Timezone</th>
936       <td tal:content="structure context/timezone/field">timezone</td>
937      </tr>
939 After that all users should be able to provide their timezone information.
940 Timezone should be a positive or negative integer - offset from GMT.
942 After providing timezone, roundup will show all dates values, found in web
943 and mail interfaces in local time. It will also accept any Date info in
944 local time, convert and store it in GMT.
947 0.6.0 Search page structure
948 ---------------------------
950 In order to accomodate query editing the search page has been restructured. If
951 you want to provide your users with query editing, you should update your
952 search page using the macros detailed in the customisation doc section
953 `Searching on categories`__.
955 __ customizing.html#searching-on-categories
957 Also, the url field in the query class no longer starts with a '?'. You'll need
958 to remove this question mark from the url field to support queries. There's
959 a script in the "tools" directory called ``migrate-queries.py`` that should
960 automatically change any existing queries for you. As always, make a backup
961 of your database before running such a script.
964 0.6.0 Notes for metakit backend users
965 -------------------------------------
967 Roundup 0.6.0 introduced searching on ranges of dates and intervals. To
968 support it, some modifications to interval storing routine were made. So if
969 your tracker uses metakit backend and your db schema contains intervals
970 property, searches on that property will not be accurate for db items that
971 was stored before roundup' upgrade. However all new records should be
972 searchable on intervals.
974 It is possible to convert your database to new format: you can export and
975 import back all your data (consult "Migrating backends" in "Maintenance"
976 documentation). After this operation all your interval properties should
977 become searchable.
979 Users of backends others than metakit should not worry about this issue.
982 Migrating from 0.4.x to 0.5.0
983 =============================
985 This has been a fairly major revision of Roundup:
987 1. Brand new, much more powerful, flexible, tasty and nutritious templating.
988    Unfortunately, this means all your current templates are useless. Hopefully
989    the new documentation and examples will be enough to help you make the
990    transition. Please don't hesitate to ask on roundup-users for help (or
991    complete conversions if you're completely stuck)!
992 2. The database backed got a lot more flexible, allowing Metakit and SQL
993    databases! The only decent SQL database implemented at present is sqlite,
994    but others shouldn't be a whole lot more work.
995 3. A brand new, highly flexible and much more robust security system including
996    a system of Permissions, Roles and Role assignments to users. You may now
997    define your own Permissions that may be checked in CGI transactions.
998 4. Journalling has been made less storage-hungry, so has been turned on
999    by default *except* for author, recipient and nosy link/unlink events. You
1000    are advised to turn it off in your trackers too.
1001 5. We've changed the terminology from "instance" to "tracker", to ease the
1002    learning curve/impact for new users.
1003 6. Because of the above changes, the tracker configuration has seen some
1004    major changes. See below for the details.
1006 Please, **back up your database** before you start the migration process. This
1007 is as simple as copying the "db" directory and all its contents from your
1008 tracker to somewhere safe.
1011 0.5.0 Configuration
1012 -------------------
1014 First up, rename your ``instance_config.py`` file to just ``config.py``.
1016 Then edit your tracker's ``__init__.py`` module. It'll currently look
1017 like this::
1019  from instance_config import *
1020  try:
1021      from dbinit import *
1022  except ImportError:
1023      pass # in installdir (probably :)
1024  from interfaces import *
1026 and it needs to be::
1028  import config
1029  from dbinit import open, init
1030  from interfaces import Client, MailGW
1032 Due to the new templating having a top-level ``page`` that defines links for
1033 searching, indexes, adding items etc, the following variables are no longer
1034 used:
1036 - HEADER_INDEX_LINKS
1037 - HEADER_ADD_LINKS
1038 - HEADER_SEARCH_LINKS
1039 - SEARCH_FILTERS
1040 - DEFAULT_INDEX
1041 - UNASSIGNED_INDEX
1042 - USER_INDEX
1043 - ISSUE_FILTER
1045 The new security implementation will require additions to the dbinit module,
1046 but also removes the need for the following tracker config variables:
1048 - ANONYMOUS_ACCESS
1049 - ANONYMOUS_REGISTER
1051 but requires two new variables which define the Roles assigned to users who
1052 register through the web and e-mail interfaces:
1054 - NEW_WEB_USER_ROLES
1055 - NEW_EMAIL_USER_ROLES
1057 in both cases, 'User' is a good initial setting. To emulate
1058 ``ANONYMOUS_ACCESS='deny'``, remove all "View" Permissions from the
1059 "Anonymous" Role. To emulate ``ANONYMOUS_REGISTER='deny'``, remove the "Web
1060 Registration" and/or the "Email Registration" Permission from the "Anonymous"
1061 Role. See the section on customising security in the `customisation
1062 documentation`_ for more information.
1064 Finally, the following config variables have been renamed to make more sense:
1066 - INSTANCE_HOME -> TRACKER_HOME
1067 - INSTANCE_NAME -> TRACKER_NAME
1068 - ISSUE_TRACKER_WEB -> TRACKER_WEB
1069 - ISSUE_TRACKER_EMAIL -> TRACKER_EMAIL
1072 0.5.0 Schema Specification
1073 --------------------------
1075 0.5.0 Database backend changes
1076 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1078 Your select_db module in your tracker has changed a fair bit. Where it used
1079 to contain::
1081  # WARNING: DO NOT EDIT THIS FILE!!!
1082  from roundup.backends.back_anydbm import Database
1084 it must now contain::
1086  # WARNING: DO NOT EDIT THIS FILE!!!
1087  from roundup.backends.back_anydbm import Database, Class, FileClass, IssueClass
1089 Yes, I realise the irony of the "DO NOT EDIT THIS FILE" statement :)
1090 Note the addition of the Class, FileClass, IssueClass imports. These are very
1091 important, as they're going to make the next change work too. You now need to
1092 modify the top of the dbinit module in your tracker from::
1094  import instance_config
1095  from roundup import roundupdb
1096  from select_db import Database
1098  from roundup.roundupdb import Class, FileClass
1100  class Database(roundupdb.Database, select_db.Database):
1101      ''' Creates a hybrid database from:
1102           . the selected database back-end from select_db
1103           . the roundup extensions from roundupdb
1104      '''
1105      pass
1107  class IssueClass(roundupdb.IssueClass):
1108      ''' issues need the email information
1109      '''
1110      pass
1112 to::
1114  import config
1115  from select_db import Database, Class, FileClass, IssueClass
1117 Yes, remove the Database and IssueClass definitions and those other imports.
1118 They're not needed any more!
1120 Look for places in dbinit.py where ``instance_config`` is used too, and
1121 rename them ``config``.
1124 0.5.0 Journalling changes
1125 ~~~~~~~~~~~~~~~~~~~~~~~~~
1127 Journalling has been optimised for storage. Journalling of links has been
1128 turned back on by default. If your tracker has a large user base, you may wish
1129 to turn off journalling of nosy list, message author and message recipient
1130 link and unlink events. You do this by adding ``do_journal='no'`` to the Class
1131 initialisation in your dbinit. For example, your *msg* class initialisation
1132 probably looks like this::
1134     msg = FileClass(db, "msg",
1135                     author=Link("user"), recipients=Multilink("user"),
1136                     date=Date(),         summary=String(),
1137                     files=Multilink("file"),
1138                     messageid=String(),  inreplyto=String())
1140 to turn off journalling of author and recipient link events, add
1141 ``do_journal='no'`` to the ``author=Link("user")`` part of the statement,
1142 like so::
1144     msg = FileClass(db, "msg",
1145                     author=Link("user", do_journal='no'),
1146                     recipients=Multilink("user", do_journal='no'),
1147                     date=Date(),         summary=String(),
1148                     files=Multilink("file"),
1149                     messageid=String(),  inreplyto=String())
1151 Nosy list link event journalling is actually turned off by default now. If you
1152 want to turn it on, change to your issue class' nosy list, change its
1153 definition from::
1155     issue = IssueClass(db, "issue",
1156                     assignedto=Link("user"), topic=Multilink("keyword"),
1157                     priority=Link("priority"), status=Link("status"))
1159 to::
1161     issue = IssueClass(db, "issue", nosy=Multilink("user", do_journal='yes'),
1162                     assignedto=Link("user"), topic=Multilink("keyword"),
1163                     priority=Link("priority"), status=Link("status"))
1165 noting that your definition of the nosy Multilink will override the normal one.
1168 0.5.0 User schema changes
1169 ~~~~~~~~~~~~~~~~~~~~~~~~~
1171 Users have two more properties, "queries" and "roles". You'll have something
1172 like this in your dbinit module now::
1174     user = Class(db, "user",
1175                     username=String(),   password=Password(),
1176                     address=String(),    realname=String(),
1177                     phone=String(),      organisation=String(),
1178                     alternate_addresses=String())
1179     user.setkey("username")
1181 and you'll need to add the new properties and the new "query" class to it
1182 like so::
1184     query = Class(db, "query",
1185                     klass=String(),     name=String(),
1186                     url=String())
1187     query.setkey("name")
1189     # Note: roles is a comma-separated string of Role names
1190     user = Class(db, "user",
1191                     username=String(),   password=Password(),
1192                     address=String(),    realname=String(),
1193                     phone=String(),      organisation=String(),
1194                     alternate_addresses=String(),
1195                     queries=Multilink('query'), roles=String())
1196     user.setkey("username")
1198 The "queries" property is used to store off the user's favourite database
1199 queries. The "roles" property is explained below in `0.5.0 Security
1200 Settings`_.
1203 0.5.0 Security Settings
1204 ~~~~~~~~~~~~~~~~~~~~~~~
1206 See the `security documentation`_ for an explanation of how the new security
1207 system works. In a nutshell though, the security is handled as a four step
1208 process:
1210 1. Permissions are defined as having a name and optionally a hyperdb class
1211    they're specific to,
1212 2. Roles are defined that have one or more Permissions,
1213 3. Users are assigned Roles in their "roles" property, and finally
1214 4. Roundup checks that users have appropriate Permissions at appropriate times
1215    (like editing issues).
1217 Your tracker dbinit module's *open* function now has to define any
1218 Permissions that are specific to your tracker, and also the assignment
1219 of Permissions to Roles. At the moment, your open function
1220 ends with::
1222     import detectors
1223     detectors.init(db)
1225     return db
1227 and what we need to do is insert some commands that will set up the security
1228 parameters. Right above the ``import detectors`` line, you'll want to insert
1229 these lines::
1231     #
1232     # SECURITY SETTINGS
1233     #
1234     # new permissions for this schema
1235     for cl in 'issue', 'file', 'msg', 'user':
1236         db.security.addPermission(name="Edit", klass=cl,
1237             description="User is allowed to edit "+cl)
1238         db.security.addPermission(name="View", klass=cl,
1239             description="User is allowed to access "+cl)
1241     # Assign the access and edit permissions for issue, file and message
1242     # to regular users now
1243     for cl in 'issue', 'file', 'msg':
1244         p = db.security.getPermission('View', cl)
1245         db.security.addPermissionToRole('User', p)
1246         p = db.security.getPermission('Edit', cl)
1247         db.security.addPermissionToRole('User', p)
1248     # and give the regular users access to the web and email interface
1249     p = db.security.getPermission('Web Access')
1250     db.security.addPermissionToRole('User', p)
1251     p = db.security.getPermission('Email Access')
1252     db.security.addPermissionToRole('User', p)
1254     # May users view other user information? Comment these lines out
1255     # if you don't want them to
1256     p = db.security.getPermission('View', 'user')
1257     db.security.addPermissionToRole('User', p)
1259     # Assign the appropriate permissions to the anonymous user's Anonymous
1260     # Role. Choices here are:
1261     # - Allow anonymous users to register through the web
1262     p = db.security.getPermission('Web Registration')
1263     db.security.addPermissionToRole('Anonymous', p)
1264     # - Allow anonymous (new) users to register through the email gateway
1265     p = db.security.getPermission('Email Registration')
1266     db.security.addPermissionToRole('Anonymous', p)
1267     # - Allow anonymous users access to the "issue" class of data
1268     #   Note: this also grants access to related information like files,
1269     #         messages, statuses etc that are linked to issues
1270     #p = db.security.getPermission('View', 'issue')
1271     #db.security.addPermissionToRole('Anonymous', p)
1272     # - Allow anonymous users access to edit the "issue" class of data
1273     #   Note: this also grants access to create related information like
1274     #         files and messages etc that are linked to issues
1275     #p = db.security.getPermission('Edit', 'issue')
1276     #db.security.addPermissionToRole('Anonymous', p)
1278     # oh, g'wan, let anonymous access the web interface too
1279     p = db.security.getPermission('Web Access')
1280     db.security.addPermissionToRole('Anonymous', p)
1282 Note in the comments there the places where you might change the permissions
1283 to restrict users or grant users more access. If you've created additional
1284 classes that users should be able to edit and view, then you should add them
1285 to the "new permissions for this schema" section at the start of the security
1286 block. Then add them to the "Assign the access and edit permissions" section
1287 too, so people actually have the new Permission you've created.
1289 One final change is needed that finishes off the security system's
1290 initialisation. We need to add a call to ``db.post_init()`` at the end of the
1291 dbinit open() function. Add it like this::
1293     import detectors
1294     detectors.init(db)
1296     # schema is set up - run any post-initialisation
1297     db.post_init()
1298     return db
1300 You may verify the setup of Permissions and Roles using the new
1301 "``roundup-admin security``" command.
1304 0.5.0 User changes
1305 ~~~~~~~~~~~~~~~~~~
1307 To support all those schema changes, you'll need to massage your user database
1308 a little too, to:
1310 1. make sure there's an "anonymous" user - this user is mandatory now and is
1311    the one that unknown users are logged in as.
1312 2. make sure all users have at least one Role.
1314 If you don't have the "anonymous" user, create it now with the command::
1316   roundup-admin create user username=anonymous roles=Anonymous
1318 making sure the capitalisation is the same as above. Once you've done that,
1319 you'll need to set the roles property on all users to a reasonable default.
1320 The admin user should get "Admin", the anonymous user "Anonymous"
1321 and all other users "User". The ``fixroles.py`` script in the tools directory
1322 will do this. Run it like so (where python is your python 2+ binary)::
1324   python tools/fixroles.py -i <tracker home> fixroles
1328 0.5.0 CGI interface changes
1329 ---------------------------
1331 The CGI interface code was completely reorganised and largely rewritten. The
1332 end result is that this section of your tracker interfaces module will need
1333 changing from::
1335  from roundup import cgi_client, mailgw
1336  from roundup.i18n import _
1337  
1338  class Client(cgi_client.Client):
1339      ''' derives basic CGI implementation from the standard module,
1340          with any specific extensions
1341      '''
1342      pass
1344 to::
1346  from roundup import mailgw
1347  from roundup.cgi import client
1348  
1349  class Client(client.Client): 
1350      ''' derives basic CGI implementation from the standard module,
1351          with any specific extensions
1352      '''
1353      pass
1355 You will also need to install the new version of roundup.cgi from the source
1356 cgi-bin directory if you're using it.
1359 0.5.0 HTML templating
1360 ---------------------
1362 You'll want to make a backup of your current tracker html directory. You
1363 should then copy the html directory from the Roundup source "classic" template
1364 and modify it according to your local schema changes.
1366 If you need help with the new templating system, please ask questions on the
1367 roundup-users mailing list (available through the roundup project page on
1368 sourceforge, http://roundup.sf.net/)
1371 0.5.0 Detectors
1372 ---------------
1374 The nosy reactor has been updated to handle the tracker not having an
1375 "assignedto" property on issues. You may want to copy it into your tracker's
1376 detectors directory. Chances are you've already fixed it though :)
1379 Migrating from 0.4.1 to 0.4.2
1380 =============================
1382 0.4.2 Configuration
1383 -------------------
1384 The USER_INDEX definition introduced in 0.4.1 was too restrictive in its
1385 allowing replacement of 'assignedto' with the user's userid. Users must change
1386 the None value of 'assignedto' to 'CURRENT USER' (the string, in quotes) for
1387 the replacement behaviour to occur now.
1389 The new configuration variables are:
1391 - EMAIL_KEEP_QUOTED_TEXT 
1392 - EMAIL_LEAVE_BODY_UNCHANGED
1393 - ADD_RECIPIENTS_TO_NOSY
1395 See the sample configuration files in::
1397  <roundup source>/roundup/templates/classic/instance_config.py
1399 and::
1401  <roundup source>/roundup/templates/extended/instance_config.py
1403 and the `customisation documentation`_ for information on how they're used.
1406 0.4.2 Changes to detectors
1407 --------------------------
1408 You will need to copy the detectors from the distribution into your instance
1409 home "detectors" directory. If you used the classic schema, the detectors
1410 are in::
1412  <roundup source>/roundup/templates/classic/detectors/
1414 If you used the extended schema, the detectors are in::
1416  <roundup source>/roundup/templates/extended/detectors/
1418 The change means that schema-specific code has been removed from the
1419 mail gateway and cgi interface and made into auditors:
1421 - nosyreactor.py has now got an updatenosy auditor which updates the nosy
1422   list with author, recipient and assignedto information.
1423 - statusauditor.py makes the unread or resolved -> chatting changes and
1424   presets the status of an issue to unread.
1426 There's also a bug or two fixed in the nosyreactor code.
1428 0.4.2 HTML templating changes
1429 -----------------------------
1430 The link() htmltemplate function now has a "showid" option for links and
1431 multilinks. When true, it only displays the linked item id as the anchor
1432 text. The link value is displayed as a tooltip using the title anchor
1433 attribute. To use in eg. the superseder field, have something like this::
1435    <td>
1436     <display call="field('superseder', showid=1)">
1437     <display call="classhelp('issue', 'id,title', label='list', width=500)">
1438     <property name="superseder">
1439      <br>View: <display call="link('superseder', showid=1)">
1440     </property>
1441    </td>
1443 The stylesheets have been cleaned up too. You may want to use the newer
1444 versions in::
1446  <roundup source>/roundup/templates/<template>/html/default.css
1450 Migrating from 0.4.0 to 0.4.1
1451 =============================
1453 0.4.1 Files storage
1454 -------------------
1456 Messages and files from newly created issues will be put into subdierectories
1457 in thousands e.g. msg123 will be put into files/msg/0/msg123, file2003
1458 will go into files/file/2/file2003. Previous messages are still found, but
1459 could be put into this structure.
1461 0.4.1 Configuration
1462 -------------------
1464 To allow more fine-grained access control, the variable used to check
1465 permission to auto-register users in the mail gateway is now called
1466 ANONYMOUS_REGISTER_MAIL rather than overloading ANONYMOUS_REGISTER. If the
1467 variable doesn't exist, then ANONYMOUS_REGISTER is tested as before.
1469 Configuring the links in the web header is now easier too. The following
1470 variables have been added to the classic instance_config.py::
1472   HEADER_INDEX_LINKS   - defines the "index" links to be made available
1473   HEADER_ADD_LINKS     - defines the "add" links
1474   DEFAULT_INDEX        - specifies the index view for DEFAULT
1475   UNASSIGNED_INDEX     - specifies the index view for UNASSIGNED
1476   USER_INDEX           - specifies the index view for USER
1478 See the <roundup source>/roundup/templates/classic/instance_config.py for more
1479 information - including how the variables are to be set up. Most users will
1480 just be able to copy the variables from the source to their instance home. If
1481 you've modified the header by changing the source of the interfaces.py file in
1482 the instance home, you'll need to remove that customisation and move it into
1483 the appropriate variables in instance_config.py.
1485 The extended schema has similar variables added too - see the source for more
1486 info.
1488 0.4.1 Alternate E-Mail Addresses
1489 --------------------------------
1491 If you add the property "alternate_addresses" to your user class, your users
1492 will be able to register alternate email addresses that they may use to
1493 communicate with roundup as. All email from roundup will continue to be sent
1494 to their primary address.
1496 If you have not edited the dbinit.py file in your instance home directory,
1497 you may simply copy the new dbinit.py file from the core code. If you used
1498 the classic schema, the interfaces file is in::
1500  <roundup source>/roundup/templates/classic/dbinit.py
1502 If you used the extended schema, the file is in::
1504  <roundup source>/roundup/templates/extended/dbinit.py 
1506 If you have modified your dbinit.py file, you need to edit the dbinit.py
1507 file in your instance home directory. Find the lines which define the user
1508 class::
1510     user = Class(db, "msg",
1511                     username=String(),   password=Password(),
1512                     address=String(),    realname=String(), 
1513                     phone=String(),      organisation=String(),
1514                     alternate_addresses=String())
1516 You will also want to add the property to the user's details page. The
1517 template for this is the "user.item" file in your instance home "html"
1518 directory. Similar to above, you may copy the file from the roundup source if
1519 you haven't modified it. Otherwise, add the following to the template::
1521    <display call="multiline('alternate_addresses')">
1523 with appropriate labelling etc. See the standard template for an idea.
1527 Migrating from 0.3.x to 0.4.0
1528 =============================
1530 0.4.0 Message-ID and In-Reply-To addition
1531 -----------------------------------------
1532 0.4.0 adds the tracking of messages by message-id and allows threading
1533 using in-reply-to. Most e-mail clients support threading using this
1534 feature, and we hope to add support for it to the web gateway. If you
1535 have not edited the dbinit.py file in your instance home directory, you may
1536 simply copy the new dbinit.py file from the core code. If you used the
1537 classic schema, the interfaces file is in::
1539  <roundup source>/roundup/templates/classic/dbinit.py
1541 If you used the extended schema, the file is in::
1543  <roundup source>/roundup/templates/extended/dbinit.py 
1545 If you have modified your dbinit.py file, you need to edit the dbinit.py
1546 file in your instance home directory. Find the lines which define the msg
1547 class::
1549     msg = FileClass(db, "msg",
1550                     author=Link("user"), recipients=Multilink("user"),
1551                     date=Date(),         summary=String(),
1552                     files=Multilink("file"))
1554 and add the messageid and inreplyto properties like so::
1556     msg = FileClass(db, "msg",
1557                     author=Link("user"), recipients=Multilink("user"),
1558                     date=Date(),         summary=String(),
1559                     files=Multilink("file"),
1560                     messageid=String(),  inreplyto=String())
1562 Also, configuration is being cleaned up. This means that your dbinit.py will
1563 also need to be changed in the open function. If you haven't changed your
1564 dbinit.py, the above copy will be enough. If you have, you'll need to change
1565 the line (round line 50)::
1567     db = Database(instance_config.DATABASE, name)
1569 to::
1571     db = Database(instance_config, name)
1574 0.4.0 Configuration
1575 --------------------
1576 ``TRACKER_NAME`` and ``EMAIL_SIGNATURE_POSITION`` have been added to the
1577 instance_config.py. The simplest solution is to copy the default values
1578 from template in the core source.
1580 The mail gateway now checks ``ANONYMOUS_REGISTER`` to see if unknown users
1581 are to be automatically registered with the tracker. If it is set to "deny"
1582 then unknown users will not have access. If it is set to "allow" they will be
1583 automatically registered with the tracker.
1586 0.4.0 CGI script roundup.cgi
1587 ----------------------------
1588 The CGI script has been updated with some features and a bugfix, so you should
1589 copy it from the roundup cgi-bin source directory again. Make sure you update
1590 the ROUNDUP_INSTANCE_HOMES after the copy.
1593 0.4.0 Nosy reactor
1594 ------------------
1595 The nosy reactor has also changed - copy the nosyreactor.py file from the core
1596 source::
1598    <roundup source>/roundup/templates/<template>/detectors/nosyreactor.py
1600 to your instance home "detectors" directory.
1603 0.4.0 HTML templating
1604 ---------------------
1605 The field() function was incorrectly implemented - links and multilinks now
1606 display as text fields when rendered using field(). To display a menu (drop-
1607 down or select box) you need to use the menu() function.
1611 Migrating from 0.2.x to 0.3.x
1612 =============================
1614 0.3.x Cookie Authentication changes
1615 -----------------------------------
1616 0.3.0 introduces cookie authentication - you will need to copy the
1617 interfaces.py file from the roundup source to your instance home to enable
1618 authentication. If you used the classic schema, the interfaces file is in::
1620  <roundup source>/roundup/templates/classic/interfaces.py
1622 If you used the extended schema, the file is in::
1624  <roundup source>/roundup/templates/extended/interfaces.py
1626 If you have modified your interfaces.Client class, you will need to take
1627 note of the login/logout functionality provided in roundup.cgi_client.Client
1628 (classic schema) or roundup.cgi_client.ExtendedClient (extended schema) and
1629 modify your instance code apropriately.
1632 0.3.x Password encoding
1633 -----------------------
1634 This release also introduces encoding of passwords in the database. If you
1635 have not edited the dbinit.py file in your instance home directory, you may
1636 simply copy the new dbinit.py file from the core code. If you used the
1637 classic schema, the interfaces file is in::
1639  <roundup source>/roundup/templates/classic/dbinit.py
1641 If you used the extended schema, the file is in::
1643  <roundup source>/roundup/templates/extended/dbinit.py
1646 If you have modified your dbinit.py file, you may use encoded passwords:
1648 1. Edit the dbinit.py file in your instance home directory
1649    a. At the first code line of the open() function::
1651        from roundup.hyperdb import String, Date, Link, Multilink
1653       alter to include Password, as so::
1655        from roundup.hyperdb import String, Password, Date, Link, Multilink
1657    b. Where the password property is defined (around line 66)::
1659        user = Class(db, "user", 
1660                        username=String(),   password=String(),
1661                        address=String(),    realname=String(), 
1662                        phone=String(),      organisation=String())
1663        user.setkey("username")
1665       alter the "password=String()" to "password=Password()"::
1667        user = Class(db, "user", 
1668                        username=String(),   password=Password(),
1669                        address=String(),    realname=String(), 
1670                        phone=String(),      organisation=String())
1671        user.setkey("username")
1673 2. Any existing passwords in the database will remain cleartext until they
1674    are edited. It is recommended that at a minimum the admin password be
1675    changed immediately::
1677       roundup-admin -i <instance home> set user1 password=<new password>
1680 0.3.x Configuration
1681 -------------------
1682 FILTER_POSITION, ANONYMOUS_ACCESS, ANONYMOUS_REGISTER have been added to
1683 the instance_config.py. Simplest solution is to copy the default values from
1684 template in the core source.
1686 MESSAGES_TO_AUTHOR has been added to the IssueClass in dbinit.py. Set to 'yes'
1687 to send nosy messages to the author. Default behaviour is to not send nosy
1688 messages to the author. You will need to add MESSAGES_TO_AUTHOR to your
1689 dbinit.py in your instance home.
1692 0.3.x CGI script roundup.cgi
1693 ----------------------------
1694 There have been some structural changes to the roundup.cgi script - you will
1695 need to install it again from the cgi-bin directory of the source
1696 distribution. Make sure you update the ROUNDUP_INSTANCE_HOMES after the
1697 copy.
1700 .. _`customisation documentation`: customizing.html
1701 .. _`security documentation`: security.html
1702 .. _`administration guide`: admin_guide.html