comparison doc/upgrading.txt @ 8416:370689471a08 issue2550923_computed_property

merge from default branch accumulated changes since Nov 2023
author John Rouillard <rouilj@ieee.org>
date Sun, 17 Aug 2025 16:12:25 -0400
parents 0663a7bcef6c
children 94eed885e958
comparison
equal deleted inserted replaced
7693:78585199552a 8416:370689471a08
1 .. meta:: 1 .. meta::
2 :description: 2 :description:
3 Critical documentation for upgrading the Roundup Issue 3 Critical documentation for upgrading the Roundup Issue
4 Tracker. Actions that must be taken when upgrading from 4 Tracker. Actions that must be taken when upgrading from
5 one version to another are documented here. 5 one version to another are documented here.
6 6
7 .. index:: Upgrading 7 .. index:: Upgrading
8 8
9 ====================================== 9 ======================================
10 Upgrading to newer versions of Roundup 10 Upgrading to newer versions of Roundup
31 each version transition. If you are starting at 1.5.0 31 each version transition. If you are starting at 1.5.0
32 and installing to 2.3.0, you need to make the changes for **all** 32 and installing to 2.3.0, you need to make the changes for **all**
33 versions starting at 1.5 and ending at 2.3. E.G. 33 versions starting at 1.5 and ending at 2.3. E.G.
34 1.5.0 -> 1.5.1, 1.5.1 -> 1.6.0, ..., 2.1.0 -> 2.2.0, 34 1.5.0 -> 1.5.1, 1.5.1 -> 1.6.0, ..., 2.1.0 -> 2.2.0,
35 2.2.0 -> 2.3.0. 35 2.2.0 -> 2.3.0.
36 6. Run ``roundup-admin -i <tracker_home> migrate`` using the newer 36 6. Run ``roundup-admin -i <tracker_home> migrate`` using
37 version of Roundup for **all** the trackers you have 37 the newer version of Roundup for the instance you are
38 upgraded. This will update the database if it is required. 38 upgrading. This will update the database if it is
39 required.
39 7. Bring your Roundup instance back online 40 7. Bring your Roundup instance back online
40 8. Test 41 8. Test
42
43 Repeat for each tracker instance.
41 44
42 .. note:: 45 .. note::
43 The v1.5.x releases of Roundup were the last to support 46 The v1.5.x releases of Roundup were the last to support
44 Python v2.5 and v2.6. Starting with the v1.6 releases of Roundup 47 Python v2.5 and v2.6. Starting with the v1.6 releases of Roundup
45 Python version 2.7 that is newer than 2.7.2 is required to run 48 Python version 2.7 that is newer than 2.7.2 is required to run
46 Roundup. Starting with Roundup version 2.0.0 we also support Python 3 49 Roundup. Starting with Roundup version 2.0.0 we also support Python 3
47 versions newer than 3.6. 50 versions newer than 3.6. Roundup version 2.5 supports Python
51 3.7 and newer.
48 52
49 Recent release notes have the following labels: 53 Recent release notes have the following labels:
50 54
51 * required - Roundup will not work properly if these steps are not done 55 * **required** - Roundup will not work properly if these steps are not done
52 * recommended - Roundup will still work, but these steps can cause 56 * **recommended** - Roundup will still work, but these steps can cause
53 security or stability issues if not done. 57 security or stability issues if not done.
54 * optional - new features or changes to existing features you might 58 * **optional** - new features or changes to existing features you might
55 want to use 59 want to use
56 * info - important possibly visible changes in how things operate 60 * **info** - important possibly visible changes in how things operate
57 61
58 If you use virtual environments for your installation, you can run 62 If you use virtual environments for your installation, you
59 trackers with different versions of Roundup. So you can have one tracker 63 can run trackers with different versions of Roundup. So you
60 using version 2.2.0 and another tracker using version 1.6.1. This 64 can have one tracker using version 2.2.0 and another tracker
61 allows you to upgrade trackers one at a time rather than having to 65 using version 1.6.1. This allows you to upgrade trackers one
62 upgrade all your trackers at once. 66 at a time rather than having to upgrade all your trackers at
67 once. Note that downgrading may require restoring your
68 database to an earlier version, so make sure you backed up
69 your database.
63 70
64 .. note:: 71 .. note::
65 72
66 This file only includes versions released in the last 10 73 This file only includes versions released in the last 10
67 years. If you are upgrading from an older version, start with the 74 years. If you are upgrading from an older version, start with the
69 document. 76 document.
70 77
71 .. admonition:: Python 2 Support 78 .. admonition:: Python 2 Support
72 79
73 If you are running Roundup under Python 2, you should make plans to 80 If you are running Roundup under Python 2, you should make plans to
74 switch to Python 3. The continuous Integration (CI) and other services 81 switch to Python 3. Release 2.4.0 (Jul 2024) is the last release to
75 used for developing Roundup are dropping support for Python 2. Also 82 officially support Python 2. The next non-patch release scheduled
76 optional packages are dropping Python 2 support. As a result Python 2 83 for 2025 will mark 5 years since Roundup supported Python 3.
77 may not be supported for many more release cycles.
78 84
79 .. admonition:: XHTML Support Deprecation Notice 85 .. admonition:: XHTML Support Deprecation Notice
80 86
81 If you are running a tracker where the ``html_version`` setting in 87 If you are running a tracker where the ``html_version`` setting in
82 ``config.ini`` is ``xhtml``, you should plan to change your 88 ``config.ini`` is ``xhtml``, you should plan to change your
83 templates to use html (HTML5). If you are affected by this, please 89 templates to use html (HTML5). If you are affected by this, please
84 send email to the roundup-users mailing list (roundup-users at 90 send email to the roundup-users mailing list (roundup-users at
85 lists.sourceforge.net). Version 2.3.0 is expected to be the last 91 lists.sourceforge.net). Version 2.3.0 is the last version to support
86 version to support XHTML. 92 XHTML.
87 93
88 Contents: 94 .. raw:: html
95
96 <details>
97 <summary>Contents:</summary>
89 98
90 .. contents:: 99 .. contents::
91 :local: 100 :local:
92 101
93 .. index:: Upgrading; 2.2.0 to 2.3.0 102 .. raw:: html
103
104 </details>
105
106 .. index:: Upgrading; 2.5.0 to 2.6.0
107
108 Migrating from 2.5.0 to 2.6.0
109 =============================
110
111 Support authorized changes in your tracker (optional)
112 -----------------------------------------------------
113
114 An auditor can require change verification with user's password.
115
116 When changing sensitive information (e.g. passwords) it is
117 useful to ask for a validated authorization. This makes sure
118 that the user is present by typing their password.
119
120 You can add this to your auditors using the example
121 :ref:`sensitive_changes`.
122
123 To use this, you must copy ``_generic.reauth.html`` into your
124 tracker's html subdirectory. See the classic template directory for a
125 copy. If you are using jinja2, see the jinja2 template directory.
126 Then you can raise a Reauth exception and have the proper page
127 displayed.
128
129 Also javascript *MUST* be turned on if this is used with a file
130 input. If JavaScript is not turned on, attached files are lost during
131 the reauth step. Information from other types of inputs (password,
132 date, text etc.) do not need JavaScript to work.
133
134 See :ref:`Confirming the User` in the reference manual for details.
135
136 .. index:: Upgrading; 2.4.0 to 2.5.0
137
138 Migrating from 2.4.0 to 2.5.0
139 =============================
140
141 .. _CVE-2025-53865:
142
143 XSS security issue with devel and responsive templates (recommended)
144 --------------------------------------------------------------------
145
146 There are actually two different issues under this heading.
147
148 1. incorrect use of the ``structure`` keyword with
149 ``tal:content``
150 2. use of ``tal:replace`` on unsafe input
151
152 See the `security page for a link to CVE-2025-53865
153 <security.html#cve-announcements>`_.
154
155 In the discussion below, the :term:`html directory` means one or
156 more directories listed in the ``templates`` key of your
157 tracker's ``config.ini`` file.
158
159 These directions can be used to solve the XSS security issue with
160 any version of Roundup. Even if you used a classic or minimal
161 template, you should check your trackers for these issues. The
162 classic template fixed most of these many years ago, but the
163 updates were not made to the devel and responsive templates. No
164 report of similar issues with the jinja template has been seen.
165
166 Incorrect use of structure in templates
167 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
168
169 The devel and responsive templates prior to Roundup 2.5 used this
170 construct::
171
172 tal:content="structure context/MUMBLE/plain"
173
174 Where ``MUMBLE`` is a property of your issues (e.g. title).
175
176 This construct allows a URL with a carefully crafted query
177 parameter to execute arbitrary JavaScript.
178
179 You should check all your trackers. The classic template has not
180 used this construct since at least 2009, but your tracker's
181 templates may use the offending construct anyway.
182
183 This fix will apply if your tracker is based on the responsive or
184 devel template. Check the TEMPLATE-INFO.txt file in your tracker
185 home. The template name is the first component of the ``Name``
186 field. For example a Name like::
187
188 Name: responsive-bugtracker
189
190 Name: devel-bugtracker
191
192 shows that tracker is based on the responsive or devel templates.
193
194 .. _cve-2025-53865-fixed:
195
196 To fix this, remove the ``structure`` declaration when it is used
197 with a plain representation. So fixing the code by replacing the
198 example above with::
199
200 tal:content="context/MUMBLE/plain"
201
202 prevents the attack.
203
204 To check for this issue, search for ``structure`` followed by
205 ``/plain`` in all your html templates. If you are on a Linux/Unix
206 system you can search the html subdirectory of your tracker with
207 the following::
208
209 grep 'structure.*/plain' *.html
210
211 which should return any lines with issues.
212
213 .. warning::
214
215 Backup the files in the ``html`` subdirectory of your tracker
216 in case an edit goes wrong.
217
218 As an example, you could fix this issue using the GNU sed
219 command::
220
221 sed -i.bak -e '/structure.*\/plain/s/structure.//' *.html
222
223 to edit the files in place and remove the structure keyword. It
224 will create a ``.bak`` file with the original contents of the
225 file. If your templates were changed, this might still miss some
226 entries. If you are on windows, some text editors support search
227 and replace using a regular expression.
228
229 If the construct is split across lines::
230
231 tal:content="structure
232 context/MUMBLE/plain"
233
234 the commands above will miss the construct. So you should also
235 search the html files using ``grep /plain *.html`` and verify
236 that all of the ``context/MUMBLE/plain`` include ``tal:content``
237 as in the `fixed example above <#cve-2025-53865-fixed>`_. Any
238 lines that have ``context/MUMBLE/plain`` without ``tal:content=``
239 before it need to be manually verified/fixed.
240
241 The distributed devel and responsive templates do not split the
242 construct across lines, but if you changed the files it may be
243 split.
244
245 tal:replace used with unsafe input
246 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
247
248 The problem was caused by the following markup::
249
250 <span tal:replace="context/MUMBLE" />
251
252 in the head of the ``bug.item.html``, ``task.item.html`` and
253 other files in the devel and responsive templates.
254
255 This was fixed many years ago in the classic template's
256 ``index.item.html``. The classic template replaces the above
257 construct with::
258
259 <tal:x tal:content="context/MUMBLE" />
260
261 ``tal:content`` explicitly escapes the result unless the
262 ``structure`` directive is used. ``tal:replace`` expects the
263 result to be safe and usable in an HTML context.
264
265 TAL drops any tags that it doesn't know about from the output.
266 ``<tal:x tal:content="..." />`` results in the value of the
267 content expression without a surrounding html tag. (Effectively
268 replacing the construct.)
269
270 The following diff for ``bug.item.html`` in the devel template
271 shows the change to make things safe (remove lines starting with
272 ``-`` and add lines staring with ``+``)::
273
274 <tal:block metal:use-macro="templates/page/macros/frame">
275 <title metal:fill-slot="head_title">
276 <tal:block condition="context/id" i18n:translate=""
277 - >Bug <span tal:replace="context/id" i18n:name="id"
278 - />: <span tal:replace="context/title" i18n:name="title"
279 - /> - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
280 + >Bug <tal:x tal:content="context/id" i18n:name="id"
281 + />: <tal:x tal:content="context/title" i18n:name="title"
282 + /> - <tal:x tal:content="config/TRACKER_NAME" i18n:name="tracker"
283 /></tal:block>
284 <tal:block condition="not:context/id" i18n:translate=""
285 >New Bug report - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
286
287 A similar change was applied in the following html files in the
288 devel or responsive templates:
289
290 .. rst-class:: multicol
291
292 * _generic.collision.html
293 * bug.item.html
294 * keyword.item.html
295 * milestone.item.html
296 * msg.item.html
297 * task.item.html
298 * user.item.html
299
300 Also ``page.html`` should be changed from::
301
302 <p class="label"><b tal:replace="request/user/username">username</b></p>
303
304 to::
305
306 <p class="label"><b tal:replace="python:request.user.username.plain(escape=1)">username</b></p>
307
308 The code audit found the ``tal:replace`` construct is used with
309 ``context/id`` and ``context/designator`` paths. The references
310 to these paths have been changed to use ``tal:x`` in the classic
311 template's ``msg.item.html`` file and the classic and minimal
312 template's ``_generic.collision.html`` file.
313
314 These paths are critical to navigation in Roundup and are set
315 from the path part of the URL. Roundup's URL path validation
316 makes it unlikely that an attacker could exploit them. If you
317 wish you can change your templates or copy the corresponding
318 files from the template if you haven't made local changes.
319
320 Also you may have used copies of these insecure templates
321 elsewhere in your tracker (e.g. to create a feature class). To
322 find other possible issues you can use the command::
323
324 grep -r "tal:replace=" *.html
325
326 in your tracker's :term:`html directory`. Check each occurrence
327 and if needed, change it to the safer form. You should consider
328 any reference to ``context`` to be under the user's (attacker's)
329 control. Also ``db`` (excluding ``db/config``) and ``request``
330 references that use user supplied content
331 (e.g. ``request/user/username`` above) should be changed to
332 ``tal:x`` form
333
334 .. comment:
335 As part of the analysis, the following command was used to find
336 potentially vulnerable stuff in the templates. Each grep -v was
337 removed to display items in that category and they were checked::
338
339 grep -r 'tal:replace' . | grep -v 'replace="batch' | \
340 grep -v 'replace="config' | grep -v 'replace="db/config' | \
341 grep -v 'replace="structure' | grep -v 'replace="python:' | \
342 grep -v 'replace="request/'
343
344
345 context/id, context/designator:
346 assume safe if used in an class.item.html page as the page
347 wouldn't be shown if they weren't valid numbers/designators.
348
349 Might not be ok referenced in a _generic fallback page though.
350
351 config, db/config, batch, nothing:
352 should be safe as they are not under user control
353
354 request/classname (python:request._classname), request/template:
355 should be safe as they are needed to navigate to a display page,
356 so if they are invalid nothing will be displayed.
357
358 utils, python:
359 assume it's written correctly and is safe (could use some new
360 tests for the shipped utility functions). The intent of these
361 can be to deliver blocks of <script> or other html markup.
362
363 db, request:
364 might be dangerous when accessing user supplied values.
365
366 request/user/username:
367 Escape these. If the username is an XSS issue, an attacker could
368 use it to compromise a user.
369
370 request/dispname:
371 should be quoted and is by the existing python: code.
372
373 Open question: why does there have to be an error generated by the
374 url @sort=1. Without invalid sort param, the exploit url doesn't
375 work and the context appears to use the database's title not the one
376 in the url. Also its not positional @sort=1 can appear anywhere in
377 the url.
378
379 Deprecation Notices (required)
380 ------------------------------
381
382 * Support for SQLite version 2 has been removed in 2.5.0.
383 * Support for the `PySQLite <https://github.com/ghaering/pysqlite>`_
384 library has been removed in 2.5.0. Only the Python supplied
385 sqlite3 library is supported.
386 * Roundup 2.5.0 supports Python 3.7 or newer. (It is not tested
387 on Python 3.6. It may work but we don't support it.)
388
389 Update responsive template _generic.404.html and query.item.html (recommended)
390 ------------------------------------------------------------------------------
391
392 This only applies if your tracker is based on the responsive
393 template. Check the TEMPLATE-INFO.txt file in your tracker
394 home. The template name is the first component of the ``Name``
395 field. For example a Name like::
396
397 Name: responsive-bugtracker
398
399 is based on the responsive template. If the Name doesn't start with
400 ``responsive`` no changes are needed.
401
402 The ``_generic.404.html`` and ``query.item.html`` templates will crash
403 when displayed because a missing macro is called. Change::
404
405 <tal:block metal:use-macro="templates/page/macros/icing">
406
407 to::
408
409 <tal:block metal:use-macro="templates/page/macros/frame">
410
411 at the top of both files. The icing macro used in other tracker
412 templates was renamed to frame in this tracker template.
413
414 Update userauditor.py detector (recommended)
415 --------------------------------------------
416
417 When using the REST interface, setting the address property of the
418 user to the same value it currently has resulted in an error.
419
420 If you have not changed your userauditor, you can copy one from any of
421 the supplied templates in the ``detectors/userauditor.py`` file. Use
422 ``roundup-admin templates`` to find a list of template directories.
423
424 If you have changed your userauditor from the stock version, apply the
425 following diff::
426
427 raise ValueError('Email address syntax is invalid
428 "%s"'%address)
429
430 check_main = db.user.stringFind(address=address)
431 + # allow user to set same address via rest
432 + if check_main:
433 + check_main = nodeid not in check_main
434 +
435 # make sure none of the alts are owned by anyone other than us (x!=nodeid)
436
437 add the lines marked with ``+`` in the file in the location after
438 check_main is assigned.
439
440 Modify config.ini password_pbkdf2_default_rounds setting (recommended)
441 ----------------------------------------------------------------------
442
443 The method for hashing and storing passwords has been updated to use
444 PBKDF2 with SHA512 hash. This change was first introduced in Roundup
445 2.3 and is now the standard. If you previously added code in
446 interfaces.py for a `PBKDF2 upgrade`_ to enable PBKDF2S5, you can
447 remove that code now.
448
449 SHA512 is a more secure hash, it requires fewer rounds to ensure
450 safety. The older PBKDF2-SHA1 needed around 2 million rounds.
451
452 You should update the ``password_pbkdf2_default_rounds`` setting in
453 ``config.ini`` to 250000. This value is higher than the OWASP
454 recommendation of 210000 from three years ago. If you don’t make this
455 change, logins will be slow, especially for REST or XMLRPC calls.
456
457 See `PBKDF2 upgrade`_ for details on how to test the algorithm's
458 speed. We do not recommend reverting to the older SHA1 PBKDF2. If you
459 have to do so due to a slow CPU, you can add the following to your
460 tracker's ``interfaces.py``::
461
462 from roundup.password import Password
463 ## Use PBDKF2 (PBKDF2-SHA1) as default hash for passwords.
464 # That scheme is at the start of the deprecated_schemes list and ha
465 # to be removed.
466 Password.default_scheme = Password.deprecated_schemes.pop(0)
467 # Add PBKDF2S5 (PBKDF2-SHA512) as a valid scheme. Passwords
468 # using it will be rehashed to use PBDKF2.
469 Password.experimental_schemes.insert(0, "PBKDF2S5")
470
471 If you proceed with this, you should set
472 ``password_pbkdf2_default_rounds`` to 2 million or more rounds to keep
473 your hashed password database secure in case it gets stolen.
474
475 Defusedxml support improves XMLRPC security (optional)
476 ------------------------------------------------------
477
478 This release adds support for the defusedxml_ module. If it is
479 installed it will be automatically used. The default xmlrpc module in
480 the standard library has known issues when parsing crafted XML. It can
481 take a lot of CPU time and consume large amounts of memory with small
482 payloads.
483
484 When the XMLRPC endpoint is used without defusedxml, it will log a
485 warning to the log file. The log entry can be disabled by adding::
486
487
488 from roundup.cgi import client
489 client.WARN_FOR_MISSING_DEFUSEDXML = False
490
491 to the ``interfaces.py`` file in the tracker home. (Create the file if
492 it is missing.)
493
494 XMLRPC access is enabled by default in the classic and other trackers.
495 Upgrading to defusedxml is considered optional because the XMLRPC
496 endpoint can be disabled in the tracker's ``config.ini``. Also
497 ``Xmlrpc Access`` can be removed from the ``Users`` role by commenting
498 out a line in ``schema.py``.
499
500 If you have enabled the xmlrpc endpoint, you should install
501 defusedxml.
502
503 .. _defusedxml: https://pypi.org/project/defusedxml/
504
505 Enable use of native date inputs (optional)
506 -------------------------------------------
507
508 Roundup now can use native ``date`` or ``datetime-local`` inputs for
509 ``Date()`` properties. These inputs take the place of the text input and
510 calendar popup from earlier Roundup versions. Modern browsers come with
511 a built-in calendar for date selection, so the ``(cal)`` calendar link
512 is no longer needed. These native inputs show the date based on the
513 browser's locale and translate terms into the local language.
514
515 Note that the date format is tied to the language setting in most
516 browsers, with some browsers you need special configurations to make the
517 browser use the operating system date format.
518
519 By default the old input mechanism (using type=text inputs) is used.
520 To enable native date input you need to set the config variable ::
521
522 use_browser_date_input = yes
523
524 in section ``[web]`` in the ``config.ini`` file.
525
526 If native date input is used, simple uses of the ``field()`` method will
527 generate ``datetime-local`` inputs to allow selection of a date and time.
528 Input fields for ``Date()`` properties will not have the ``(cal)`` link
529 anymore. If fields should only use a date (without time) you can specify
530 the parameter ``display_time=no`` in ``schema.py`` for a ``Date()``
531 property (the default is ``yes``). This will use ``date`` inputs in the
532 generated html to select a date only. If you need this only for a single
533 date, the ``field()`` method now has a boolean parameter
534 ``display_time`` (which by default is set to the ``display_time``
535 parameter of ``Date()``)
536
537 Complex uses using a ``format`` specification in ``field()`` will not be
538 upgraded and will operate like earlier Roundup versions. In addition the
539 ``format`` can now also be specified in the ``Date()`` constructor.
540
541 To upgrade all date properties, there are five changes to make:
542
543 1. Configure ``use_browser_date_input = yes`` in section ``[web]`` in
544 ``config.ini``
545
546 2. Optionally add ``display_time = no`` in the schema for Date()
547 properties that should have no time displayed
548
549 3. Remove the format argument from field() calls on Date()
550 properties.
551
552 4. Remove popcal() calls.
553
554 5. Include datecopy.js in page.html.
555
556 The ``display_time`` option
557 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
558
559 Both the ``Date()`` constructor and the ``field`` call take a
560 ``display_time`` option which by default is ``yes`` in the ``Date()``
561 constructor and ``True`` in ``field``. The ``display_time`` setting of
562 ``Date()`` is inherited by the html property, so it doesn't need to be
563 specified in each ``field()`` call for this property.
564
565 When ``display_time`` is off, the date field does not include hours,
566 minutes or seconds.
567
568 Remove format argument
569 ~~~~~~~~~~~~~~~~~~~~~~
570
571 Speaking of arguments, avoid setting the date ``format`` if you want to
572 use native date inputs. If you include the `format` argument in the
573 `field` method, it should be removed.
574
575 By default using a format argument will show the
576 popup calendar link. You can disable the link by setting
577 ``popcal=False`` in the field() call. If you have::
578
579 tal:content="structure python:context.duedate.field(
580 placeholder='YYYY-MM, format='%Y-%m')"
581
582 changing it to::
583
584 tal:content="structure python:context.duedate.field(
585 placeholder='YYYY-MM, format='%Y-%m',
586 popcal=False)"
587
588 will generate the input as in Roundup 2.4 or earlier without a
589 popcal link.
590
591 Remove popcal
592 ~~~~~~~~~~~~~
593
594 if you have enabled date input types in the configuration and you
595 use the ``popcal()`` method directly in your templates, you
596 should remove them. The browser's native date selection calendar should
597 be used instead.
598
599 Add copy/paste/edit on double-click using datecopy.js
600 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
601
602 When using date input types,
603 there is no way to copy/paste using a native ``datetime-local`` or
604 ``date`` input. With the ``datecopy.js`` file installed, double-clicking
605 on the input turns it into a normal text input with the ability
606 to copy, paste, or manually edit the date.
607
608 To set this up, take either ``datecopy.js`` or the smaller
609 version, ``datecopy.min.js``, from the ``html`` folder of the
610 classic tracker template. Put the file in the ``html`` folder of
611 your tracker home.
612
613 After you install the datecopy file, you can add the script
614 directly to a page using::
615
616 <script tal:attributes="nonce request/client/client_nonce"
617 tal:content="structure python:utils.readfile('datecopy.min.js')">
618 </script>
619
620 or get the file in a separate download using a regular script
621 tag::
622
623 <script type="text/javascript" src="@@file/datecopy.js">
624 </script>
625
626 You can place these at the end of ``page.html`` just before the
627 close body ``</body>`` tag. This is the method used in the
628 classic template. This forces the file to be run for every page
629 even those that don't have any date inputs. However, it is cached
630 after the first download.
631
632 Alternatively you can inline or link to it using a script tag
633 only on pages that will have a date input. For example
634 ``issue.item.html``.
635
636 There is no support for activating text mode using the
637 keyboard. Tablet/touch support is mixed. Chrome supports
638 double-tap to activate text mode input. Firefox does not.
639
640 Enable native number inputs for Number() and Integer() (optional)
641 -----------------------------------------------------------------
642
643 Roundup's ``field()`` method for properties of type ``Number()`` or
644 ``Integer()`` can use a native browser number input by default.
645
646 This is configurable for *all* ``Number()`` and ``Integer()`` properties
647 with the config option ``use_browser_number_input`` in section ``[web]``.
648
649 You can use the old style text inputs for individual fields
650 by calling the field method with ``type="text"``.
651
652 Note that the ``Integer()`` type also uses ``step="1"`` by default to
653 add a stepper control and try to constrain the input to
654 integers. This can be overridden by passing a new step
655 (e.g. ``step="50"``) to the ``field()`` method.
656
657 This is an experiment and maybe changed based on feedback.
658
659 Change in REST response for invalid CORS requests (info)
660 --------------------------------------------------------
661
662 CORS_ preflight requests that are missing required headers can
663 now result in either a 403 or 400 error code. If you permit
664 anonymous users to access the REST interface, a 400 error may
665 still occur. Previously, only a 400 error was given. This change
666 is not expected to create issues since the client will recognize
667 both codes it as an error response, and the CORS request will
668 still fail.
669
670 More secure session cookie handling (info)
671 ------------------------------------------
672
673 This affects you if you are accessing a tracker via https. The name
674 for the cookie that you get when logging into the web interface has a
675 new name. When upgrading to Roundup 2.5 all users will have to to log
676 in again. The cookie now has a ``__Secure-`` prefix to prevent it
677 from being exposed/used over http.
678
679 If your tracker is using the unencrypted http protocol, nothing has
680 changed.
681
682 See
683 https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#cookie_prefixes
684 for details on this security measure.
685
686 Invalid accept header now prevents operation (info)
687 ---------------------------------------------------
688
689 In earlier versions, the rest interface checked for an incorrect
690 "Accept" header, "@apiver", or the ".json" mime type only after
691 processing the request. This would lead to a 406 error, but the
692 requested change would still be completed.
693
694 In this release, the validation of the output format and version
695 occurs before any database changes are made. Now, all errors related
696 to the data format (mime type, API version) will return 406 errors,
697 where some previously resulted in 400 errors.
698
699 New method for registering templating utils (info)
700 --------------------------------------------------
701
702 If you are building a template utility function that needs access
703 to:
704
705 * the database
706 * the client instance
707 * the form the user submitted
708
709 you had to pass these objects from the template using the ``db``,
710 ``request.client`` or ``request.form`` arguments.
711
712 A new method for registering a template utility has been added. If you
713 use the ``instance`` object's ``registerUtilMethod()`` to register a
714 utility function, you do not need to pass these arguments. The
715 function is called as a method and the first argument is a
716 TemplatingUtils (tu) instance from which the client object
717 (tu.client), the database (tu.client.db), form (tu.client.form),
718 request (tu.client.request), the translator for the current language
719 (tu._) and any functions (tu.X) you registered using
720 ``registerUtil()`` are available.
721
722 You can find an example in :ref:`dynamic_csp`.
723
724 Directions for installing gpg (optional)
725 ----------------------------------------
726
727 In this release a new version of the gpg module was needed for Ubuntu
728 24.04 and python 3.13. Paul Schwabauer produced a new version of the
729 gpg module. However it is only on the test instance of pypi. If you
730 run into issues installing gpg with pip, you can use::
731
732 pip install --index-url https://test.pypi.org/simple/ \
733 --extra-index-url https://pypi.org/simple gpg;
734
735 to installed version 2.0 of gpg from test.pypi.org obtaining it's
736 requirements from pypi.org.
737
738 When `issue2551368 <https://issues.roundup-tracker.org/issue2551368>`_
739 is closed, you should be able to use ``pip install gpg`` again.
740
741 .. index:: Upgrading; 2.3.0 to 2.4.0
94 742
95 Migrating from 2.3.0 to 2.4.0 743 Migrating from 2.3.0 to 2.4.0
96 ============================= 744 =============================
97 745
98 Update your ``config.ini`` (required) 746 Update your ``config.ini`` (required)
110 ``updateconfig`` will tell you if it is changing old default 758 ``updateconfig`` will tell you if it is changing old default
111 values or if a value must be changed manually. 759 values or if a value must be changed manually.
112 760
113 This will insert the bad API login rate limiting settings. 761 This will insert the bad API login rate limiting settings.
114 762
763 Also if you have ``html_version`` set to ``xhtml``, you will get
764 an error.
765
766 .. _CVE-2024-39124:
767
768 Fix for CVE-2024-39124 in help/calendar popups (recommended)
769 ------------------------------------------------------------
770
771 Classhelper components accessed via URL using ``@template=help``,
772 ``@template=calendar`` or other template frame in the classhelper
773 can run JavaScript embedded in the URL. If user clicks on a
774 malicious URL that:
775
776 * arrives in an email,
777 * is embedded in a note left on a ticket [#markdown-note]_,
778 * left on some other web page
779
780 the JavaScript code will be executed. This vulnerability seems to
781 be limited to manually crafted URL's. It has not been generated
782 by using Roundup's mechanism for generating classhelper URLs.
783
784 The files that need to be changed to fix this depend on the
785 template used to create the tracker. Check the
786 TEMPLATE-INFO.txt file in your tracker home. The template
787 name is the first component of the ``Name`` field. For
788 example trackers with Names like::
789
790 Name: classic-bugtracker
791
792 Name: devel-mytracker
793
794 were derived from the ``classic`` and ``devel`` templates
795 respectively. If your tracker is derived from the jinja2
796 template, you may not be affected as it doesn't provide
797 classhelpers by default. If you aren't sure which tracker
798 template was used to create your tracker home, check the
799 ``html/help.html`` file for the word ``Javascript``. If your
800 help.html is missing the word ``Javascript``, follow the
801 directions for the classic template.
802
803 If you have not modified the original tracker html
804 templates, you can copy replacement files from the new
805 templates supplied with release 2.4.0. If you install 2.4.0
806 in a `new virtual environment
807 <installation.html#standard-installation>`_, you can use the
808 command ``roundup-admin templates`` to find the installation
809 path of the default templates.
810
811 If your template was based on the classic template, replace the
812 following files in your tracker:
813
814 * html/_generic.calendar.html
815 * html/_generic.help-list.html
816 * html/_generic.help-submit.html
817 * html/_generic.help.html
818 * html/user.help-search.html
819 * html/user.help.html
820
821 If your template was based on the minimal template, replace the
822 following files in your tracker:
823
824 * html/_generic.calendar.html
825 * html/_generic.help.html
826
827 If your template was based on the responsive or devel templates,
828 replace the following files in your tracker:
829
830 * html/_generic.calendar.html
831 * html/_generic.help-submit.html
832 * html/help.html
833 * html/user.help-search.html
834 * html/user.help.html
835
836 As an example, assume Roundup's virtual environment is
837 ``/tools/roundup``. The classic tracker's default template will
838 be in ``/tools/roundup/share/roundup/templates/classic``.
839 Copy
840 ``/tools/roundup/share/roundup/templates/classic/html/_generic.calendar.html``
841 to ``html/_generic.calendar.html`` in your tracker's home
842 directory. Repeat for every one of the files that needs to
843 be replaced.
844
845 If you have made local changes to your popup/classhelper
846 files or have created new help templates based on the
847 existing ones, don't copy the default files. Instead, follow
848 the directions below to modify each file as needed for your
849 template.
850
851 In the examples below, your script tag may differ. For
852 example it could include::
853
854 tal:attributes="nonce request/client/client_nonce"
855
856 If it does, keep the differences. You want to make changes
857 to remove the structure option but keep the rest of the
858 valid attributes.
859
860 Most files have a small script that sets a few variables
861 from the settings in the URL. You should change::
862
863 <script language="Javascript" type="text/javascript"
864 tal:content="structure string:
865 // this is the name of the field in the original form that we're working on
866 form = window.opener.document.${request/form/form/value};
867 field = '${request/form/property/value}';">
868
869 to::
870
871 <script language="Javascript" type="text/javascript"
872 tal:content="string:
873 // this is the name of the field in the original form that we're working on
874 form = window.opener.document.${request/form/form/value};
875 field = '${request/form/property/value}';">
876
877 by removing the ``structure`` keyword from the tal:content
878 block. This will html escape the settings in the URL. This
879 neutralizes an attempt to execute JavaScript by manipulating
880 the URL. Most of the files use code similar to this.
881
882 A few files have more extensive JavaScript embedded in the same
883 script tag. To handle this you should split it into two scripts
884 and encode the replaced strings. For example, change::
885
886 <script language="Javascript" type="text/javascript"
887 tal:content="structure string:<!--
888 // this is the name of the field in the original form that we're working on
889 form = parent.opener.document.${request/form/form/value};
890 callingform=form
891 field = '${request/form/property/value}';
892 var listform = null
893 function listPresent() {
894 return document.frm_help.cb_listpresent.checked
895 [more code skipped]
896
897 to::
898
899 <script language="Javascript" type="text/javascript"
900 tal:content="string:
901 // this is the name of the field in the original form that we're working on
902 form = parent.opener.document.${request/form/form/value};
903 callingform=form
904 field = '${request/form/property/value}';">
905 </script>
906 <script language="Javascript" type="text/javascript"
907 tal:content="string:
908 var listform = null
909 function listPresent() {
910 return document.frm_help.cb_listpresent.checked
911 [...]
912
913 modifying the original by:
914
915 1. removing the ``structure`` keyword and the HTML comment
916 marker ``<!--``. This encodes the replaced strings.
917 2. adding ``">`` at the end of the line that sets ``field`` closes
918 the script tag.
919 3. adding::
920
921 </script>
922 <script language="Javascript" type="text/javascript"
923 tal:content="string:
924
925 after the line used in step 2, to ends the first script and
926 starts a new script.
927
928 Just removing the ``structure`` directive is enough to fix the
929 bug. Splitting the large script into two parts:
930
931 1. one that has replaced strings with values taken from the URL
932 2. one that has no replaced strings
933
934 allows use of ``structure`` on the script with no replaced
935 strings should it be required for your tracker.
936
937 .. [#markdown-note] If you are using markdown formatting for your tracker's notes,
938 the user will see the markdown label rather than the long
939 (suspicious) URL. You may want to add something like::
940
941 a[href*=\@template]::after {
942 content: ' [' attr(href) ']';
943 }
944
945 to your css. This displays the URL inside square brackets if
946 the href has ``@template`` in it. It is placed after the link
947 label.
948
949 Fix CVE in earlier versions of Roundup (recommended)
950 ----------------------------------------------------
951
952 If you are upgrading to version 2.4.0, you can skip this
953 section. These fixes are already present in 2.4.0.
954
955 This section is for people who can not upgrade yet, and want
956 to fix the issues.
957
958 .. _CVE-2024-39125:
959
960 Referer value not escaped CVE-2024-39125
961 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
962
963 Malicious JavaScript inserted into a page can change the value of
964 the Referer header to include a script. If a link on that page
965 points to a Roundup tracker, that script will be executed. The
966 technique to change the header will result in a change of the URL
967 in the browser's address bar, but this is easily missed.
968
969 Fix this by editing ``cgi/client.py``, and change::
970
971 except (UsageError, Unauthorised) as msg:
972 csrf_ok = False
973 self.form_wins = True
974 self._error_message = msg.args
975
976 to::
977
978 except (UsageError, Unauthorised) as msg:
979 csrf_ok = False
980 self.form_wins = True
981 self.add_error_message(' '.join(msg.args))
982
983 This escapes the Referer value and prevents it from being
984 executed.
985
986 .. _CVE-2024-39126:
987
988 Stop JavaScript execution from attached files CVE-2024-39126
989 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
990
991 If an SVG, XML or PDF file that includes malicious JavaScript is
992 attached to an issue, downloading the file will cause the
993 JavaScript to run.
994
995 In ``cgi/client.py`` add the Content-Security-Policy line
996 after the existing ``nosniff`` line so it looks like::
997
998 # exception handlers.
999 self.determine_language()
1000 self.db.i18n = self.translator
1001 self.setHeader("X-Content-Type-Options", "nosniff")
1002 self.setHeader("Content-Security-Policy", "script-src 'none'")
1003 self.serve_file(designator)
1004
1005 (the example is reindented for display).
1006
1007 This should prevent SVG and XML files with embedded scripts
1008 from running.
1009
1010 If your version of Roundup is old enough that the ``nosniff``
1011 line is missing, search for ``serve_file(designator)`` and add
1012 both setHeader lines.
1013
1014 .. warning::
1015
1016 If your users use older browsers that don't support Content
1017 Security Policies (e.g. Internet Explorer), you must
1018 remove ``text/xml`` and ``image/svg`` from
1019 ``mime_type_allowlist`` as explained below for
1020 ``application/pdf``.
1021
1022 PDF files can also embed JavaScript. Many browsers include
1023 PDF viewers that may not support disabling scripting. The
1024 safest way to handle this is to force a download of the PDF
1025 file and use a PDF viewer with scripting disabled. To force
1026 downloading, look in ``cgi/client.py`` for
1027 ``mime_type_allowlist`` and remove the line for
1028 ``application/pdf``.
1029
1030 Version 2.4.0 allows you to `modify the mime_type_allowlist
1031 using interfaces.py
1032 <admin_guide.html#controlling-browser-handling-of-attached-files>`_.
1033 This will allow you to enable in-browser reading of PDF
1034 files when you upgrade to 2.4.0 if you wish.
1035
1036 Note that a `Content Security Policy as documented in the admin
1037 guide
1038 <admin_guide.html#adding-a-web-content-security-policy-csp>`_ is
1039 not applied it to a direct download. This requires adding an
1040 explicit CSP header as above.
1041
1042 .. comment: end of CVE include marker
1043
1044 XHTML no longer supported (required)
1045 ------------------------------------
1046
1047 If your ``config.ini`` sets ``html_version`` to ``xhtml``,
1048 you need to change it to ``html``. Then you need to change
1049 your tracker's templates to html from xhtml.
1050
1051 Note that the default Roundup templates use html4 so it is
1052 unlikely that your templates are xhtml based. See
1053 `issue2551323
1054 <https://issues.roundup-tracker.org/issue2551323>`_ for
1055 details on the deprecation of xhtml.
1056
1057 Update MySQL character set/collations (required)
1058 ------------------------------------------------
1059
1060 issue2551282_ and issue2551115_ discuss issues with MySQL's utf8
1061 support. MySQL has variations on utf8 character support. This
1062 version of Roundup expects to use utf8mb4 which is a version of
1063 utf8 that covers all characters, not just the ones in the basic
1064 multilingual plane. Previous versions of Roundup used latin1 or
1065 utf8mb3 (also known as just utf8). Newer versions of MySQL are
1066 supposed to make utf8mb4 and not utf8mb3 the default.
1067
1068 To convert your database, you need to have MySQL 8.0.11 or newer
1069 (April 2018) and a mysql client.
1070
1071 .. warning::
1072
1073 This conversion can damage your database. Back up your
1074 database using mysqldump or other tools. Preferably on a quiet
1075 database. Verify that your database can be restored (or at
1076 least look up directions for restoring it). This is very
1077 important.
1078
1079 We suggest shutting down Roundup's interfaces:
1080
1081 * web
1082 * email
1083 * cron jobs that use Python or roundup-admin
1084
1085 then make your backup.
1086
1087 Then connect to your mysql instance using ``mysql`` with the
1088 information in ``config.ini``. If your tracker's ``config.ini``
1089 includes::
1090
1091 name = roundupdb
1092 host = localhost
1093 user = roundupuser
1094 password = rounduppw
1095
1096 you would run some version of::
1097
1098 mysql -u roundupuser --host localhost -p roundupdb
1099
1100 and supply ``rounduppw`` when prompted.
1101
1102 With the Roundup database quiet, convert the character set for the
1103 database and then for all the tables. To convert the tables you
1104 need a list of them. To get this run::
1105
1106 mysql -sN -u roundupuser --host localhost -p \
1107 -e 'show tables;' roundupdb > /tmp/tracker.tables
1108
1109 The ``-sN`` removes line drawing characters and column headers
1110 from the output. For each table ``<t>`` in the file, run::
1111
1112 ALTER TABLE `<t>` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
1113
1114 You can automate this conversion using sed::
1115
1116 sed -e 's/^/ALTER TABLE `/' \
1117 -e 's/$/` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;/'\
1118 /tmp/tracker.tables> /tmp/tracker.tables.sql
1119
1120 The backticks "`" are required as some of the table names became
1121 MySQL reserved words during Roundup's lifetime.
1122
1123 Inspect ``tracker.tables.sql`` to see if all the lines look
1124 correct. If so then we can start the conversion.
1125
1126 First convert the character set for the database by running::
1127
1128 mysql -u roundupuser --host localhost -p roundupdb
1129
1130 Then at the ``mysql>`` prompt run::
1131
1132 ALTER DATABASE roundupdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
1133
1134 you should see: ``Query OK, 1 row affected (0.01 sec)``.
1135
1136 Now to modify all the tables run:
1137
1138 \. /tmp/tracker.tables.sql
1139
1140 You will see output similar to::
1141
1142 Query OK, 5 rows affected (0.01 sec)
1143 Records: 5 Duplicates: 0 Warnings: 0
1144
1145 for each table. The rows/records will depend on the number of
1146 entries in the table. This can take a while.
1147
1148 Once you have successfully completed this, copy your tracker's
1149 config.ini to a backup file. Edit ``config.ini`` to use the defaults:
1150
1151 * mysql_charset = utf8mb4
1152 * mysql_collation = utf8mb4_unicode_ci
1153 * mysql_binary_collation = utf8mb4_0900_bin
1154
1155 Also look for a ``~/.my.cnf`` for the roundup user and make sure
1156 that the settings for character set (charset) are utf8mb4 compatible.
1157
1158 To test, run ``roundup-admin -i tracker_home`` and display an
1159 issue designator: e.g. ``display issue10``. Check that the text
1160 fields are properly displayed (e.g. title). Start the web
1161 interface and browse some issues. Again, check that the text
1162 fields display correctly, that the history at the bottom of the
1163 issues displays correctly and if you are using the default full
1164 text search, make sure that that works.
1165
1166 If this works, bring email cron jobs etc. back online.
1167
1168 If this fails, take down the web interface, restore the database
1169 from backup, restore the old config.ini. Then test again and
1170 reach out to the mailing list for help.
1171
1172 We can use assistance in getting these directions corrected or
1173 enhanced. The core Roundup developers don't use MySQL for their
1174 production workloads so we count on users to help us with this.
1175
1176 References:
1177
1178 * https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4
1179 * https://adamhooper.medium.com/in-mysql-never-use-utf8-use-utf8mb4-11761243e434
1180
1181 .. _issue2551282: https://issues.roundup-tracker.org/issue2551282
1182 .. _issue2551115: https://issues.roundup-tracker.org/issue2551115
1183
1184 Disable spellcheck on all password fields (recommended)
1185 -------------------------------------------------------
1186
1187 All tracker templates have been updated to disable spell checking on
1188 password input fields. This can help prevent exposing the password to
1189 an external server that provides spell checking for a browser. Since
1190 passwords should not be real words in any language, spell checking
1191 serves no purpose.
1192
1193 If you have modified your template with a "show password" option you
1194 should disable spell check.
1195
1196 To implement this in your deployed trackers, add::
1197
1198 spellcheck="false"
1199
1200 to make your password inputs look like::
1201
1202 <input type="password" spellcheck="false" name=....>
1203
1204 The changed files in the classic/devel/responsive templates are:
1205
1206 .. code-block:: text
1207
1208 html/page.html
1209 html/user.item.html
1210
1211 and in the jinja2 template the following files were changed:
1212
1213 .. code-block:: text
1214
1215 html/user.item.html
1216 html/user.register.html
1217 html/layout/navigation.html
1218
1219 Add new classhelper to your templates (optional)
1220 ------------------------------------------------
1221
1222 The classic classhelper invoked by the ``(list)`` link in your
1223 issue.item.html template can be greatly improved by wrapping the
1224 links with the new web-component based ``roundup-classhelper``.
1225
1226 The new classhelper:
1227
1228 * allows you to select items from multiple pages
1229 * is usable with a content security policy
1230 * is more easily styled
1231
1232 To deploy it, install the required files and wrap classhelp calls
1233 in the new ``<roundup-classhelper>`` component. For example,
1234 wrap::
1235
1236 <span tal:condition="context/is_edit_ok" tal:replace="structure
1237 python:db.user.classhelp('username,realname,address',
1238 property='nosy', width='600'" />
1239
1240 so it looks like::
1241
1242 <roundup-classhelper
1243 data-search-with="username,phone,roles[]">
1244
1245 <span tal:condition="context/is_edit_ok" tal:replace="structure
1246 python:db.user.classhelp('username,realname,address',
1247 property='nosy', width='600')" />
1248
1249 </roundup-classhelper>
1250
1251 to allow the user to search by: username, phone number and use a
1252 select/dropdown to search by role. Full details about the
1253 attributes and installation instructions can be found in the
1254 `classhelper documentation`_ in the admin guide.
1255
1256
1257 Disable performance improvement for wsgi mode (optional)
1258 --------------------------------------------------------
1259
1260 In Roundup version 2.2.0, an experimental feature was introduced to
1261 enhance performance while operating in wsgi mode. Initially, this
1262 feature was disabled. Over the past two years, it has been used at a
1263 few sites without any reported problems.
1264
1265 As a result, the default setting now enables this performance
1266 improvement, encouraging a wider adoption of the feature. In the
1267 event that an undiscovered bug arises, it can still be disabled
1268 if you experience problems. To disable it, modify your wsgi
1269 startup script and add the feature_flags to the RequestDispatcher
1270 as below::
1271
1272 feature_flags = { "cache_tracker": False }
1273 app = RequestDispatcher(tracker_home, feature_flags=feature_flags)
1274
1275 Then restart your wsgi instance. If you have to disable this
1276 feature, send email to the roundup-users mailing list
1277 (roundup-users at lists.sourceforge.net) so we can help you
1278 diagnose the cause and fix it for everybody.
1279
1280 In the future, support for disabling this improvement will be removed.
1281
115 Fix duplicate id for confirm password in user.item.html (optional) 1282 Fix duplicate id for confirm password in user.item.html (optional)
116 ------------------------------------------------------------------ 1283 ------------------------------------------------------------------
117 1284
118 The TAL macro ``user_confirm_input`` at the end of ``html/page.html`` 1285 The TAL macro ``user_confirm_input`` at the end of ``html/page.html``
119 for all templates except ``jinja2`` sets the ``id`` of the ``Confirm 1286 for all templates except ``jinja2`` sets the ``id`` of the ``Confirm
132 to:: 1299 to::
133 1300
134 tal:attributes="id string:confirm_$name; name string:@confirm@$name; readonly not:edit_ok" value=""> 1301 tal:attributes="id string:confirm_$name; name string:@confirm@$name; readonly not:edit_ok" value="">
135 1302
136 This will change the id to ``confirm_password``. 1303 This will change the id to ``confirm_password``.
1304
1305 Merge changes from devel template task.index.html (optional)
1306 ------------------------------------------------------------
1307
1308 The devel template's ``task.index.html`` has some fields that are not
1309 defined in the schema. It looks like it was originally copied from the
1310 ``bug.index.html``. If the task index is requested without specifying
1311 the columns/fields, the template will crash trying to display
1312 ``severity`` and other fields that don't exist in the task schema.
1313
1314 In normal use, the left hand menu for tasks always specifies valid
1315 columns so you may not see this issue. However if you remove the
1316 ``@columns`` query parameter, you can see the error.
1317
1318 The removed columns are: severity, versions, keywords, dependencies.
1319
1320 It is also missing the ``solves`` field which is added to match the
1321 schema.
1322
1323 `You can see the diff in the Sourceforge web interface <https://sourceforge.net/p/roundup/code/ci/54eb12cd3be143b079809795dcb2f813f75a691c/tree/share/roundup/templates/devel/html/task.index.html?diff=c95870b2bbab822def6066498a4ef8634e76e0b3>`_.
1324
1325 Make group headers span all columns (optional)
1326 ----------------------------------------------
1327
1328 In a number of index pages a version of the following TAL command
1329 appears::
1330
1331 <th tal:attributes="colspan python:len(request.columns)" class="group">
1332
1333 If the ``@columns`` parameter (aka request.columns) is not set,
1334 all columns are shown. However the group header only spans the
1335 first column. Changing this to read::
1336
1337 <th tal:attributes="colspan python:len(request.columns) or 100" class="group">
1338
1339 makes the group header span all the columns (if you have fewer
1340 than 100 columns). All of the supplied templates hae been
1341 upgraded with this change. `See issue 2551341 for details
1342 <https://issues.roundup-tracker.org/issue2551341>`_.
1343
1344 Note the jinja2 template has the same issue, but the development
1345 team hasn't devised a solution.
1346
1347 Use @current_user in Searches (optional)
1348 ----------------------------------------
1349
1350 You can create queries like: "My issues" by searching the ``creator``
1351 property of issues for your id number. Similarly you can search for
1352 "Issues assigned to me" by searching on the ``assignedto`` property.
1353
1354 Queries in Roundup can be shared between users. However queries like
1355 these can be shared. However for any user but they will only find
1356 issues created by/assigned to the user who created the query.
1357
1358 This release allows you to search Links to the User class by
1359 specifying ``@current_user``. This token searches for the currently
1360 log in user. It makes searches like the above usable when shared.
1361
1362 This only works for properties that are a Link to the user
1363 class. E.G. creator, actor, assignedto. It does not yet work for
1364 MultiLink properties (like nosy).
1365
1366 As an example this can be deployed to the classic tracker's issue
1367 search template (issue.search.html), by replacing::
1368
1369 <option metal:fill-slot="extra_options" i18n:translate=""
1370 tal:attributes="value request/user/id">created by
1371 me</option>
1372
1373 with::
1374
1375 <option metal:fill-slot="extra_options" value="@current_user"
1376 tal:attributes="selected python:value == '@current_user'"
1377 i18n:translate="">created by me</option>
1378
1379 There are three places where ``value request/user/id`` is used in the
1380 classic template. Your template may have more.
1381
1382 If you have a user with the exact username of `@current_user` they
1383 should change it. `Details can be found in issue1525113
1384 <https://issues.roundup-tracker.org/issue1525113>`_.
1385
1386 New PostgreSQL Settings (optional)
1387 ----------------------------------
1388
1389 With this release, you can specify a Postgresql database schema
1390 to use. By default Roundup creates a database when using
1391 ``roundup-admin init``. Setting the rdbms ``name`` keyword to
1392 ``roundup_database.roundup_schema`` will create and use the
1393 ``roundup_schema`` in the pre-created ``roundup_database``. See
1394 the `Roundup PostgreSQL documentation`_ for details on how to set
1395 up the roles.
1396
1397 Also there is a new configuration keyword in the rdbms
1398 section of ``config.ini``. The ``service`` keyword allows
1399 you to define the service name for Postgres that will be
1400 looked up in the `Connection Service File`_. Any of the
1401 methods of specifying the file including by using the
1402 ``PGSERVICEFILE`` environment variable are supported.
1403
1404 This is similar to the existing support for MySQL
1405 option/config files and groups.
1406
1407 If you use services, any settings for the same properties
1408 (user, name, password ...) that are in the tracker's
1409 ``config.ini`` will override the service settings. So you
1410 want to leave the ``config.ini`` settings blank. E.G.::
1411
1412 [rdbms]
1413 name =
1414 host =
1415 port =
1416 user =
1417 password =
1418 service = roundup_roundup
1419
1420 Setting ``service`` to ``roundup_roundup`` with
1421 the following in the service file::
1422
1423 [roundup_roundup]
1424 host=127.0.0.1
1425 port=5432
1426 user=roundup
1427 password=roundup
1428 dbname=roundup
1429
1430 would use the roundup database with the specified
1431 credentials. It is possible to define a service that
1432 connects to a specific schema using::
1433
1434 options=-c search_path=roundup_service_dev
1435
1436 Note that the first schema specified after ``search_path=``
1437 is created and populated. The schema name
1438 (``roundup_service_dev``) must be terminated by: a comma,
1439 whitespace or end of line.
1440
1441 You can use the command ``psql "service=db_service_name"``
1442 to verify the settings in the connection file. Inside of
1443 ``psql`` you can verify the ``search_path`` using ``show
1444 search_path;``.
1445
1446 .. _`Connection Service File`: https://www.postgresql.org/docs/current/libpq-pgservice.html
1447
1448 Update for user.help-search.html (optional)
1449 -------------------------------------------
1450
1451 There is a bug in the template used as a search helper for the user
1452 fields (e.g. the nosy list). The ``properties`` url query argument was
1453 ignored. You can not select the displayed fields using the
1454 ``properties`` argument. This is fixed in 2.4.0. You can probably just
1455 copy the ``user.help-search.html`` from the classic tracker template.
1456
1457 If you have modified that template, you can follow the analysis in
1458 `issue2551320 <https://issues.roundup-tracker.org/issue2551320>`_
1459 to fix your template.
1460
1461 Update for _generic.help.html (optional)
1462 ----------------------------------------
1463
1464 Using the ``_generic.help.html`` template with ``classhelper()`` to
1465 provide information on a property without selecting a property caused
1466 an error when processing the template. Using the help template with
1467 Link properties can provide description or other information that the
1468 user can use to determine the right setting.
1469
1470 If your tracker is based on the minimal or classic tracker and you have
1471 not changed the _generic.help.html file, you can copy it into place
1472 from the template directory.
1473
1474
1475 Fix static_files use of '-' directory (info)
1476 --------------------------------------------
1477
1478 Use of the '-' directory in ``static_files`` config.ini setting now
1479 works. So it will prevent access to the html directory when using
1480 ``@@file/`` based url's.
1481
137 1482
138 Bad Login Rate Limiting and Locking (info) 1483 Bad Login Rate Limiting and Locking (info)
139 ------------------------------------------ 1484 ------------------------------------------
140 1485
141 Brute force logins have been rate limited in the HTML web interface 1486 Brute force logins have been rate limited in the HTML web interface
158 and its storage objects available by importing from:: 1503 and its storage objects available by importing from::
159 1504
160 from roundup.anypy.cgi_ import cgi 1505 from roundup.anypy.cgi_ import cgi
161 from roundup.anypy.cgi_ import FieldStorage, MiniFieldStorage 1506 from roundup.anypy.cgi_ import FieldStorage, MiniFieldStorage
162 1507
163 It is unlikey that you will care unless you have done some expert 1508 It is unlikely that you will care unless you have done some expert
164 level Roundup customization. If you have, use one of the imports above 1509 level Roundup customization. If you have, use one of the imports above
165 if you plan on running on Python 3.13 (expected in 2024) or newer. 1510 if you plan on running on Python 3.13 (expected in 2024) or newer.
166 1511
167 Fixing PostgreSQL Out of Memory Errors when Importing Tracker (info) 1512 Fixing PostgreSQL Out of Memory Errors when Importing Tracker (info)
168 -------------------------------------------------------------------- 1513 --------------------------------------------------------------------
175 1520
176 before changing your PostgreSQL configuration, try changing the pragma 1521 before changing your PostgreSQL configuration, try changing the pragma
177 ``savepoint_limit`` to a lower value. By default it is set to 1522 ``savepoint_limit`` to a lower value. By default it is set to
178 ``10000``. In some cases this may be too high. See the `administration 1523 ``10000``. In some cases this may be too high. See the `administration
179 guide`_ for further details. 1524 guide`_ for further details.
1525
1526 roundup-admin's History Command Produces Readable Output (info)
1527 ---------------------------------------------------------------
1528
1529 The history command of roundup-admin used to print the raw journal
1530 data. In this release the default is to produce more human readable
1531 data. The original output (not pretty printed as below) was::
1532
1533 [('1', <Date 2013-02-18.20:30:34.125>, '1', 'create', {}),
1534 ('1',
1535 <Date 2013-02-19.21:24:20.391>,
1536 '1',
1537 'set',
1538 {'messages': (('+', ['3']),)}),
1539 ('1', <Date 2013-02-19.21:24:24.797>, '1', 'set', {'priority': '1'}),
1540 ('1',
1541 <Date 2013-02-20.03:16:52.000>,
1542 '1',
1543 'link',
1544 ('issue', '2', 'dependson')),
1545 ('1', <Date 2013-02-21.20:51:40.750>, '1', 'link', ('issue', '2',
1546 'seealso')),
1547 ('1',
1548 <Date 2013-02-22.05:33:08.875>,
1549 '1',
1550 'set',
1551 {'dependson': (('+', ['3']),), 'private': None, 'queue': None}),
1552 ('1',
1553 <Date 2013-02-22.05:33:19.406>,
1554 '1',
1555 'set',
1556 {'dependson': (('+', ['2']),)}),
1557 ('1',
1558 <Date 2013-02-27.03:24:42.844>,
1559 '1',
1560 'unlink',
1561 ('issue', '2', 'seealso')),
1562 ...
1563
1564 Now it produces (Each entry is on one line, lines wrapped
1565 and indented for display)::
1566
1567 admin(2013-02-18.20:30:34) create issue
1568 admin(2013-02-19.21:24:20) set modified messages: added: msg3
1569 admin(2013-02-19.21:24:24) set priority was critical(1)
1570 admin(2013-02-20.03:16:52) link added issue2 to dependson
1571 admin(2013-02-21.20:51:40) link added issue2 to seealso
1572 admin(2013-02-22.05:33:08) set modified dependson: added: issue3;
1573 private was None; queue was None
1574 admin(2013-02-22.05:33:19) set modified dependson: added: issue2
1575 admin(2013-02-27.03:24:42) unlink removed issue2 from seealso
1576 ...
1577
1578
1579 A few things to note: set operations can either assign a property or
1580 report a modification of a multilink property. If an assignment
1581 occurs, the value reported is the **old value** that was there before
1582 the assignment. It is **not** the value that is assigned. In the
1583 example above I don't know what the current value of priority is. All
1584 I know it was set to critical when the issue was created.
1585
1586 Modifications to multilink properties work differently. I know that
1587 ``msg3`` was present in the messages property after 2013-02-19 at
1588 21:24:20 UTC.
1589
1590 The history command gets a new optional argument ``raw`` that produces
1591 the old style output. The old style is (marginally) more useful for
1592 script automation.
1593
1594 Deprecation Notices (info)
1595 --------------------------
1596
1597 Support for SQLite version 1 has been removed in 2.4.0.
1598
1599 Support for SQLite version 2 will be removed in 2.5.0.
1600
1601 Support for StructuredText has been removed in 2.4.0. Support for
1602 reStructuredText remains.
1603
1604 Support for the `PySQLite <https://github.com/ghaering/pysqlite>`_
1605 library will be removed in 2.5.0. Only the Python supplied sqlite3
1606 library will be supported.
180 1607
181 .. index:: Upgrading; 2.2.0 to 2.3.0 1608 .. index:: Upgrading; 2.2.0 to 2.3.0
182 1609
183 Migrating from 2.2.0 to 2.3.0 1610 Migrating from 2.2.0 to 2.3.0
184 ============================= 1611 =============================
256 PostgreSQL database use a numeric type that 1683 PostgreSQL database use a numeric type that
257 truncates/rounds expiration timestamps. This results in 1684 truncates/rounds expiration timestamps. This results in
258 entries being purged early or late (depending on whether 1685 entries being purged early or late (depending on whether
259 it rounds up or down). The discrepancy is a couple of 1686 it rounds up or down). The discrepancy is a couple of
260 days for Mysql or a couple of minutes for PostgreSQL. 1687 days for Mysql or a couple of minutes for PostgreSQL.
261 1688
262 Session keys stay for a week or more and CSRF keys are 1689 Session keys stay for a week or more and CSRF keys are
263 two weeks by default. As a result, this isn't usually a 1690 two weeks by default. As a result, this isn't usually a
264 visible issue. This migration updates the numeric types 1691 visible issue. This migration updates the numeric types
265 to ones that supports more significant figures. 1692 to ones that supports more significant figures.
266 1693
313 1740
314 Update ``config.ini``'s ``password_pbkdf2_default_rounds`` (required) 1741 Update ``config.ini``'s ``password_pbkdf2_default_rounds`` (required)
315 --------------------------------------------------------------------- 1742 ---------------------------------------------------------------------
316 1743
317 Roundup hashes passwords using PBKDF2 with SHA1. In this release, you 1744 Roundup hashes passwords using PBKDF2 with SHA1. In this release, you
318 can `upgrade to PBKDF2-SHA512 from current PBKDF2-SHA1`. If you 1745 can `upgrade to PBKDF2-SHA512 from current PBKDF2-SHA1 (recommended)`_. If you
319 upgrade, you want to set the default rounds according to the 1746 upgrade, you want to set the default rounds according to the
320 PBKDF2-SHA512 upgrading directions. Note that this algorithm is 1747 PBKDF2-SHA512 upgrading directions. Note that this algorithm is
321 expected to be the default in a future version of Roundup. 1748 expected to be the default in a future version of Roundup.
322 1749
323 If you don't want to upgrade, we recommend that you increase the 1750 If you don't want to upgrade, we recommend that you increase the
383 You should find out how to make the import succeed. You may need to 1810 You should find out how to make the import succeed. You may need to
384 install an OS vendor package or some other library. 1811 install an OS vendor package or some other library.
385 1812
386 .. _recommended setting of 1,300,000: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2 1813 .. _recommended setting of 1,300,000: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
387 1814
1815 .. _PBKDF2 upgrade:
1816
388 Upgrade to PBKDF2-SHA512 from current PBKDF2-SHA1 (recommended) 1817 Upgrade to PBKDF2-SHA512 from current PBKDF2-SHA1 (recommended)
389 --------------------------------------------------------------- 1818 ---------------------------------------------------------------
390 1819
391 We recommend that you upgrade to using PBKDF2-SHA512 for hashing your 1820 We recommend that you upgrade to using PBKDF2-SHA512 for hashing your
392 passwords. This is a more secure method than the old PBKDF2 (with 1821 passwords. This is a more secure method than the old PBKDF2 (with
414 command line (``roundup-admin`` for example). 1843 command line (``roundup-admin`` for example).
415 1844
416 Change the default hashing scheme by adding the following lines to 1845 Change the default hashing scheme by adding the following lines to
417 |the interfaces.py file|_ in your tracker home:: 1846 |the interfaces.py file|_ in your tracker home::
418 1847
1848 from roundup.password import Password
419 ## Use PBDKF2S5 (PBKDF2-SHA512) for passwords. Re-hash old PBDFK2 1849 ## Use PBDKF2S5 (PBKDF2-SHA512) for passwords. Re-hash old PBDFK2
420 # Force password with scheme PBKDF2 (SHA1) to get re-hashed 1850 # Force password with scheme PBKDF2 (SHA1) to get re-hashed
421 Password.deprecated_schemes.insert(0, Password.known_schemes[0]) 1851 Password.deprecated_schemes.insert(0, Password.known_schemes[0])
422 # choose PBKDF2S5 as the scheme to use for rehashing. 1852 # choose PBKDF2S5 as the scheme to use for rehashing.
423 Password.default_scheme = Password.experimental_schemes[0] 1853 Password.default_scheme = Password.experimental_schemes[0]
429 1859
430 You can verify that PBKDF2S5 is used by default by running:: 1860 You can verify that PBKDF2S5 is used by default by running::
431 1861
432 roundup-admin -i <tracker_home> perftest password rounds=250,000 1862 roundup-admin -i <tracker_home> perftest password rounds=250,000
433 1863
434 and verify that the scheme is PBKDF2S5. 1864 and verify that the scheme is PBKDF2S5.
435 1865
436 .. _the interfaces.py file: 1866 .. _the interfaces.py file:
437 reference.html#interfaces-py-hooking-into-the-core-of-roundup 1867 reference.html#interfaces-py-hooking-into-the-core-of-roundup
438 1868
439 .. |the interfaces.py file| replace:: the ``interfaces.py`` file 1869 .. |the interfaces.py file| replace:: the ``interfaces.py`` file
490 sqlite3 <tracker_home>/db/db "pragma journal_mode;" 1920 sqlite3 <tracker_home>/db/db "pragma journal_mode;"
491 1921
492 2. If it returns ``delete``, change it to WAL mode using:: 1922 2. If it returns ``delete``, change it to WAL mode using::
493 1923
494 sqlite3 <tracker_home>/db/db "pragma journal_mode=WAL;" 1924 sqlite3 <tracker_home>/db/db "pragma journal_mode=WAL;"
495 1925
496 3. verify by running the command in step 1 again and you 1926 3. verify by running the command in step 1 again and you
497 should get ``wal``. 1927 should get ``wal``.
498 1928
499 If you are using SQLite for session and otk databases, 1929 If you are using SQLite for session and otk databases,
500 perform the same steps replacing ``db`` with ``db-session`` 1930 perform the same steps replacing ``db`` with ``db-session``
513 1943
514 Change in processing allowed_api_origins setting (info) 1944 Change in processing allowed_api_origins setting (info)
515 ------------------------------------------------------- 1945 -------------------------------------------------------
516 1946
517 In this release you can use both ``*`` (as the first origin) and 1947 In this release you can use both ``*`` (as the first origin) and
518 explicit origins in the `allowed_api_origins`` setting in 1948 explicit origins in the ``allowed_api_origins`` setting in
519 ``config.ini``. (Before it was only one or the other.) 1949 ``config.ini``. (Before it was only one or the other.)
520 1950
521 You do not need to use ``*``. If you do, it allows any client 1951 You do not need to use ``*``. If you do, it allows any client
522 anonymous (unauthenticated) access to the Roundup tracker. This 1952 anonymous (unauthenticated) access to the Roundup tracker. This
523 is the same as browsing the tracker without logging in. If they 1953 is the same as browsing the tracker without logging in. If they
626 allowed to login. Blank passwords have been allowed since 2002, but 2056 allowed to login. Blank passwords have been allowed since 2002, but
627 2022 is a different time. If you have a use case that requires a user 2057 2022 is a different time. If you have a use case that requires a user
628 to login without a password, set the ``login_empty_passwords`` setting 2058 to login without a password, set the ``login_empty_passwords`` setting
629 in the ``web`` section of ``config.ini`` to ``yes``. In 2059 in the ``web`` section of ``config.ini`` to ``yes``. In
630 general this should be left at its default value of ``no``. 2060 general this should be left at its default value of ``no``.
2061
2062 Verify that SQLite supports FTS5 (required)
2063 -------------------------------------------
2064
2065 If you use SQLite as your backend, it *must* support FTS5. See the
2066 `FTS5 testing steps`_ for how to verify this.
2067
2068 .. _FTS5 testing steps: installation.html#fts5-testing
631 2069
632 Check allowed_api_origins setting (optional) 2070 Check allowed_api_origins setting (optional)
633 -------------------------------------------- 2071 --------------------------------------------
634 2072
635 If you are using the REST or xmlrpc api's from an origin 2073 If you are using the REST or xmlrpc api's from an origin
677 https://www.postgresql.org/docs/14/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES 2115 https://www.postgresql.org/docs/14/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES
678 can be used. The default is websearch. Prefixing the search with 2116 can be used. The default is websearch. Prefixing the search with
679 ``ts:`` enables tsquery mode. 2117 ``ts:`` enables tsquery mode.
680 2118
681 A list of words behaves almost the same as the default text search 2119 A list of words behaves almost the same as the default text search
682 (`native`). So the search string `fts search` will find all issues 2120 (``native``). So the search string ``fts search`` will find all issues
683 that have both of those words (an AND search) in a text-field (like 2121 that have both of those words (an AND search) in a text-field (like
684 title) or in a message (or file) attached to the issue. 2122 title) or in a message (or file) attached to the issue.
685 2123
686 One thing to note is that native-fts searches do not ignore words 2124 One thing to note is that native-fts searches do not ignore words
687 longer than 50 characters or less than 2 characters. Also SQLite does 2125 longer than 50 characters or less than 2 characters. Also SQLite does
968 + from html import escape 2406 + from html import escape
969 +except ImportError: 2407 +except ImportError:
970 + from cgi import escape 2408 + from cgi import escape
971 2409
972 try: 2410 try:
973 import pytz 2411 import pytz
974 @@ -25,7 +28,7 @@ 2412 @@ -25,7 +28,7 @@
975 s = ' ' 2413 s = ' '
976 if zone == value: 2414 if zone == value:
977 s = 'selected=selected ' 2415 s = 'selected=selected '
978 - z = cgi.escape(zone) 2416 - z = cgi.escape(zone)
979 + z = escape(zone) 2417 + z = escape(zone)
980 2418
981 See https://issues.roundup-tracker.org/issue2551136 for more details. 2419 See https://issues.roundup-tracker.org/issue2551136 for more details.
982 2420
1055 will take longer but may be worth trying if the ``exporttables`` and 2493 will take longer but may be worth trying if the ``exporttables`` and
1056 ``importtables`` method fails for some reason. 2494 ``importtables`` method fails for some reason.
1057 2495
1058 Another way that should be faster, but is untested is to use mysql 2496 Another way that should be faster, but is untested is to use mysql
1059 dump to dump the database. 2497 dump to dump the database.
1060 https://makandracards.com/makandra/595-dumping-and-importing-from-to-mysql-in-an-utf-8-safe-way 2498 https://makandracards.com/makandra/595-dumping-importing-mysql-utf-8-safe-way
1061 recommends:: 2499 recommends:
1062 2500
1063 Note that when your MySQL server is not set to UTF-8 you need to do 2501 Note that when your MySQL server is not set to UTF-8 you need to do
1064 mysqldump --default-character-set=latin1 (!) to get a correctly 2502 mysqldump --default-character-set=latin1 (!) to get a correctly
1065 encoded dump. In that case you will also need to remove the SET 2503 encoded dump. In that case you will also need to remove the SET
1066 NAMES='latin1' comment at the top of the dump, so the target machine 2504 NAMES='latin1' comment at the top of the dump, so the target machine
1068 2506
1069 Then import the dump. Removing ``SET NAMES`` should allow the import 2507 Then import the dump. Removing ``SET NAMES`` should allow the import
1070 to use UTF-8. 2508 to use UTF-8.
1071 2509
1072 Please report success or issues with this conversion to the 2510 Please report success or issues with this conversion to the
1073 roundup-users AT lists.sourceforge.net mailing list. 2511 roundup-users at lists.sourceforge.net mailing list.
1074 2512
1075 As people report successful or unsuccessful conversions, we will update 2513 As people report successful or unsuccessful conversions, we will update
1076 the errata page at: https://wiki.roundup-tracker.org/ReleaseErrata. 2514 the errata page at: https://wiki.roundup-tracker.org/ReleaseErrata.
1077 2515
1078 Upgrade tracker's config.ini file (recommended) 2516 Upgrade tracker's config.ini file (recommended)
1134 processed. 2572 processed.
1135 2573
1136 If you do not modify the ``user.register.html`` template in your 2574 If you do not modify the ``user.register.html`` template in your
1137 tracker's html directory, you *must* set this to 0. Otherwise you will 2575 tracker's html directory, you *must* set this to 0. Otherwise you will
1138 see the error: 2576 see the error:
2577
2578 .. code-block:: text
1139 2579
1140 Form is corrupted, missing: opaqueregister. 2580 Form is corrupted, missing: opaqueregister.
1141 2581
1142 If set to 0, the rate limit check is disabled. 2582 If set to 0, the rate limit check is disabled.
1143 2583
1411 this section. 2851 this section.
1412 2852
1413 Make sure that user can view labelprop on classes (required) 2853 Make sure that user can view labelprop on classes (required)
1414 ------------------------------------------------------------ 2854 ------------------------------------------------------------
1415 2855
1416 If you have View permissions that use ```properties=...```, make sure 2856 If you have View permissions that use ``properties=...``, make sure
1417 that the `labelprop <reference.html#setlabelprop-property>`_ for the 2857 that the `labelprop <reference.html#setlabelprop-property>`_ for the
1418 class is listed in the properties list. 2858 class is listed in the properties list.
1419 2859
1420 The first one of these that exists must must be in the list: 2860 The first one of these that exists must must be in the list:
1421 2861
1526 these forms as it is not needed. 2966 these forms as it is not needed.
1527 2967
1528 Errors and Troubleshooting - AttributeError list object no attribute value 2968 Errors and Troubleshooting - AttributeError list object no attribute value
1529 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2969 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1530 If you get an error: 2970 If you get an error:
2971
2972 .. code-block:: text
1531 2973
1532 AttributeError: 'list' object has no attribute 'value' 2974 AttributeError: 'list' object has no attribute 'value'
1533 2975
1534 in handle_csrf, you have more than one @csrf token for the form. This 2976 in handle_csrf, you have more than one @csrf token for the form. This
1535 usually occurs because the form uses the standard context/submit 2977 usually occurs because the form uses the standard context/submit
1696 # who updated the issue, but it could be useful in some 3138 # who updated the issue, but it could be useful in some
1697 # unusual circumstances. 3139 # unusual circumstances.
1698 # If set to some other value, the value is used as the reply-to 3140 # If set to some other value, the value is used as the reply-to
1699 # address. It must be a valid RFC2822 address or people will not be 3141 # address. It must be a valid RFC2822 address or people will not be
1700 # able to reply. 3142 # able to reply.
1701 # Default: 3143 # Default:
1702 replyto_address = 3144 replyto_address =
1703 3145
1704 Login from a search or after logout works better (required) 3146 Login from a search or after logout works better (required)
1705 ----------------------------------------------------------- 3147 -----------------------------------------------------------
1706 3148
1707 The login form has been improved to work with some back end code 3149 The login form has been improved to work with some back end code
1708 changes. Now when a user logs in they stay on the same page where they 3150 changes. Now when a user logs in they stay on the same page where they
1709 started the login. To make this work, you must change the tal that is 3151 started the login. To make this work, you must change the tal that is
1710 used to set the ``__came_from`` form variable. Note that the url 3152 used to set the ``__came_from`` form variable. Note that the url
1711 assigned to __came_from must be url encoded/quoted and be under the 3153 assigned to __came_from must be url encoded/quoted and be under the
1712 tracker's base url. If the base_url uses http, you can set the url to 3154 tracker's base url. If the base_url uses http, you can set the url to
1713 https. 3155 https.
1714 3156
1715 Replace the existing code in the tracker's html/page.html page that 3157 Replace the existing code in the tracker's html/page.html page that
1716 looks similar to (look for name="__came_from"): 3158 looks similar to (look for name="__came_from"):
1717 3159
1869 :class: big-code 3311 :class: big-code
1870 3312
1871 <tal:block tal:repeat="qs request/user/queries"> 3313 <tal:block tal:repeat="qs request/user/queries">
1872 - <a href="#" tal:attributes="href string:${qs/klass}?${qs/url}&@dispname=${qs/name}" 3314 - <a href="#" tal:attributes="href string:${qs/klass}?${qs/url}&@dispname=${qs/name}"
1873 + <a href="#" tal:attributes="href string:${qs/klass}?${qs/url}&@dispname=${qs/name/url_quote}" 3315 + <a href="#" tal:attributes="href string:${qs/klass}?${qs/url}&@dispname=${qs/name/url_quote}"
1874 tal:content="qs/name">link</a><br> 3316 tal:content="qs/name">link</a><br>
1875 </tal:block> 3317 </tal:block>
1876 3318
1877 Find the tal:repeat line that loops over all queries. Then 3319 Find the tal:repeat line that loops over all queries. Then
1878 change the value assigned to @dispname in the href attribute from 3320 change the value assigned to @dispname in the href attribute from
1879 ${qs/name} to ${qs/name/url_quote}. Note that you should *not* change 3321 ${qs/name} to ${qs/name/url_quote}. Note that you should *not* change
1993 3435
1994 If you haven't modified you query.item.html template, simply copy the 3436 If you haven't modified you query.item.html template, simply copy the
1995 query.item.html template from one of the above default templates to 3437 query.item.html template from one of the above default templates to
1996 your tracker's html directory. 3438 your tracker's html directory.
1997 3439
1998 Enhancement to check command for Permissions 3440 Enhancement to check command for Permissions (optional)
1999 -------------------------------------------- 3441 -------------------------------------------------------
2000
2001 A new form of check function is permitted in permission definitions. 3442 A new form of check function is permitted in permission definitions.
2002 The three argument form is still supported and will work the same 3443 An example check function is ``own_record(db, userid, itemid)`` in the
2003 as it always has (although it may be depricated in the future). 3444 file schema.py. The three argument form is still supported and will
3445 work the same as it always has (although it may be depricated in the
3446 future).
2004 3447
2005 If the check function is defined as:: 3448 If the check function is defined as::
2006 3449
2007 check(db, userid, itemid, **ctx) 3450 check(db, userid, itemid, **ctx)
2008 3451
2019 3462
2020 This should make defining complex permissions much easier. Consider:: 3463 This should make defining complex permissions much easier. Consider::
2021 3464
2022 def issue_private_access(db, userid, itemid, **ctx): 3465 def issue_private_access(db, userid, itemid, **ctx):
2023 if not db.issue.get(itemid, 'private'): 3466 if not db.issue.get(itemid, 'private'):
2024 # allow access to everything if not private 3467 # allow access to everything if not private
2025 return True 3468 return True
2026 3469
2027 # It is a private issue hide nosy list 3470 # It is a private issue hide nosy list
2028 # Note that the nosy property *must* be listed 3471 # Note that the nosy property *must* be listed
2029 # in permissions argument to the addPermission 3472 # in permissions argument to the addPermission
2030 # definition otherwise this check command 3473 # definition otherwise this check command
2031 # is not run. 3474 # is not run.
2032 if ctx['property'] == 'nosy': 3475 if ctx['property'] == 'nosy':
2033 return False # deny access to this property 3476 return False # deny access to this property
2034 3477
2035 # allow access for editing, viewing etc. of the class 3478 # allow access for editing, viewing etc. of the class
2036 return True 3479 return True
2037 3480
2038 3481
2039 e = db.security.addPermission(name='Edit', klass='issue', 3482 e = db.security.addPermission(name='Edit', klass='issue',
2040 check=issue_private_access, 3483 check=issue_private_access,
2041 properties=['nosy'], 3484 properties=['nosy'],
2042 description="Edit issue checks") 3485 description="Edit issue checks")
2043 3486
2044 It is suggested that you change your checks to use the ``**ctx`` 3487 It is suggested that you change your checks to use the ``**ctx``
2045 parameter. This is expected to be the preferred form in the future. 3488 parameter. This is expected to be the preferred form in the future.
2046 You do not need to use the ``ctx`` parameter in the function if you do 3489 You do not need to use the ``ctx`` parameter in the function if you do
2047 not need it. 3490 not need it.
2048 3491
3492 If the new four argument form is required in the future, there will be
3493 required (not optional) directions on upgrading your schema.
3494
2049 Changes to property permissions 3495 Changes to property permissions
2050 ------------------------------- 3496 -------------------------------
2051 3497
2052 If you create a permission: 3498 If you create a permission::
2053 3499
2054 db.security.addPermission(name='View', klass='user', 3500 db.security.addPermission(name='View', klass='user',
2055 properties=['theme'], check=own_record, 3501 properties=['theme'], check=own_record,
2056 description="User is allowed to view their own theme") 3502 description="User is allowed to view their own theme")
2057 3503
2074 page when the search is triggered. This is usually correct since the 3520 page when the search is triggered. This is usually correct since the
2075 user expects to see the results of the query. But now that 3521 user expects to see the results of the query. But now that
2076 the code properly checks for duplicate search names, the user should 3522 the code properly checks for duplicate search names, the user should
2077 stay on the search page if there is an error. To add this to your 3523 stay on the search page if there is an error. To add this to your
2078 existing issue.search.html page, add the following line after the 3524 existing issue.search.html page, add the following line after the
2079 hidden field @old-queryname: 3525 hidden field ``@old-queryname``::
2080 3526
2081 <input type="hidden" name="@template" value="index|search"/> 3527 <input type="hidden" name="@template" value="index|search"/>
2082 3528
2083 With this addition, the index template is displayed if there is no 3529 With this addition, the index template is displayed if there is no
2084 error, and the user stays on the search template if there is an error. 3530 error, and the user stays on the search template if there is an error.
2185 ============================= 3631 =============================
2186 3632
2187 See the `historical migration <upgrading-history.html>`_ document. 3633 See the `historical migration <upgrading-history.html>`_ document.
2188 3634
2189 .. _`security documentation`: security-history.html 3635 .. _`security documentation`: security-history.html
3636 .. _`Roundup postgresql documentation`: postgresql.html
2190 .. _`administration guide`: admin_guide.html 3637 .. _`administration guide`: admin_guide.html
2191 .. _`xmlrpc guide`: xmlrpc.html 3638 .. _`xmlrpc guide`: xmlrpc.html
2192 .. _FTS5 full-text search engine: https://www.sqlite.org/fts5.html 3639 .. _FTS5 full-text search engine: https://www.sqlite.org/fts5.html
2193 .. _PostgreSQL's full text search: https://www.postgresql.org/docs/current/textsearch.html 3640 .. _PostgreSQL's full text search: https://www.postgresql.org/docs/current/textsearch.html
2194 .. _`administration guide notes on native-fts`: admin_guide.html#configuring-native-fts-full-text-search 3641 .. _`administration guide notes on native-fts`: admin_guide.html#configuring-native-fts-full-text-search
2195 .. _Configuring Compression: admin_guide.html#configuring-compression 3642 .. _Configuring Compression: admin_guide.html#configuring-compression
3643 .. _classhelper documentation: admin_guide.html#classhelper-web-component
2196 .. _Software Upgrade: admin_guide.html#software-upgrade 3644 .. _Software Upgrade: admin_guide.html#software-upgrade
2197 .. _new search permissions for query in 1.4.17: 3645 .. _new search permissions for query in 1.4.17:
2198 upgrading-history.html#new-search-permissions-for-query-in-1-4-17 3646 upgrading-history.html#new-search-permissions-for-query-in-1-4-17

Roundup Issue Tracker: http://roundup-tracker.org/