Code

Fix security hole allowing user permission escalation (thanks Ralf Schlatterbeck)
[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.11
17 ==============================
19 Close poential security hole
20 ----------------------------
22 If your tracker has untrusted users you should examine its ``schema.py``
23 file and look for the section granting the "Edit" permission to your users.
24 This should look something like::
26     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
27         description="User is allowed to edit their own user details")
29 and should be modified to restrict the list of properties they are allowed
30 to edit by adding the ``properties=`` section like::
32     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
33         properties=('username', 'password', 'address', 'realname', 'phone',
34             'organisation', 'alternate_addresses', 'queries', 'timezone'),
35         description="User is allowed to edit their own user details")
37 Most importantly the "roles" property should not be editable - thus not
38 appear in that list of properties.
41 Grant the "Register" permission to the Anonymous role
42 -----------------------------------------------------
44 A separate "Register" permission has been introduced to allow
45 anonymous users to register. This means you will need to add the
46 following to your tracker's ``schema.py`` to add the permission and
47 assign it to the Anonymous role (replacing any previously assigned
48 "Create user" permission for the Anonymous role):
50   +db.security.addPermission(name='Register', klass='user',
51   +                          description='User is allowed to register new user')
52  
53    # Assign the appropriate permissions to the anonymous user's Anonymous
54    # Role. Choices here are:
55    # - Allow anonymous users to register
56   -db.security.addPermissionToRole('Anonymous', 'Create', 'user')
57   +db.security.addPermissionToRole('Anonymous', 'Register', 'user')
59 The lines marked "+" should be added and lines marked "-" should be
60 deleted (minus the "+"/"-" signs).
63 Migrating from 1.4.x to 1.4.9
64 =============================
66 Customized MailGW Class
67 -----------------------
69 If you have customized the MailGW class in your tracker: The new MailGW
70 class opens the database for each message in the method handle_message
71 (instance.open) instead of passing the opened database as a parameter to
72 the MailGW constructor. The old handle_message has been renamed to
73 _handle_message. The new method opens the database and wraps the call to
74 the old method into a try/finally.
76 Your customized MailGW class needs to mirror this behavior.
78 Fix the "remove" button in issue files and messages lists
79 ---------------------------------------------------------
81 The "remove" button(s) in the issue messages list needs to be altered. Find
82 the following in your tracker's ``html/issue.item.html`` template::
84   <td>
85    <form style="padding:0" tal:condition="context/is_edit_ok"
86          tal:attributes="action string:issue${context/id}">
87     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
89 and add ``method="POST"`` as shown below::
91   <td>
92    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
93          tal:attributes="action string:issue${context/id}">
94     <input type="hidden" name="@remove@files" tal:attributes="value file/id">
96 Then also find::
98   <td>
99    <form style="padding:0" tal:condition="context/is_edit_ok"
100          tal:attributes="action string:issue${context/id}">
101     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
103 and add ``method="POST"`` as shown below::
105   <td>
106    <form style="padding:0" method="POST" tal:condition="context/is_edit_ok"
107          tal:attributes="action string:issue${context/id}">
108     <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
111 Fixing the "retire" button in user management list
112 --------------------------------------------------
114 If you made the change to the "reture" link in the user management list as
115 listed below in `Migrating from 1.4.x to 1.4.7`_ then you'll need to fix that
116 change by adding ``method="POST"`` to the ``<form>`` tag::
118      <form style="padding:0" method="POST"
119            tal:attributes="action string:user${user/id}">
120       <input type="hidden" name="@template" value="index">
121       <input type="hidden" name="@action" value="retire">
122       <input type="submit" value="retire" i18n:attributes="value">
123      </form>
126 Migrating from 1.4.x to 1.4.7
127 =============================
129 Several security issues were addressed in this release. Some aspects of your
130 trackers may no longer function depending on your local customisations. Core
131 functionality that will need to be modified:
133 Grant the "retire" permission to users for their queries
134 --------------------------------------------------------
136 Users will no longer be able to retire their own queries. To remedy this you
137 will need to add the following to your tracker's ``schema.py`` just under the
138 line that grants them permission to edit their own queries::
140    p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
141       description="User is allowed to edit their queries")
142    db.security.addPermissionToRole('User', p)
143  + p = db.security.addPermission(name='Retire', klass='query', check=edit_query,
144  +    description="User is allowed to retire their queries")
145  + db.security.addPermissionToRole('User', p)
146    p = db.security.addPermission(name='Create', klass='query',
147       description="User is allowed to create queries")
148    db.security.addPermissionToRole('User', p)
150 The lines marked "+" should be added, minus the "+" sign.
153 Fix the "retire" link in the users list for admin users
154 -------------------------------------------------------
156 The "retire" link found in the file ``html/users.index.html``::
158   <td tal:condition="context/is_edit_ok">
159    <a tal:attributes="href string:user${user/id}?@action=retire&@template=index"
160     i18n:translate="">retire</a>
162 Should be replaced with::
164   <td tal:condition="context/is_retire_ok">
165      <form style="padding:0" method="POST"
166            tal:attributes="action string:user${user/id}">
167       <input type="hidden" name="@template" value="index">
168       <input type="hidden" name="@action" value="retire">
169       <input type="submit" value="retire" i18n:attributes="value">
170      </form>
173 Fix for Python 2.6+ users
174 -------------------------
176 If you use Python 2.6 you should edit your tracker's
177 ``detectors/nosyreaction.py`` file to change::
179    import sets
181 at the top to::
183    from roundup.anypy.sets_ import set
185 and then all instances of ``sets.Set()`` to ``set()`` in the later code.
189 Trackers currently allowing HTML file uploading
190 -----------------------------------------------
192 Trackers which wish to continue to allow uploading of HTML content against issues
193 will need to set a new configuration variable in the ``[web]`` section of the
194 tracker's ``config.ini`` file:
196    # Setting this option enables Roundup to serve uploaded HTML
197    # file content *as HTML*. This is a potential security risk
198    # and is therefore disabled by default. Set to 'yes' if you
199    # trust *all* users uploading content to your tracker.
200    # Allowed values: yes, no
201    # Default: no
202    allow_html_file = no
206 Migrating from 1.4.2 to 1.4.3
207 =============================
209 If you are using the MySQL backend you will need to replace some indexes
210 that may have been created by version 1.4.2.
212 You should to access your MySQL database directly and remove any indexes
213 with a name ending in "_key_retired_idx". You should then re-add them with
214 the same spec except the key column name needs a size. So an index on
215 "_user (__retired, _name)" should become "_user (__retired, _name(255))".
218 Migrating from 1.4.x to 1.4.2
219 =============================
221 You should run the "roundup-admin migrate" command for your tracker once
222 you've installed the latest codebase. 
224 Do this before you use the web, command-line or mail interface and before
225 any users access the tracker.
227 This command will respond with either "Tracker updated" (if you've not
228 previously run it on an RDBMS backend) or "No migration action required"
229 (if you have run it, or have used another interface to the tracker,
230 or are using anydbm).
232 It's safe to run this even if it's not required, so just get into the
233 habit.
236 Migrating from 1.3.3 to 1.4.0
237 =============================
239 Value of the "refwd_re" tracker configuration option (section "mailgw")
240 is treated as UTF-8 string.  In previous versions, it was ISO8859-1.
242 If you have running trackers based on the classic template, please
243 update the messagesummary detector as follows::
245     --- detectors/messagesummary.py 17 Apr 2003 03:26:38 -0000      1.1
246     +++ detectors/messagesummary.py 3 Apr 2007 06:47:21 -0000       1.2
247     @@ -8,7 +8,7 @@
248      if newvalues.has_key('summary') or not newvalues.has_key('content'):
249          return
251     -    summary, content = parseContent(newvalues['content'], 1, 1)
252     +    summary, content = parseContent(newvalues['content'], config=db.config)
253      newvalues['summary'] = summary
255 In the latest version we have added some database indexes to the
256 SQL-backends (mysql, postgresql, sqlite) for speeding up building the
257 roundup-index for full-text search. We recommend that you create the
258 following database indexes on the database by hand::
260  CREATE INDEX words_by_id ON __words (_textid)
261  CREATE UNIQUE INDEX __textids_by_props ON __textids (_class, _itemid, _prop)
263 Migrating from 1.2.x to 1.3.0
264 =============================
266 1.3.0 Web interface changes
267 ---------------------------
269 Some of the HTML files in the "classic" and "minimal" tracker templates
270 were changed to fix some bugs and clean them up. You may wish to compare
271 them to the HTML files in your tracker and apply any changes.
274 Migrating from 1.1.2 to 1.2.0
275 =============================
277 1.2.0 Sorting and grouping by multiple properties
278 -------------------------------------------------
280 Starting with this version, sorting and grouping by multiple properties
281 is possible. This means that request.sort and request.group are now
282 lists. This is reflected in several places:
284  * ``renderWith`` now has list attributes for ``sort`` and ``group``,
285    where you previously wrote::
286    
287     renderWith(... sort=('-', 'activity'), group=('+', 'priority')
289    you write now::
291     renderWith(... sort=[('-', 'activity')], group=[('+', 'priority')]
293  * In templates that permit to edit sorting/grouping, request.sort and
294    request.group are (possibly empty) lists. You can now sort and group
295    by multiple attributes. For an example, see the classic template. You
296    may want search for the variable ``n_sort`` which can be set to the
297    number of sort/group properties.
299  * Templates that diplay new headlines for each group of items with
300    equal group properties can now use the modified ``batch.propchanged``
301    method that can take several properties which are checked for
302    changes. See the example in the classic template which makes use of
303    ``batch.propchanged``.
305 Migrating from 1.1.0 to 1.1.1
306 =============================
308 1.1.1 "Clear this message"
309 --------------------------
311 In 1.1.1, the standard ``page.html`` template includes a "clear this message"
312 link in the green "ok" message bar that appears after a successful edit
313 (or other) action.
315 To include this in your tracker, change the following in your ``page.html``
316 template::
318  <p tal:condition="options/ok_message | nothing" class="ok-message"
319     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
321 to be::
323  <p tal:condition="options/ok_message | nothing" class="ok-message">
324    <span tal:repeat="m options/ok_message"
325       tal:content="structure string:$m <br/ > " />
326     <a class="form-small" tal:attributes="href request/current_url"
327        i18n:translate="">clear this message</a>
328  </p>
331 If you implemented the "clear this message" in your 1.1.0 tracker, then you
332 should change it to the above and it will work much better!
335 Migrating from 1.0.x to 1.1.0
336 =============================
338 1.1 Login "For Session Only"
339 ----------------------------
341 In 1.1, web logins are alive for the length of a session only, *unless* you
342 add the following to the login form in your tracker's ``page.html``::
344     <input type="checkbox" name="remember" id="remember">
345     <label for="remember" i18n:translate="">Remember me?</label><br>
347 See the classic tracker ``page.html`` if you're unsure where this should
348 go.
351 1.1 Query Display Name
352 ----------------------
354 The ``dispname`` web variable has been renamed ``@dispname`` to avoid
355 clashing with other variables of the same name. If you are using the
356 display name feature, you will need to edit your tracker's ``page.html``
357 and ``issue.index.html`` pages to change ``dispname`` to ``@dispname``.
359 A side-effect of this change is that the renderWith method used in the
360 ``home.html`` page may now take a dispname argument.
363 1.1 "Clear this message"
364 ------------------------
366 In 1.1, the standard ``page.html`` template includes a "clear this message"
367 link in the green "ok" message bar that appears after a successful edit
368 (or other) action.
370 To include this in your tracker, change the following in your ``page.html``
371 template::
373  <p tal:condition="options/ok_message | nothing" class="ok-message"
374     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
376 to be::
378  <p tal:condition="options/ok_message | nothing" class="ok-message">
379    <span tal:repeat="m options/ok_message"
380       tal:content="structure string:$m <br/ > " />
381     <a class="form-small" tal:attributes="href string:issue${context/id}"
382        i18n:translate="">clear this message</a>
383  </p>
386 Migrating from 0.8.x to 1.0
387 ===========================
389 1.0 New Query Permissions
390 -------------------------
392 New permissions are defined for query editing and viewing. To include these
393 in your tracker, you need to add these lines to your tracker's
394 ``schema.py``::
396  # Users should be able to edit and view their own queries. They should also
397  # be able to view any marked as not private. They should not be able to
398  # edit others' queries, even if they're not private
399  def view_query(db, userid, itemid):
400      private_for = db.query.get(itemid, 'private_for')
401      if not private_for: return True
402      return userid == private_for
403  def edit_query(db, userid, itemid):
404      return userid == db.query.get(itemid, 'creator')
405  p = db.security.addPermission(name='View', klass='query', check=view_query,
406      description="User is allowed to view their own and public queries")
407  db.security.addPermissionToRole('User', p)
408  p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
409      description="User is allowed to edit their queries")
410  db.security.addPermissionToRole('User', p)
411  p = db.security.addPermission(name='Create', klass='query',
412      description="User is allowed to create queries")
413  db.security.addPermissionToRole('User', p)
415 and then remove 'query' from the line::
417  # Assign the access and edit Permissions for issue, file and message
418  # to regular users now
419  for cl in 'issue', 'file', 'msg', 'query', 'keyword':
421 so it looks like::
423  for cl in 'issue', 'file', 'msg', 'keyword':
426 Migrating from 0.8.0 to 0.8.3
427 =============================
429 0.8.3 Nosy Handling Changes
430 ---------------------------
432 A change was made to fix a bug in the ``nosyreaction.py`` standard
433 detector. To incorporate this fix in your trackers, you will need to copy
434 the ``nosyreaction.py`` file from the ``templates/classic/detectors``
435 directory of the source to your tracker's ``templates`` directory.
437 If you have modified the ``nosyreaction.py`` file from the standard
438 version, you will need to roll your changes into the new file.
441 Migrating from 0.7.1 to 0.8.0
442 =============================
444 You *must* fully uninstall previous Roundup version before installing
445 Roundup 0.8.0.  If you don't do that, ``roundup-admin install``
446 command may fail to function properly.
448 0.8.0 Backend changes
449 ---------------------
451 Backends 'bsddb' and 'bsddb3' are removed.  If you are using one of these,
452 you *must* migrate to another backend before upgrading.
455 0.8.0 API changes
456 -----------------
458 Class.safeget() was removed from the API. Test your item ids before calling
459 Class.get() instead.
462 0.8.0 New tracker layout
463 ------------------------
465 The ``config.py`` file has been replaced by ``config.ini``. You may use the
466 roundup-admin command "genconfig" to generate a new config file::
468   roundup-admin genconfig <tracker home>/config.ini
470 and modify the values therein based on the contents of your old config.py.
471 In most cases, the names of the config variables are the same.
473 The ``select_db.py`` file has been replaced by a file in the ``db``
474 directory called ``backend_name``. As you might guess, this file contains
475 just the name of the backend. To figure what the contents of yours should
476 be, use the following table:
478   ================================ =========================
479   ``select_db.py`` contents        ``backend_name`` contents
480   ================================ =========================
481   from back_anydbm import ...      anydbm
482   from back_metakit import ...     metakit
483   from back_sqlite import ...      sqlite
484   from back_mysql import ...       mysql
485   from back_postgresql import ...  postgresql
486   ================================ =========================
488 The ``dbinit.py`` file has been split into two new files,
489 ``initial_data.py`` and ``schema.py``. The contents of this file are:
491 ``initial_data.py``
492   You don't need one of these as your tracker is already initialised.
494 ``schema.py``
495   Copy the body of the ``def open(name=None)`` function from your old
496   tracker's ``dbinit.py`` file to this file. As the lines you're copying
497   aren't part of a function definition anymore, one level of indentation
498   needs to be removed (remove only the leading four spaces on each
499   line). 
501   The first few lines -- those starting with ``from roundup.hyperdb
502   import ...`` and the ``db = Database(config, name)`` line -- don't
503   need to be copied. Neither do the last few lines -- those starting
504   with ``import detectors``, down to ``return db`` inclusive.
506 You may remove the ``__init__.py`` module from the "detectors" directory as
507 it is no longer used.
509 There's a new way to write extension code for Roundup. If you have code in
510 an ``interfaces.py`` file you should move it. See the `customisation
511 documentation`_ for information about how extensions are now written.
512 Note that some older trackers may use ``interfaces.py`` to customise the
513 mail gateway behaviour. You will need to keep your ``interfaces.py`` file
514 if this is the case.
517 0.8.0 Permissions Changes
518 -------------------------
520 The creation of a new item in the user interfaces is now controlled by the
521 "Create" Permission. You will need to add an assignment of this Permission
522 to your users who are allowed to create items. The most common form of this
523 is the following in your ``schema.py`` added just under the current
524 assignation of the Edit Permission::
526     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
527         p = db.security.getPermission('Create', cl)
528         db.security.addPermissionToRole('User', p)
530 You will need to explicitly let anonymous users access the web interface so
531 that regular users are able to see the login form. Note that almost all
532 trackers will need this Permission. The only situation where it's not
533 required is in a tracker that uses an HTTP Basic Authenticated front-end.
534 It's enabled by adding to your ``schema.py``::
536     p = db.security.getPermission('Web Access')
537     db.security.addPermissionToRole('Anonymous', p)
539 Finally, you will need to enable permission for your users to edit their
540 own details by adding the following to ``schema.py``::
542     # Users should be able to edit their own details. Note that this
543     # permission is limited to only the situation where the Viewed or
544     # Edited item is their own.
545     def own_record(db, userid, itemid):
546         '''Determine whether the userid matches the item being accessed.'''
547         return userid == itemid
548     p = db.security.addPermission(name='View', klass='user', check=own_record,
549         description="User is allowed to view their own user details")
550     p = db.security.addPermission(name='Edit', klass='user', check=own_record,
551         description="User is allowed to edit their own user details")
552     db.security.addPermissionToRole('User', p)
555 0.8.0 Use of TemplatingUtils
556 ----------------------------
558 If you used custom python functions in TemplatingUtils, they must
559 be moved from interfaces.py to a new file in the ``extensions`` directory. 
561 Each Function that should be available through TAL needs to be defined
562 as a toplevel function in the newly created file. Furthermore you
563 add an inititialization function, that registers the functions with the 
564 tracker.
566 If you find this too tedious, donfu wrote an automatic init function that
567 takes an existing TemplatingUtils class, and registers all class methods
568 that do not start with an underscore. The following hack should be placed
569 in the ``extensions`` directory alongside other extensions::
571     class TemplatingUtils:
572          # copy from interfaces.py
574     def init(tracker):
575          util = TemplatingUtils()
577          def setClient(tu):
578              util.client = tu.client
579              return util
581          def execUtil(name):
582              return lambda tu, *args, **kwargs: \
583                      getattr(setClient(tu), name)(*args, **kwargs)
585          for name in dir(util):
586              if callable(getattr(util, name)) and not name.startswith('_'):
587                   tracker.registerUtil(name, execUtil(name))
590 0.8.0 Logging Configuration
591 ---------------------------
593 See the `administration guide`_ for information about configuring the new
594 logging implemented in 0.8.0.
597 Migrating from 0.7.2 to 0.7.3
598 =============================
600 0.7.3 Configuration
601 -------------------
603 If you choose, you may specify the directory from which static files are
604 served (those which use the URL component ``@@file``). Currently the
605 directory defaults to the ``TEMPLATES`` configuration variable. You may
606 define a new variable, ``STATIC_FILES`` which overrides this value for
607 static files.
610 Migrating from 0.7.0 to 0.7.2
611 =============================
613 0.7.2 DEFAULT_TIMEZONE is now required
614 --------------------------------------
616 The DEFAULT_TIMEZONE configuration variable is now required. Add the
617 following to your tracker's ``config.py`` file::
619     # You may specify a different default timezone, for use when users do not
620     # choose their own in their settings.
621     DEFAULT_TIMEZONE = 0            # specify as numeric hour offest
624 Migrating from 0.7.0 to 0.7.1
625 =============================
627 0.7.1 Permission assignments
628 ----------------------------
630 If you allow anonymous access to your tracker, you might need to assign
631 some additional View (or Edit if your tracker is that open) permissions
632 to the "anonymous" user. To do so, find the code in your ``dbinit.py`` that
633 says::
635     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
636         p = db.security.getPermission('View', cl)
637         db.security.addPermissionToRole('User', p)
638         p = db.security.getPermission('Edit', cl)
639         db.security.addPermissionToRole('User', p)
640     for cl in 'priority', 'status':
641         p = db.security.getPermission('View', cl)
642         db.security.addPermissionToRole('User', p)
644 Add add a line::
646         db.security.addPermissionToRole('Anonymous', p)
648 next to the existing ``'User'`` lines for the Permissions you wish to
649 assign to the anonymous user.
652 Migrating from 0.6 to 0.7
653 =========================
655 0.7.0 Permission assignments
656 ----------------------------
658 Due to a change in the rendering of web widgets, permissions are now
659 checked on Classes where they previously weren't (this is a good thing).
661 You will need to add some additional Permission assignments for your
662 regular users, or some displays will break. After the following in your 
663 tracker's ``dbinit.py``::
665     # Assign the access and edit Permissions for issue, file and message
666     # to regular users now
667     for cl in 'issue', 'file', 'msg', 'query', 'keyword':
668         p = db.security.getPermission('View', cl)
669         db.security.addPermissionToRole('User', p)
670         p = db.security.getPermission('Edit', cl)
671         db.security.addPermissionToRole('User', p)
673 add::
675     for cl in 'priority', 'status':
676         p = db.security.getPermission('View', cl)
677         db.security.addPermissionToRole('User', p)
680 0.7.0 Getting the current user id
681 ---------------------------------
683 The Database.curuserid attribute has been removed.
685 Any code referencing this attribute should be replaced with a
686 call to Database.getuid().
689 0.7.0 ZRoundup changes
690 ----------------------
692 The templates in your tracker's html directory will need updating if you
693 wish to use ZRoundup. If you've not modified those files (or some of them),
694 you may just copy the new versions from the Roundup source in the
695 templates/classic/html directory.
697 If you have modified the html files, then you'll need to manually edit them
698 to change all occurances of special form variables from using the colon ":"
699 special character to the at "@" special character. That is, variables such
700 as::
702   :action :required :template :remove:messages ...
704 should become::
706   @action @required @template @remove@messages ...
708 Note that ``tal:`` statements are unaffected. So are TAL expression type
709 prefixes such as ``python:`` and ``string:``. Please ask on the
710 roundup-users mailing list for help if you're unsure.
713 0.7.0 Edit collision detection
714 ------------------------------
716 Roundup now detects collisions with editing in the web interface (that is,
717 two people editing the same item at the same time).
719 You must copy the ``_generic.collision.html`` file from Roundup source in
720 the ``templates/classic/html`` directory. to your tracker's ``html``
721 directory.
724 Migrating from 0.6.x to 0.6.3
725 =============================
727 0.6.3 Configuration
728 -------------------
730 You will need to copy the file::
732   templates/classic/detectors/__init__.py
734 to your tracker's ``detectors`` directory, replacing the one already there.
735 This fixes a couple of bugs in that file.
739 Migrating from 0.5 to 0.6
740 =========================
743 0.6.0 Configuration
744 -------------------
746 Introduced EMAIL_FROM_TAG config variable. This value is inserted into
747 the From: line of nosy email. If the sending user is "Foo Bar", the
748 From: line is usually::
750      "Foo Bar" <issue_tracker@tracker.example>
752 the EMAIL_FROM_TAG goes inside the "Foo Bar" quotes like so::
754      "Foo Bar EMAIL_FROM_TAG" <issue_tracker@tracker.example>
756 I've altered the mechanism in the detectors __init__.py module so that it
757 doesn't cross-import detectors from other trackers (if you run more than one
758 in a single roundup-server). This change means that you'll need to copy the
759 __init__.py from roundup/templates/classic/detectors/__init__.py to your
760 <tracker home>/detectors/__init__.py. Don't worry, the "classic" __init__ is a
761 one-size-fits-all, so it'll work even if you've added/removed detectors.
763 0.6.0 Templating changes
764 ------------------------
766 The ``user.item`` template (in the tracker home "templates" directory)
767 needs to have the following hidden variable added to its form (between the
768 ``<form...>`` and ``</form>`` tags::
770   <input type="hidden" name=":template" value="item">
773 0.6.0 Form handling changes
774 ---------------------------
776 Roundup's form handling capabilities have been significantly expanded. This
777 should not affect users of 0.5 installations - but if you find you're
778 getting errors from form submissions, please ask for help on the Roundup
779 users mailing list:
781   http://lists.sourceforge.net/lists/listinfo/roundup-users
783 See the customisation doc section on `Form Values`__ for documentation of the
784 new form variables possible.
786 __ customizing.html#form-values
789 0.6.0 Multilingual character set support
790 ----------------------------------------
792 Added internationalization support. This is done via encoding all data
793 stored in roundup database to utf-8 (unicode encoding). To support utf-8 in
794 web interface you should add the folowing line to your tracker's html/page
795 and html/_generic.help files inside <head> tag::
796   
797     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
799 Since latin characters in utf-8 have the same codes as in ASCII table, this
800 modification is optional for users who use only plain latin characters. 
802 After this modification, you will be able to see and enter any world
803 character via web interface. Data received via mail interface also converted
804 to utf-8, however only new messages will be converted. If your roundup
805 database contains some of non-ASCII characters in one of 8-bit encoding,
806 they will not be visible in new unicode environment. Some of such data (e.g.
807 user names, keywords, etc)  can be edited by administrator, the others
808 (e.g. messages' contents) is not editable via web interface. Currently there
809 is no tool for converting such data, the only solution is to close
810 appropriate old issues and create new ones with the same content.
813 0.6.0 User timezone support
814 ---------------------------
816 From version 0.6.0 roundup supports displaying of Date data in user' local
817 timezone if he/she has provided timezone information. To make it possible
818 some modification to tracker's schema and HTML templates are required.
819 First you must add string property 'timezone' to user class in dbinit.py
820 like this::
821   
822     user = Class(db, "user", 
823                     username=String(),   password=Password(),
824                     address=String(),    realname=String(), 
825                     phone=String(),      organisation=String(),
826                     alternate_addresses=String(),
827                     queries=Multilink('query'), roles=String(),
828                     timezone=String())
829   
830 And second - html interface. Add following lines to
831 $TRACKER_HOME/html/user.item template::
832   
833      <tr>
834       <th>Timezone</th>
835       <td tal:content="structure context/timezone/field">timezone</td>
836      </tr>
838 After that all users should be able to provide their timezone information.
839 Timezone should be a positive or negative integer - offset from GMT.
841 After providing timezone, roundup will show all dates values, found in web
842 and mail interfaces in local time. It will also accept any Date info in
843 local time, convert and store it in GMT.
846 0.6.0 Search page structure
847 ---------------------------
849 In order to accomodate query editing the search page has been restructured. If
850 you want to provide your users with query editing, you should update your
851 search page using the macros detailed in the customisation doc section
852 `Searching on categories`__.
854 __ customizing.html#searching-on-categories
856 Also, the url field in the query class no longer starts with a '?'. You'll need
857 to remove this question mark from the url field to support queries. There's
858 a script in the "tools" directory called ``migrate-queries.py`` that should
859 automatically change any existing queries for you. As always, make a backup
860 of your database before running such a script.
863 0.6.0 Notes for metakit backend users
864 -------------------------------------
866 Roundup 0.6.0 introduced searching on ranges of dates and intervals. To
867 support it, some modifications to interval storing routine were made. So if
868 your tracker uses metakit backend and your db schema contains intervals
869 property, searches on that property will not be accurate for db items that
870 was stored before roundup' upgrade. However all new records should be
871 searchable on intervals.
873 It is possible to convert your database to new format: you can export and
874 import back all your data (consult "Migrating backends" in "Maintenance"
875 documentation). After this operation all your interval properties should
876 become searchable.
878 Users of backends others than metakit should not worry about this issue.
881 Migrating from 0.4.x to 0.5.0
882 =============================
884 This has been a fairly major revision of Roundup:
886 1. Brand new, much more powerful, flexible, tasty and nutritious templating.
887    Unfortunately, this means all your current templates are useless. Hopefully
888    the new documentation and examples will be enough to help you make the
889    transition. Please don't hesitate to ask on roundup-users for help (or
890    complete conversions if you're completely stuck)!
891 2. The database backed got a lot more flexible, allowing Metakit and SQL
892    databases! The only decent SQL database implemented at present is sqlite,
893    but others shouldn't be a whole lot more work.
894 3. A brand new, highly flexible and much more robust security system including
895    a system of Permissions, Roles and Role assignments to users. You may now
896    define your own Permissions that may be checked in CGI transactions.
897 4. Journalling has been made less storage-hungry, so has been turned on
898    by default *except* for author, recipient and nosy link/unlink events. You
899    are advised to turn it off in your trackers too.
900 5. We've changed the terminology from "instance" to "tracker", to ease the
901    learning curve/impact for new users.
902 6. Because of the above changes, the tracker configuration has seen some
903    major changes. See below for the details.
905 Please, **back up your database** before you start the migration process. This
906 is as simple as copying the "db" directory and all its contents from your
907 tracker to somewhere safe.
910 0.5.0 Configuration
911 -------------------
913 First up, rename your ``instance_config.py`` file to just ``config.py``.
915 Then edit your tracker's ``__init__.py`` module. It'll currently look
916 like this::
918  from instance_config import *
919  try:
920      from dbinit import *
921  except ImportError:
922      pass # in installdir (probably :)
923  from interfaces import *
925 and it needs to be::
927  import config
928  from dbinit import open, init
929  from interfaces import Client, MailGW
931 Due to the new templating having a top-level ``page`` that defines links for
932 searching, indexes, adding items etc, the following variables are no longer
933 used:
935 - HEADER_INDEX_LINKS
936 - HEADER_ADD_LINKS
937 - HEADER_SEARCH_LINKS
938 - SEARCH_FILTERS
939 - DEFAULT_INDEX
940 - UNASSIGNED_INDEX
941 - USER_INDEX
942 - ISSUE_FILTER
944 The new security implementation will require additions to the dbinit module,
945 but also removes the need for the following tracker config variables:
947 - ANONYMOUS_ACCESS
948 - ANONYMOUS_REGISTER
950 but requires two new variables which define the Roles assigned to users who
951 register through the web and e-mail interfaces:
953 - NEW_WEB_USER_ROLES
954 - NEW_EMAIL_USER_ROLES
956 in both cases, 'User' is a good initial setting. To emulate
957 ``ANONYMOUS_ACCESS='deny'``, remove all "View" Permissions from the
958 "Anonymous" Role. To emulate ``ANONYMOUS_REGISTER='deny'``, remove the "Web
959 Registration" and/or the "Email Registration" Permission from the "Anonymous"
960 Role. See the section on customising security in the `customisation
961 documentation`_ for more information.
963 Finally, the following config variables have been renamed to make more sense:
965 - INSTANCE_HOME -> TRACKER_HOME
966 - INSTANCE_NAME -> TRACKER_NAME
967 - ISSUE_TRACKER_WEB -> TRACKER_WEB
968 - ISSUE_TRACKER_EMAIL -> TRACKER_EMAIL
971 0.5.0 Schema Specification
972 --------------------------
974 0.5.0 Database backend changes
975 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
977 Your select_db module in your tracker has changed a fair bit. Where it used
978 to contain::
980  # WARNING: DO NOT EDIT THIS FILE!!!
981  from roundup.backends.back_anydbm import Database
983 it must now contain::
985  # WARNING: DO NOT EDIT THIS FILE!!!
986  from roundup.backends.back_anydbm import Database, Class, FileClass, IssueClass
988 Yes, I realise the irony of the "DO NOT EDIT THIS FILE" statement :)
989 Note the addition of the Class, FileClass, IssueClass imports. These are very
990 important, as they're going to make the next change work too. You now need to
991 modify the top of the dbinit module in your tracker from::
993  import instance_config
994  from roundup import roundupdb
995  from select_db import Database
997  from roundup.roundupdb import Class, FileClass
999  class Database(roundupdb.Database, select_db.Database):
1000      ''' Creates a hybrid database from:
1001           . the selected database back-end from select_db
1002           . the roundup extensions from roundupdb
1003      '''
1004      pass
1006  class IssueClass(roundupdb.IssueClass):
1007      ''' issues need the email information
1008      '''
1009      pass
1011 to::
1013  import config
1014  from select_db import Database, Class, FileClass, IssueClass
1016 Yes, remove the Database and IssueClass definitions and those other imports.
1017 They're not needed any more!
1019 Look for places in dbinit.py where ``instance_config`` is used too, and
1020 rename them ``config``.
1023 0.5.0 Journalling changes
1024 ~~~~~~~~~~~~~~~~~~~~~~~~~
1026 Journalling has been optimised for storage. Journalling of links has been
1027 turned back on by default. If your tracker has a large user base, you may wish
1028 to turn off journalling of nosy list, message author and message recipient
1029 link and unlink events. You do this by adding ``do_journal='no'`` to the Class
1030 initialisation in your dbinit. For example, your *msg* class initialisation
1031 probably looks like this::
1033     msg = FileClass(db, "msg",
1034                     author=Link("user"), recipients=Multilink("user"),
1035                     date=Date(),         summary=String(),
1036                     files=Multilink("file"),
1037                     messageid=String(),  inreplyto=String())
1039 to turn off journalling of author and recipient link events, add
1040 ``do_journal='no'`` to the ``author=Link("user")`` part of the statement,
1041 like so::
1043     msg = FileClass(db, "msg",
1044                     author=Link("user", do_journal='no'),
1045                     recipients=Multilink("user", do_journal='no'),
1046                     date=Date(),         summary=String(),
1047                     files=Multilink("file"),
1048                     messageid=String(),  inreplyto=String())
1050 Nosy list link event journalling is actually turned off by default now. If you
1051 want to turn it on, change to your issue class' nosy list, change its
1052 definition from::
1054     issue = IssueClass(db, "issue",
1055                     assignedto=Link("user"), topic=Multilink("keyword"),
1056                     priority=Link("priority"), status=Link("status"))
1058 to::
1060     issue = IssueClass(db, "issue", nosy=Multilink("user", do_journal='yes'),
1061                     assignedto=Link("user"), topic=Multilink("keyword"),
1062                     priority=Link("priority"), status=Link("status"))
1064 noting that your definition of the nosy Multilink will override the normal one.
1067 0.5.0 User schema changes
1068 ~~~~~~~~~~~~~~~~~~~~~~~~~
1070 Users have two more properties, "queries" and "roles". You'll have something
1071 like this in your dbinit module now::
1073     user = Class(db, "user",
1074                     username=String(),   password=Password(),
1075                     address=String(),    realname=String(),
1076                     phone=String(),      organisation=String(),
1077                     alternate_addresses=String())
1078     user.setkey("username")
1080 and you'll need to add the new properties and the new "query" class to it
1081 like so::
1083     query = Class(db, "query",
1084                     klass=String(),     name=String(),
1085                     url=String())
1086     query.setkey("name")
1088     # Note: roles is a comma-separated string of Role names
1089     user = Class(db, "user",
1090                     username=String(),   password=Password(),
1091                     address=String(),    realname=String(),
1092                     phone=String(),      organisation=String(),
1093                     alternate_addresses=String(),
1094                     queries=Multilink('query'), roles=String())
1095     user.setkey("username")
1097 The "queries" property is used to store off the user's favourite database
1098 queries. The "roles" property is explained below in `0.5.0 Security
1099 Settings`_.
1102 0.5.0 Security Settings
1103 ~~~~~~~~~~~~~~~~~~~~~~~
1105 See the `security documentation`_ for an explanation of how the new security
1106 system works. In a nutshell though, the security is handled as a four step
1107 process:
1109 1. Permissions are defined as having a name and optionally a hyperdb class
1110    they're specific to,
1111 2. Roles are defined that have one or more Permissions,
1112 3. Users are assigned Roles in their "roles" property, and finally
1113 4. Roundup checks that users have appropriate Permissions at appropriate times
1114    (like editing issues).
1116 Your tracker dbinit module's *open* function now has to define any
1117 Permissions that are specific to your tracker, and also the assignment
1118 of Permissions to Roles. At the moment, your open function
1119 ends with::
1121     import detectors
1122     detectors.init(db)
1124     return db
1126 and what we need to do is insert some commands that will set up the security
1127 parameters. Right above the ``import detectors`` line, you'll want to insert
1128 these lines::
1130     #
1131     # SECURITY SETTINGS
1132     #
1133     # new permissions for this schema
1134     for cl in 'issue', 'file', 'msg', 'user':
1135         db.security.addPermission(name="Edit", klass=cl,
1136             description="User is allowed to edit "+cl)
1137         db.security.addPermission(name="View", klass=cl,
1138             description="User is allowed to access "+cl)
1140     # Assign the access and edit permissions for issue, file and message
1141     # to regular users now
1142     for cl in 'issue', 'file', 'msg':
1143         p = db.security.getPermission('View', cl)
1144         db.security.addPermissionToRole('User', p)
1145         p = db.security.getPermission('Edit', cl)
1146         db.security.addPermissionToRole('User', p)
1147     # and give the regular users access to the web and email interface
1148     p = db.security.getPermission('Web Access')
1149     db.security.addPermissionToRole('User', p)
1150     p = db.security.getPermission('Email Access')
1151     db.security.addPermissionToRole('User', p)
1153     # May users view other user information? Comment these lines out
1154     # if you don't want them to
1155     p = db.security.getPermission('View', 'user')
1156     db.security.addPermissionToRole('User', p)
1158     # Assign the appropriate permissions to the anonymous user's Anonymous
1159     # Role. Choices here are:
1160     # - Allow anonymous users to register through the web
1161     p = db.security.getPermission('Web Registration')
1162     db.security.addPermissionToRole('Anonymous', p)
1163     # - Allow anonymous (new) users to register through the email gateway
1164     p = db.security.getPermission('Email Registration')
1165     db.security.addPermissionToRole('Anonymous', p)
1166     # - Allow anonymous users access to the "issue" class of data
1167     #   Note: this also grants access to related information like files,
1168     #         messages, statuses etc that are linked to issues
1169     #p = db.security.getPermission('View', 'issue')
1170     #db.security.addPermissionToRole('Anonymous', p)
1171     # - Allow anonymous users access to edit the "issue" class of data
1172     #   Note: this also grants access to create related information like
1173     #         files and messages etc that are linked to issues
1174     #p = db.security.getPermission('Edit', 'issue')
1175     #db.security.addPermissionToRole('Anonymous', p)
1177     # oh, g'wan, let anonymous access the web interface too
1178     p = db.security.getPermission('Web Access')
1179     db.security.addPermissionToRole('Anonymous', p)
1181 Note in the comments there the places where you might change the permissions
1182 to restrict users or grant users more access. If you've created additional
1183 classes that users should be able to edit and view, then you should add them
1184 to the "new permissions for this schema" section at the start of the security
1185 block. Then add them to the "Assign the access and edit permissions" section
1186 too, so people actually have the new Permission you've created.
1188 One final change is needed that finishes off the security system's
1189 initialisation. We need to add a call to ``db.post_init()`` at the end of the
1190 dbinit open() function. Add it like this::
1192     import detectors
1193     detectors.init(db)
1195     # schema is set up - run any post-initialisation
1196     db.post_init()
1197     return db
1199 You may verify the setup of Permissions and Roles using the new
1200 "``roundup-admin security``" command.
1203 0.5.0 User changes
1204 ~~~~~~~~~~~~~~~~~~
1206 To support all those schema changes, you'll need to massage your user database
1207 a little too, to:
1209 1. make sure there's an "anonymous" user - this user is mandatory now and is
1210    the one that unknown users are logged in as.
1211 2. make sure all users have at least one Role.
1213 If you don't have the "anonymous" user, create it now with the command::
1215   roundup-admin create user username=anonymous roles=Anonymous
1217 making sure the capitalisation is the same as above. Once you've done that,
1218 you'll need to set the roles property on all users to a reasonable default.
1219 The admin user should get "Admin", the anonymous user "Anonymous"
1220 and all other users "User". The ``fixroles.py`` script in the tools directory
1221 will do this. Run it like so (where python is your python 2+ binary)::
1223   python tools/fixroles.py -i <tracker home> fixroles
1227 0.5.0 CGI interface changes
1228 ---------------------------
1230 The CGI interface code was completely reorganised and largely rewritten. The
1231 end result is that this section of your tracker interfaces module will need
1232 changing from::
1234  from roundup import cgi_client, mailgw
1235  from roundup.i18n import _
1236  
1237  class Client(cgi_client.Client):
1238      ''' derives basic CGI implementation from the standard module,
1239          with any specific extensions
1240      '''
1241      pass
1243 to::
1245  from roundup import mailgw
1246  from roundup.cgi import client
1247  
1248  class Client(client.Client): 
1249      ''' derives basic CGI implementation from the standard module,
1250          with any specific extensions
1251      '''
1252      pass
1254 You will also need to install the new version of roundup.cgi from the source
1255 cgi-bin directory if you're using it.
1258 0.5.0 HTML templating
1259 ---------------------
1261 You'll want to make a backup of your current tracker html directory. You
1262 should then copy the html directory from the Roundup source "classic" template
1263 and modify it according to your local schema changes.
1265 If you need help with the new templating system, please ask questions on the
1266 roundup-users mailing list (available through the roundup project page on
1267 sourceforge, http://roundup.sf.net/)
1270 0.5.0 Detectors
1271 ---------------
1273 The nosy reactor has been updated to handle the tracker not having an
1274 "assignedto" property on issues. You may want to copy it into your tracker's
1275 detectors directory. Chances are you've already fixed it though :)
1278 Migrating from 0.4.1 to 0.4.2
1279 =============================
1281 0.4.2 Configuration
1282 -------------------
1283 The USER_INDEX definition introduced in 0.4.1 was too restrictive in its
1284 allowing replacement of 'assignedto' with the user's userid. Users must change
1285 the None value of 'assignedto' to 'CURRENT USER' (the string, in quotes) for
1286 the replacement behaviour to occur now.
1288 The new configuration variables are:
1290 - EMAIL_KEEP_QUOTED_TEXT 
1291 - EMAIL_LEAVE_BODY_UNCHANGED
1292 - ADD_RECIPIENTS_TO_NOSY
1294 See the sample configuration files in::
1296  <roundup source>/roundup/templates/classic/instance_config.py
1298 and::
1300  <roundup source>/roundup/templates/extended/instance_config.py
1302 and the `customisation documentation`_ for information on how they're used.
1305 0.4.2 Changes to detectors
1306 --------------------------
1307 You will need to copy the detectors from the distribution into your instance
1308 home "detectors" directory. If you used the classic schema, the detectors
1309 are in::
1311  <roundup source>/roundup/templates/classic/detectors/
1313 If you used the extended schema, the detectors are in::
1315  <roundup source>/roundup/templates/extended/detectors/
1317 The change means that schema-specific code has been removed from the
1318 mail gateway and cgi interface and made into auditors:
1320 - nosyreactor.py has now got an updatenosy auditor which updates the nosy
1321   list with author, recipient and assignedto information.
1322 - statusauditor.py makes the unread or resolved -> chatting changes and
1323   presets the status of an issue to unread.
1325 There's also a bug or two fixed in the nosyreactor code.
1327 0.4.2 HTML templating changes
1328 -----------------------------
1329 The link() htmltemplate function now has a "showid" option for links and
1330 multilinks. When true, it only displays the linked item id as the anchor
1331 text. The link value is displayed as a tooltip using the title anchor
1332 attribute. To use in eg. the superseder field, have something like this::
1334    <td>
1335     <display call="field('superseder', showid=1)">
1336     <display call="classhelp('issue', 'id,title', label='list', width=500)">
1337     <property name="superseder">
1338      <br>View: <display call="link('superseder', showid=1)">
1339     </property>
1340    </td>
1342 The stylesheets have been cleaned up too. You may want to use the newer
1343 versions in::
1345  <roundup source>/roundup/templates/<template>/html/default.css
1349 Migrating from 0.4.0 to 0.4.1
1350 =============================
1352 0.4.1 Files storage
1353 -------------------
1355 Messages and files from newly created issues will be put into subdierectories
1356 in thousands e.g. msg123 will be put into files/msg/0/msg123, file2003
1357 will go into files/file/2/file2003. Previous messages are still found, but
1358 could be put into this structure.
1360 0.4.1 Configuration
1361 -------------------
1363 To allow more fine-grained access control, the variable used to check
1364 permission to auto-register users in the mail gateway is now called
1365 ANONYMOUS_REGISTER_MAIL rather than overloading ANONYMOUS_REGISTER. If the
1366 variable doesn't exist, then ANONYMOUS_REGISTER is tested as before.
1368 Configuring the links in the web header is now easier too. The following
1369 variables have been added to the classic instance_config.py::
1371   HEADER_INDEX_LINKS   - defines the "index" links to be made available
1372   HEADER_ADD_LINKS     - defines the "add" links
1373   DEFAULT_INDEX        - specifies the index view for DEFAULT
1374   UNASSIGNED_INDEX     - specifies the index view for UNASSIGNED
1375   USER_INDEX           - specifies the index view for USER
1377 See the <roundup source>/roundup/templates/classic/instance_config.py for more
1378 information - including how the variables are to be set up. Most users will
1379 just be able to copy the variables from the source to their instance home. If
1380 you've modified the header by changing the source of the interfaces.py file in
1381 the instance home, you'll need to remove that customisation and move it into
1382 the appropriate variables in instance_config.py.
1384 The extended schema has similar variables added too - see the source for more
1385 info.
1387 0.4.1 Alternate E-Mail Addresses
1388 --------------------------------
1390 If you add the property "alternate_addresses" to your user class, your users
1391 will be able to register alternate email addresses that they may use to
1392 communicate with roundup as. All email from roundup will continue to be sent
1393 to their primary address.
1395 If you have not edited the dbinit.py file in your instance home directory,
1396 you may simply copy the new dbinit.py file from the core code. If you used
1397 the classic schema, the interfaces file is in::
1399  <roundup source>/roundup/templates/classic/dbinit.py
1401 If you used the extended schema, the file is in::
1403  <roundup source>/roundup/templates/extended/dbinit.py 
1405 If you have modified your dbinit.py file, you need to edit the dbinit.py
1406 file in your instance home directory. Find the lines which define the user
1407 class::
1409     user = Class(db, "msg",
1410                     username=String(),   password=Password(),
1411                     address=String(),    realname=String(), 
1412                     phone=String(),      organisation=String(),
1413                     alternate_addresses=String())
1415 You will also want to add the property to the user's details page. The
1416 template for this is the "user.item" file in your instance home "html"
1417 directory. Similar to above, you may copy the file from the roundup source if
1418 you haven't modified it. Otherwise, add the following to the template::
1420    <display call="multiline('alternate_addresses')">
1422 with appropriate labelling etc. See the standard template for an idea.
1426 Migrating from 0.3.x to 0.4.0
1427 =============================
1429 0.4.0 Message-ID and In-Reply-To addition
1430 -----------------------------------------
1431 0.4.0 adds the tracking of messages by message-id and allows threading
1432 using in-reply-to. Most e-mail clients support threading using this
1433 feature, and we hope to add support for it to the web gateway. If you
1434 have not edited the dbinit.py file in your instance home directory, you may
1435 simply copy the new dbinit.py file from the core code. If you used the
1436 classic schema, the interfaces file is in::
1438  <roundup source>/roundup/templates/classic/dbinit.py
1440 If you used the extended schema, the file is in::
1442  <roundup source>/roundup/templates/extended/dbinit.py 
1444 If you have modified your dbinit.py file, you need to edit the dbinit.py
1445 file in your instance home directory. Find the lines which define the msg
1446 class::
1448     msg = FileClass(db, "msg",
1449                     author=Link("user"), recipients=Multilink("user"),
1450                     date=Date(),         summary=String(),
1451                     files=Multilink("file"))
1453 and add the messageid and inreplyto properties like so::
1455     msg = FileClass(db, "msg",
1456                     author=Link("user"), recipients=Multilink("user"),
1457                     date=Date(),         summary=String(),
1458                     files=Multilink("file"),
1459                     messageid=String(),  inreplyto=String())
1461 Also, configuration is being cleaned up. This means that your dbinit.py will
1462 also need to be changed in the open function. If you haven't changed your
1463 dbinit.py, the above copy will be enough. If you have, you'll need to change
1464 the line (round line 50)::
1466     db = Database(instance_config.DATABASE, name)
1468 to::
1470     db = Database(instance_config, name)
1473 0.4.0 Configuration
1474 --------------------
1475 ``TRACKER_NAME`` and ``EMAIL_SIGNATURE_POSITION`` have been added to the
1476 instance_config.py. The simplest solution is to copy the default values
1477 from template in the core source.
1479 The mail gateway now checks ``ANONYMOUS_REGISTER`` to see if unknown users
1480 are to be automatically registered with the tracker. If it is set to "deny"
1481 then unknown users will not have access. If it is set to "allow" they will be
1482 automatically registered with the tracker.
1485 0.4.0 CGI script roundup.cgi
1486 ----------------------------
1487 The CGI script has been updated with some features and a bugfix, so you should
1488 copy it from the roundup cgi-bin source directory again. Make sure you update
1489 the ROUNDUP_INSTANCE_HOMES after the copy.
1492 0.4.0 Nosy reactor
1493 ------------------
1494 The nosy reactor has also changed - copy the nosyreactor.py file from the core
1495 source::
1497    <roundup source>/roundup/templates/<template>/detectors/nosyreactor.py
1499 to your instance home "detectors" directory.
1502 0.4.0 HTML templating
1503 ---------------------
1504 The field() function was incorrectly implemented - links and multilinks now
1505 display as text fields when rendered using field(). To display a menu (drop-
1506 down or select box) you need to use the menu() function.
1510 Migrating from 0.2.x to 0.3.x
1511 =============================
1513 0.3.x Cookie Authentication changes
1514 -----------------------------------
1515 0.3.0 introduces cookie authentication - you will need to copy the
1516 interfaces.py file from the roundup source to your instance home to enable
1517 authentication. If you used the classic schema, the interfaces file is in::
1519  <roundup source>/roundup/templates/classic/interfaces.py
1521 If you used the extended schema, the file is in::
1523  <roundup source>/roundup/templates/extended/interfaces.py
1525 If you have modified your interfaces.Client class, you will need to take
1526 note of the login/logout functionality provided in roundup.cgi_client.Client
1527 (classic schema) or roundup.cgi_client.ExtendedClient (extended schema) and
1528 modify your instance code apropriately.
1531 0.3.x Password encoding
1532 -----------------------
1533 This release also introduces encoding of passwords in the database. If you
1534 have not edited the dbinit.py file in your instance home directory, you may
1535 simply copy the new dbinit.py file from the core code. If you used the
1536 classic schema, the interfaces file is in::
1538  <roundup source>/roundup/templates/classic/dbinit.py
1540 If you used the extended schema, the file is in::
1542  <roundup source>/roundup/templates/extended/dbinit.py
1545 If you have modified your dbinit.py file, you may use encoded passwords:
1547 1. Edit the dbinit.py file in your instance home directory
1548    a. At the first code line of the open() function::
1550        from roundup.hyperdb import String, Date, Link, Multilink
1552       alter to include Password, as so::
1554        from roundup.hyperdb import String, Password, Date, Link, Multilink
1556    b. Where the password property is defined (around line 66)::
1558        user = Class(db, "user", 
1559                        username=String(),   password=String(),
1560                        address=String(),    realname=String(), 
1561                        phone=String(),      organisation=String())
1562        user.setkey("username")
1564       alter the "password=String()" to "password=Password()"::
1566        user = Class(db, "user", 
1567                        username=String(),   password=Password(),
1568                        address=String(),    realname=String(), 
1569                        phone=String(),      organisation=String())
1570        user.setkey("username")
1572 2. Any existing passwords in the database will remain cleartext until they
1573    are edited. It is recommended that at a minimum the admin password be
1574    changed immediately::
1576       roundup-admin -i <instance home> set user1 password=<new password>
1579 0.3.x Configuration
1580 -------------------
1581 FILTER_POSITION, ANONYMOUS_ACCESS, ANONYMOUS_REGISTER have been added to
1582 the instance_config.py. Simplest solution is to copy the default values from
1583 template in the core source.
1585 MESSAGES_TO_AUTHOR has been added to the IssueClass in dbinit.py. Set to 'yes'
1586 to send nosy messages to the author. Default behaviour is to not send nosy
1587 messages to the author. You will need to add MESSAGES_TO_AUTHOR to your
1588 dbinit.py in your instance home.
1591 0.3.x CGI script roundup.cgi
1592 ----------------------------
1593 There have been some structural changes to the roundup.cgi script - you will
1594 need to install it again from the cgi-bin directory of the source
1595 distribution. Make sure you update the ROUNDUP_INSTANCE_HOMES after the
1596 copy.
1599 .. _`customisation documentation`: customizing.html
1600 .. _`security documentation`: security.html
1601 .. _`administration guide`: admin_guide.html