comparison doc/admin_guide.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
221 ``-----END PRIVATE KEY-----`` and 221 ``-----END PRIVATE KEY-----`` and
222 ``-----BEGIN CERTIFICATE-----``, 222 ``-----BEGIN CERTIFICATE-----``,
223 ``-----END CERTIFICATE-----``. 223 ``-----END CERTIFICATE-----``.
224 If not specified, roundup will generate a temporary, self-signed certificate 224 If not specified, roundup will generate a temporary, self-signed certificate
225 for use. 225 for use.
226 **loghttpvialogger** section
227 If you:
228
229 * have **loghttpvialogger** enabled
230 * use **pidfile**
231 * use a logging config file in the tracker's config.ini
232
233 it is essential to specify absolute paths for log files in the
234 tracker's logging.config file. The use of pidfile causes the
235 server to switch to the root directory ('/'). As a result
236 relative paths in the logging ini configuration file (as
237 opposed to the tracker's config.ini) will be written to the
238 system's root directory. The access error will cause the server
239 to exit.
226 **trackers** section 240 **trackers** section
227 Each line denotes a mapping from a URL component to a tracker home. 241 Each line denotes a mapping from a URL component to a tracker home.
228 Make sure the name part doesn't include any url-unsafe characters like 242 Make sure the name part doesn't include any url-unsafe characters like
229 spaces. Stick to alphanumeric characters and you'll be ok. 243 spaces. Stick to alphanumeric characters and you'll be ok.
230 244
241 existing config.ini. Running this in a tracker home directory will 255 existing config.ini. Running this in a tracker home directory will
242 move the exsiting config.ini to config.bak and replace it with the 256 move the exsiting config.ini to config.bak and replace it with the
243 roundup-server's config.ini. This will make the tracker in the 257 roundup-server's config.ini. This will make the tracker in the
244 directory fail to start util the original config.ini is restored. 258 directory fail to start util the original config.ini is restored.
245 259
260 .. _configuring-compression:
261
246 Configuring Compression 262 Configuring Compression
247 ======================= 263 =======================
248 264
249 Roundup will compress HTTP responses to clients on the fly. Dynamic, 265 Roundup will compress HTTP responses to clients on the fly. Dynamic,
250 on the fly, compression is enabled by default, to disable it set:: 266 on the fly, compression is enabled by default, to disable it set::
256 in the tracker's ``config.ini``. You should disable compression if 272 in the tracker's ``config.ini``. You should disable compression if
257 your proxy (e.g. nginx or apache) or wsgi server (uwsgi) is configured 273 your proxy (e.g. nginx or apache) or wsgi server (uwsgi) is configured
258 to compress responses on the fly. The python standard library includes 274 to compress responses on the fly. The python standard library includes
259 gzip support. For brotli or zstd you will need to install packages. See 275 gzip support. For brotli or zstd you will need to install packages. See
260 the `installation documentation`_ for details. 276 the `installation documentation`_ for details.
277
278 .. index:: single: interfaces.py; configuring http compression
261 279
262 Some assets will not be compressed on the fly. Assets with mime types 280 Some assets will not be compressed on the fly. Assets with mime types
263 of "image/png" or "image/jpeg" will not be compressed. You 281 of "image/png" or "image/jpeg" will not be compressed. You
264 can add mime types to the list by using ``interfaces.py`` as discussed 282 can add mime types to the list by using ``interfaces.py`` as discussed
265 in the `customisation documentation`_. As an example adding:: 283 in the `customisation documentation`_. As an example adding::
317 files, the data will be compressed dynamically (on the fly) using 335 files, the data will be compressed dynamically (on the fly) using
318 brotli. If there is a precompressed gzip file present the client will 336 brotli. If there is a precompressed gzip file present the client will
319 get the gzip version and not a brotli compressed version. This 337 get the gzip version and not a brotli compressed version. This
320 mechanism allows the admin to allow use of brotli and zstd for 338 mechanism allows the admin to allow use of brotli and zstd for
321 dynamic content, but not for static content. 339 dynamic content, but not for static content.
340
341 .. _browser_handling_attached_files:
342
343 .. index:: single: interfaces.py; Controlling browser handling of attached files
344
345 Controlling Browser Handling of Attached Files
346 ==============================================
347
348 You may be aware of the ``allow_html_file`` `config.ini setting
349 <reference.html#config-ini-section-web>`_. When set to yes, it permits
350 html files to be attached and displayed in the browser as html
351 files. The underlying mechanism used to enable/disable attaching HTML
352 is exposed using ``interfaces.py``.
353
354 Similar to ``Client.precompressed_mime_types`` above, there is a
355 ``Client.mime_type_allowlist``. If a mime type is present in this
356 list, an attachment with this mime type is served to the browser. If
357 the mime type is not present, the mime type is set to
358 ``application/octet-stream`` which causes the browser to download the
359 attachment to a file.
360
361 In release 2.4.0, the mime type ``application/pdf`` was removed from
362 the precompressed_mime_types list. This prevents the browser from
363 executing scripts that may be included in the PDF file. If you trust
364 the individuals uploading PDF files to your tracker and wish to allow
365 viewing PDF files from your tracker, you can do so by editing your
366 tracker's "interfaces.py" file. Adding::
367
368 from roundup.cgi.client import Client
369 Client.mime_type_allowlist.append('application/pdf')
370
371 will permit the PDF files to be viewed in the browser rather than
372 downloaded to a file.
373
374 Similarly, you can remove a mime type (e.g. audio/oog) using::
375
376 from roundup.cgi.client import Client
377 Client.mime_type_allowlist.remove('audio/oog')
378
379 which will force the browser to save the attachment to a file rather
380 than playing the audio file.
381
382 .. index:: single: interfaces.py; setting REST maximum result limit
383
384 Configuring REST Maximum Result Limit
385 =====================================
386
387 To prevent denial of service (DOS) and limit user wait time for an
388 unbounded request, the REST endpoint has a maximum limit on the number
389 of rows that can be returned. By default, this is set to 10 million.
390 This setting applies to all users of the REST interface. If you want
391 to change this limit, you can add the following code to the
392 ``interfaces.py`` file in your tracker::
393
394 # change max response rows
395 from roundup.rest import RestfulInstance
396 RestfulInstance.max_response_row_size = 26
397
398 This code will set the maximum number of rows to 25 (one less than the
399 value). Note that this setting is rarely used and is not available in
400 the tracker's ``config.ini`` file. Setting it through this mechanism
401 allows you to enter a string or number that may break Roundup, such as
402 "asdf" or 0. In general, it is recommended to keep the limit at its
403 default value. However, this option is available for cases when a
404 request requires more than 10 million rows and pagination using
405 ``@page_index`` and ``@page_size=9999999`` is not possible.
322 406
323 Adding a Web Content Security Policy (CSP) 407 Adding a Web Content Security Policy (CSP)
324 ========================================== 408 ==========================================
325 409
326 A Content Security Policy (`CSP`_) adds a layer of security to 410 A Content Security Policy (`CSP`_) adds a layer of security to
370 interface. These changes are also trusted code that will be run 454 interface. These changes are also trusted code that will be run
371 when invoked. 455 when invoked.
372 456
373 More secure CSPs can also be created. However because of the ability 457 More secure CSPs can also be created. However because of the ability
374 to customise the web interface, it is difficult to provide guidance. 458 to customise the web interface, it is difficult to provide guidance.
459
460 .. _dynamic_csp:
375 461
376 Dynamic CSP 462 Dynamic CSP
377 ----------- 463 -----------
378 464
379 Roundup creates a cryptographic nonce for every client request. The 465 Roundup creates a cryptographic nonce for every client request. The
397 "object-src 'self' 'nonce-{nonce}'; " 483 "object-src 'self' 'nonce-{nonce}'; "
398 ), 484 ),
399 } 485 }
400 486
401 487
402 def AddHtmlHeaders(client, header_dict=None): 488 def AddHtmlHeaders(self, header_dict=None):
403 ''' Generate https headers from dict use default security headers 489 ''' Generate https headers from dict use default security headers
404 490
405 Setting the header with a value of None will not inject the 491 Setting the header with a value of None will not inject the
406 header and can override the default set. 492 header and can override the default set.
407 493
408 Header values will be formatted with a dictionary including a 494 Header values will be formatted with a dictionary including a
409 nonce. Use to set a nonce for inline scripts. 495 nonce. Use to set a nonce for inline scripts.
496
497 self is an instance of the TemplatingUtilities class, so
498 you have access to self.client as well as any functions added
499 using registerUtil.
410 ''' 500 '''
411 try: 501 try:
412 if client.client_nonce is None: 502 if self.client.client_nonce is None:
413 # logger.warning("client_nonce is None") 503 # logger.warning("client_nonce is None")
414 client.client_nonce = client.session_api._gen_sid() 504 self.client.client_nonce = self.client.session_api._gen_sid()
415 except AttributeError: 505 except AttributeError:
416 # client.client_nonce doesn't exist, create it 506 # self.client.client_nonce doesn't exist, create it
417 # logger.warning("client_nonce does not exist, creating") 507 # logger.warning("client_nonce does not exist, creating")
418 client.client_nonce = client.session_api._gen_sid() 508 self.client.client_nonce = client.session_api._gen_sid()
419 509
420 headers = default_security_headers.copy() 510 headers = default_security_headers.copy()
421 if isinstance(header_dict, dict): 511 if isinstance(header_dict, dict):
422 headers.update(header_dict) 512 headers.update(header_dict)
423 513
424 client_headers = client.additional_headers 514 client_headers = self.client.additional_headers
425 515
426 for header, value in list(headers.items()): 516 for header, value in list(headers.items()):
427 if value is None: 517 if value is None:
428 continue 518 continue
429 client_headers[header] = value.format( 519 client_headers[header] = value.format(
430 nonce=client.client_nonce) 520 nonce=self.client.client_nonce)
431 521
432 def init(instance): 522 def init(instance):
433 instance.registerUtil('AddHtmlHeaders', AddHtmlHeaders) 523 # Note the use of the new (in version 2.5) registerUtilMethod
524 instance.registerUtilMethod('AddHtmlHeaders', AddHtmlHeaders)
434 525
435 526
436 Adding the following to ``page.html`` right after the opening 527 Adding the following to ``page.html`` right after the opening
437 ``<html....`>`` tag:: 528 ``<html....`>`` tag::
438 529
439 <tal:code tal:content="python:utils.AddHtmlHeaders(request.client)" /> 530 <tal:code tal:content="python:utils.AddHtmlHeaders()" />
440 531
441 will invoke ``AddHtmlHeaders()`` to add the CSP header with the nonce. 532 will invoke ``AddHtmlHeaders()`` to add the CSP header with the nonce.
442 533
443 With this set of CSP headers, all style, script and object tags will 534 With this set of CSP headers, all style, script and object tags will
444 need a ``nonce`` attribute. This can be added by changing:: 535 need a ``nonce`` attribute. This can be added by changing::
450 <script 541 <script
451 tal:attributes="nonce request/client/client_nonce" 542 tal:attributes="nonce request/client/client_nonce"
452 src="javascript.js"></script> 543 src="javascript.js"></script>
453 544
454 for each script, object or style tag. 545 for each script, object or style tag.
546
547 If you are using a version of Roundup before version 2.5, you need to
548 replace ``instance.registerUtilMethod`` with
549 ``instance.registerUtil``. For example::
550
551 def init(instance):
552 instance.registerUtil('AddHtmlHeaders', AddHtmlHeaders)
553
554 The AddHtmlHeaders function needs to be changed so that ``self.client``
555 is replaced by ``client``::
556
557 # replace self parameter with client
558 def AddHtmlHeaders(client, header_dict=None):
559 ''' Generate https headers from dict use default security headers
560
561 Setting the header with a value of None will not inject the
562 header and can override the default set.
563
564 Header values will be formatted with a dictionary including a
565 nonce. Use to set a nonce for inline scripts.
566 '''
567
568 ### Then change all references to self.client to client
569
570 try:
571 if client.client_nonce is None: # note self.client -> client
572 # logger.warning("client_nonce is None")
573 client.client_nonce = self.client.session_api._gen_sid()
574
575 ...
576
577 Lastly the client must be passed explicitly when calling
578 AddHtmlHeaders. The call looks like::
579
580 <tal:code tal:content="python:utils.AddHtmlHeaders(request.client)" />
581
455 582
456 Remediating ``unsafe-inline`` 583 Remediating ``unsafe-inline``
457 ----------------------------- 584 -----------------------------
458 .. _remediating unsafe-inline: 585 .. _remediating unsafe-inline:
459 586
485 the trusted function in base_javascript to replace the ignored ``onX`` 612 the trusted function in base_javascript to replace the ignored ``onX``
486 handlers. 613 handlers.
487 614
488 .. _CSP: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP 615 .. _CSP: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
489 616
617 Classhelper Web Component
618 =========================
619
620 Version 2.4.0 provides a new classhelper popup written as a web
621 component. By installing 3 files and editing the tracker's templates
622 you can enable the new component.
623
624 The `development of this component was done by team-03
625 <https://github.com/UMB-CS-682-Team-03/tracker>`_ of the
626 Spring 2024 CS682 graduate software engineering SDL capstone
627 class at the University of Massachusetts - Boston. Their
628 documentation is copied/adapted below.
629
630 File Installation
631 -----------------
632
633 There are three files to install in your tracker. You can
634 copy them from the template directory for the classic
635 tracker. The location of the template file can be obtained
636 by running: ``roundup-admin templates`` and looking for the
637 path value of the classic template. If the path value is
638 ``/path/to/template``, copy::
639
640 /path/to/template/html/classhelper.js
641 /path/to/template/html/classhelper.css
642 /path/to/template/html/_generic.translation
643
644 to your tracker's html directory.
645
646 Wrapping the Classic Classhelper
647 --------------------------------
648
649 To allow your users to select items in the web interface
650 using the new classhelper, you should edit the template files
651 in the ``html/`` subdirectory of your tracker. Where you see
652 code like::
653
654 <th i18n:translate="">Superseder</th>
655 <td>
656 <span tal:replace="structure
657 python:context.superseder.field(showid=1,size=20)" />
658 <span tal:condition="context/is_edit_ok"
659 tal:replace="structure
660 python:db.issue.classhelp('id,title',
661 property='superseder', pagesize=100)" />
662 [...]
663 </td>
664
665 change it to wrap the classhelp span like this::
666
667 <th i18n:translate="">Superseder</th>
668 <td>
669 <span tal:replace="structure
670 python:context.superseder.field(showid=1,size=20)" />
671 <roundup-classhelper
672 data-popup-title="Superseder Classhelper - {itemDesignator}"
673 data-search-with="title,status,keyword[]-name">
674 <span tal:condition="context/is_edit_ok"
675 tal:replace="structure
676 python:db.issue.classhelp('id,title',
677 property='superseder', pagesize=100)" />
678 </roundup-classhelper>
679 [...]
680 </td>
681
682 which displays a three part classhelper.
683
684 1. the search pane includes a text search box for the `title`
685 and `status` properties and a dropdown for the keyword property,
686 sorted by name in descending order.
687 2. the selection pane will show 100 search results per page.
688 It also allows the user to move to the next or previous result
689 page.
690 3. the accumulator at the bottom shows all the selected items. It
691 also has buttons to accept the items or cancel the
692 classhelper, leaving the original page unchanged.
693
694 Note that the user class is a little different because users without
695 an Admin role can't search for a user by Role. So we hide the Role
696 search element for non admin users. Starting with::
697
698 <th i18n:translate="">Nosy List</th>
699 <td>
700 <span tal:replace="structure context/nosy/field" />
701 <span tal:condition="context/is_edit_ok" tal:replace="structure
702 python:db.user.classhelp('username,realname,address',
703 property='nosy', width='600'" />
704 </td>
705
706 wrap the classhelp span with ``<roundup-classhelper>`` like::
707
708 <th i18n:translate="">Nosy List</th>
709 <td>
710 <span tal:replace="structure context/nosy/field" />
711 <roundup-classhelper tal:define="search string:name,phone,roles[]"
712 tal:attributes="data-search-with python:search
713 if request.user.hasRole('Admin') else
714 ','.join(search.split(',')[:-1])">
715 <span tal:condition="context/is_edit_ok" tal:replace="structure
716 python:db.user.classhelp('username,realname,address',
717 property='nosy', width='600'" />
718 </roundup-classhelper>
719 </td>
720
721 The ``','.join(search.split(',')[:-1])`` removes the last element of
722 the search string (``roles[]``) if the user does not have the Admin
723 role.
724
725 Loading the <roundup-classhelper> Script
726 ----------------------------------------
727
728 To make the ``<roundup-classhelper>`` wrappers work, you
729 have to load the classhelper.js script. Add the following
730 html script tag in the head section of page.html::
731
732 <script type="text/javascript" src="@@file/classhelper.js">
733 </script>
734
735 You can place it anywhere before ``</head>``. This will make
736 it available on all pages.
737
738 The script will also work if it is loaded at the end of the
739 body. It can also be added to the ``more-javascript`` slot
740 in one of the templates (see ``user.item.html`` for an
741 example) if you don't want the overhead of loading the script
742 on every page.
743
744 You may want to minimize and precompress the file. Using
745 dynamic compression, the file is 10k when compressed with
746 gzip (8k with brotli). If you minimize the file first with
747 `rjsmin <https://pypi.org/project/rjsmin/>`_ and then
748 compress it, it's about 6k. See the information about using
749 precompressed files in the :ref:`section on compression
750 <configuring-compression>`.
751
752 <roundup-classhelper> configuration
753 -----------------------------------
754
755 There are two attributes used to configure the classhelper.
756
757 data-popup-title:
758 * this attribute is optional. A reasonable default is
759 provided if it is missing.
760 * Adding ``data-popup-title`` changes the title of the popup
761 window with the value of the attribute.
762 * ``{itemDesignator}`` can be used inside the attribute value
763 to replace it with the current classhelper usage context.
764 E.G. ``data-popup-title="Nosy List Classhelper - {itemDesignator}"``
765 will display the popup window title as ``Nosy List Classhelper - issue24``
766
767 data-search-with:
768 * this attribute is optional. If it is not set, a search
769 panel is not created to allow the user to search within
770 the class.
771 * Adding ``data-search-with`` specifies the fields that can
772 be used for searching. For example when invoking the
773 classhelper for the issue class, using
774 ``data-search-with="title,status,keyword"`` wil enable
775 three search fields.
776 * The search can be customized using the following syntax:
777
778 * Adding ``[]`` at then end of a field (``"status[]"``)
779 will displays a dropdown for the "status" field
780 listing all the values the user can access. E.G.::
781
782 <roundup-classhelper
783 data-search-with="title,status[],keyword[]">
784 <span tal:condition="context/is_edit_ok"
785 tal:replace="structure
786 python:db.issue.classhelp('id,title',
787 property='superseder', pagesize=100)" />
788 </roundup-classhelper>
789
790 will create a search pane with a text search for title
791 and dropdowns for status and keyword.
792
793 * Adding a sort key after the ``[]`` allows you to
794 select the order of the elements in the dropdown. For
795 example ``keyword[]+name`` sorts the keyword
796 dropdown in ascending order by name. While
797 ``keyword[]-name`` sorts the keyword dropdown in
798 descending order by name. If the sort order is not
799 specified, the default order for the class is used.
800
801 <roundup-classhelper> styling
802 -----------------------------
803
804 The roundup-classhelper component uses minimal styling so it
805 can blend in with most trackers. If you want to change the
806 styling, you can modify the classhelper.css file in the html
807 directory. Even though roundup-classhelper is a web
808 component, it doesn't use the shadow DOM. If you don't know
809 what this means, it just means that it's easy to style.
810
811 Getting the web component to load changes to the css file is
812 a bit tricky. The browser caches the old file and you have
813 to resort to tricks to make it get a new copy of the file.
814
815 One way to do this is to open to the ``classhelper.css``
816 file in your browser and force refresh it. To do this:
817
818 1. Open the home page for your Roundup issue tracker in a
819 web browser.
820
821 2. In the address bar, append ``@@file/classhelper.css``
822 to the end of your Roundup URL. For example, if your
823 Roundup URL is ``https://example.com/tracker/``, the
824 URL you should visit would be
825 ``https://example.com/tracker/@@file/classhelper.css``.
826
827 3. This will open the ``classhelper.css`` file in your browser.
828
829 4. Press ``Ctrl+Shift+R`` (on Windows and Linux) or
830 ``Cmd+Shift+R`` (on macOS). This triggers a hard
831 refresh of the page, which forces the browser to
832 reload the file and associated resources from the
833 server.
834
835 This should resolve any issues caused by cached or outdated
836 files. It is possible that you have to open devtools and set
837 the disable cache option in the network panel in extreme
838 cases.
839
840 Also during development, you might want to `set a very low
841 cache time
842 <customizing.html#changing-cache-control-headers>`_ for
843 classhelper.css using something like::
844
845 Client.Cache_Control['classhelper.css'] = "public, max-age=10"
846
847
848 Translations
849 ------------
850
851 To set up translations for the <roundup-classhelper>
852 component, follow these steps.
853
854 1. Create a ``messages.pot`` file by running
855 ``roundup-gettext <tracker_home_directory>``. This
856 creates ``locale/messages.pot`` in your tracker's home
857 directory. It extracts all translatable strings from
858 your tracker. We will use it as a base template for the
859 new strings you want to translate.
860 2. See if you already have a ``.po`` translation file for
861 your language in the tracker's locale/ directory. If you
862 don't, copy ``messages.pot`` to a .po file for the
863 language you want to translate. For example German
864 would be at ``de.po`` English would be at ``en.po``
865 (for example if you want to change the ``apply`` button
866 to say ``Do It``.
867
868 3. Edit the new .po file. After the header, add the
869 translation entries for the <roundup-classhelper>
870 component. For example `next` and `submit` are
871 displayed in English when the rest of the interface is
872 in German. Add::
873
874 msgid "submit"
875 msgstr "gehen"
876
877 msgid "next"
878 msgstr "nächste"
879
880 msgid "name"
881 msgstr "name"
882
883 Note: the value for `msgid` is case sensitive. You can
884 see the msgid for static strings by looking for
885 ``CLASSHELPER_TRANSLATION_KEYWORDS`` in classhelper.js.
886
887 4. Save the .po file.
888
889 5. Restart your Roundup instance.
890
891 This should display the missing translations, for more
892 details refer to the `translation (i18n) section of the
893 developers documentation
894 <developers.html#extracting-translatable-messages>`_.
895
896 The default title used for read only popups can be changed by using
897 the translation mechanism. Use the following::
898
899 msgid "Info on {className} - {itemDesignator} - Classhelper"
900 msgstr "{itemDesignator} - info on {className}"
901
902 in ``en.po`` to reformat the title for the English language. Note that
903 ``{classname}`` is only supported in the default title.
904
905 In addition to the default template you can translate a title set
906 using ``data-popup-title`` by matching the template as the msgid.
907 Using an example above::
908
909 msgid "Nosy List Classhelper - {itemDesignator}"
910 msgstr "Nosy List Klassenhelfer - {itemDesignator}"
911
912 placed in ``de.po`` will translate the title into German.
913
914 Troubleshooting
915 ---------------
916
917 The roundup-classhelper will fallback to using the classic
918 classhelper if:
919
920 * the user doesn't have REST access
921 * the browser doesn't support web components
922
923 It will display an alert modal dialog to the user before triggering
924 the classic classhelper as a fallback. A detailed error will be
925 printed to the browser console. The console is visible in devtools and
926 can be opened by pressing the ``F12`` key.
927
928 You can disable the classhelper on a per URL basis by adding
929 ``#classhelper-wc-toggle`` to the end of the URL. This will prevent
930 the web component from starting up.
931
932 Also you can set ``DISABLE_CLASSHELP = true`` at the top of
933 classhelper.js to disable the classhelper without having to make any
934 changes to your templates.
935
936 Advanced Configuration
937 ----------------------
938
939 The classhelper.js file has a few tweakable options for use
940 by advanced users. The endpoint for the roles list requires
941 the user to have Admin rights. You can add your own roles
942 endpoint with a different authorization mechanism. The
943 following code can be added to your tracker's interfaces.py.
944 You can create this file if it doesn't exist. This code
945 creates a new REST endpoint at ``/rest/roles``::
946
947 from roundup.rest import Routing, RestfulInstance, _data_decorator
948
949 class RestfulInstance:
950
951 @Routing.route("/roles", 'GET')
952 @_data_decorator
953 def get_roles(self, input):
954 """Return all defined roles. The User class property
955 roles is a string but simulate it as a MultiLink
956 to an actual Roles class.
957 """
958 return 200, {"collection":
959 [{"id": rolename,"name": rolename}
960 for rolename in list(self.db.security.role.keys())]}
961
962
963 See the `REST documentation <rest.html>`_ for details on
964 using ``interfaces.py`` to add new REST endpoints.
965
966 The code above allows any user with REST access to see all
967 the roles defined in the tracker.
968
969 To make classhelper.js use this new endpoint, look for::
970
971
972 const ALTERNATIVE_DROPDOWN_PATHNAMES = {
973 "roles": "/rest/data/user/roles"
974 }
975
976 and change it to::
977
978 const ALTERNATIVE_DROPDOWN_PATHNAMES = {
979 "roles": "/rest/roles"
980 }
981
982 Users may have to perform a hard reload to cache this change
983 on their system.
984
490 Configuring native-fts Full Text Search 985 Configuring native-fts Full Text Search
491 ======================================= 986 =======================================
492 987
493 Roundup release 2.2.0 supports database-native full text search. 988 Roundup release 2.2.0 supports database-native full text search.
494 SQLite (minimum version 3.9.0) with FTS5 and PostgreSQL (minimum 989 SQLite (minimum version 3.9.0) with FTS5 and PostgreSQL (minimum
553 `Parsing Queries`_ under websearch_to_tsquery. This is the default. 1048 `Parsing Queries`_ under websearch_to_tsquery. This is the default.
554 1049
555 2. tsquery - described at the beginning of `Parsing Queries`_ with 1050 2. tsquery - described at the beginning of `Parsing Queries`_ with
556 to_tsquery. It is enabled by starting the search phrase with ``ts:``. 1051 to_tsquery. It is enabled by starting the search phrase with ``ts:``.
557 1052
558 .. _Parsing Queries: \ 1053 .. _Parsing Queries:
559 https://www.postgresql.org/docs/14/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES 1054 https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES
560 1055
561 Websearch provides a more natural style of search and supports: 1056 Websearch provides a more natural style of search and supports:
562 1057
563 * plain word search (stemmed in most cases) 1058 * plain word search (stemmed in most cases)
564 * phrase search with terms enclosed in quotes (``"``) 1059 * phrase search with terms enclosed in quotes (``"``)
600 requires reindexing. 1095 requires reindexing.
601 1096
602 The `configuration list can be obtained using using psql's`_ 1097 The `configuration list can be obtained using using psql's`_
603 ``\dF`` command. 1098 ``\dF`` command.
604 1099
605 .. _configuration list can be obtained using using psql's: \ 1100 .. _configuration list can be obtained using using psql's:
606 https://www.postgresql.org/docs/current/textsearch-psql.html 1101 https://www.postgresql.org/docs/current/textsearch-psql.html
607 1102
608 Roundup includes a hardcoded list for all languages supported by 1103 Roundup includes a hardcoded list for all languages supported by
609 PostgreSQL 14.1. The list includes 5 custom "languages" 1104 PostgreSQL 14.1. The list includes 5 custom "languages"
610 ``custom1`` ... ``custom5`` to allow you to set up your `own textsearch 1105 ``custom1`` ... ``custom5`` to allow you to set up your `own textsearch
611 configuration`_ using one of the custom names. Depending on your 1106 configuration`_ using one of the custom names. Depending on your
612 PostgreSQL version, we may allow an invalid language to be configured. 1107 PostgreSQL version, we may allow an invalid language to be configured.
613 You will see an error about ``text search configuration ... does not 1108 You will see an error about ``text search configuration ... does not
614 exist``. 1109 exist``.
615 1110
616 .. _own textsearch configuration: \ 1111 .. _own textsearch configuration:
617 https://www.postgresql.org/docs/14/textsearch-configuration.html 1112 https://www.postgresql.org/docs/current/textsearch-configuration.html
618 1113
619 It may be possible to append to this list using the tracker's 1114 It may be possible to append to this list using the tracker's
620 interfaces.py. For details, see ``test/test_indexer.py`` in the 1115 interfaces.py. For details, see ``test/test_indexer.py`` in the
621 roundup distribution and search for ``valid_langs``. If you succeed 1116 roundup distribution and search for ``valid_langs``. If you succeed
622 please email roundup-users AT lists.sourceforge.net with a description 1117 please email roundup-users AT lists.sourceforge.net with a description
688 sqlite databases for storing the session and otk data. 1183 sqlite databases for storing the session and otk data.
689 1184
690 The following table shows which primary databases support 1185 The following table shows which primary databases support
691 different session database backends: 1186 different session database backends:
692 1187
693 .. table:: D - default if unconfigured, X - compatible choice 1188 .. table:: D - default if unconfigured, + - compatible choice
694 :class: captionbelow 1189 :class: captionbelow
695 1190
696 +---------------+--------+--------+-------+-------+------------+ 1191 +---------------+--------+--------+-------+-------+------------+
697 | | session db | 1192 | | session db |
698 +---------------+--------+--------+-------+-------+------------+ 1193 +---------------+--------+--------+-------+-------+------------+
699 |primary db | anydbm | sqlite | redis | mysql | postgresql | 1194 |primary db | anydbm | sqlite | redis | mysql | postgresql |
700 +===============+========+========+=======+=======+============+ 1195 +===============+========+========+=======+=======+============+
701 |anydbm | D | | X | | | 1196 |anydbm | D | | \+ | | |
702 +---------------+--------+--------+-------+-------+------------+ 1197 +---------------+--------+--------+-------+-------+------------+
703 |sqlite | X | D | X | | | 1198 |sqlite | \+ | D | \+ | | |
704 +---------------+--------+--------+-------+-------+------------+ 1199 +---------------+--------+--------+-------+-------+------------+
705 |mysql | | | | D | | 1200 |mysql | | | | D | |
706 +---------------+--------+--------+-------+-------+------------+ 1201 +---------------+--------+--------+-------+-------+------------+
707 |postgresql | | | | | D | 1202 |postgresql | | | | | D |
708 +---------------+--------+--------+-------+-------+------------+ 1203 +---------------+--------+--------+-------+-------+------------+
749 where you specify the file that can be used to validate the 1244 where you specify the file that can be used to validate the
750 SSL certificate. `Securing Redis`_ has more details. 1245 SSL certificate. `Securing Redis`_ has more details.
751 1246
752 .. _Redis: https://redis.io 1247 .. _Redis: https://redis.io
753 .. _redis-py: https://pypi.org/project/redis/ 1248 .. _redis-py: https://pypi.org/project/redis/
754 .. _Securing Redis: https://redis.io/docs/manual/security/ 1249 .. _Securing Redis: https://redis.io/docs/latest/operate/oss_and_stack/management/security/
755 1250
756 1251
757 Users and Security 1252 Users and Security
758 ================== 1253 ==================
759 1254
912 pip3 install pytest 1407 pip3 install pytest
913 python3 -m pytest test/ 1408 python3 -m pytest test/
914 1409
915 2. If you're using an RDBMS backend, make a backup of its contents now. 1410 2. If you're using an RDBMS backend, make a backup of its contents now.
916 3. Make a backup of the tracker home itself. 1411 3. Make a backup of the tracker home itself.
917 4. Stop the tracker web and email frontends. 1412 4. Stop the tracker web, email frontends and any scheduled
918 5. Install the new version of the software:: 1413 (cron) jobs that access the tracker.
919 1414 5. Install the new version of the software in a new virtual
920 python setup.py install 1415 environment::
1416
1417 python3 -m venv /path/to/env
1418 . /path/to/env/bin/activate
1419 python3 pip install roundup
921 1420
922 6. Follow the steps in the `upgrading documentation`_ for all the 1421 6. Follow the steps in the `upgrading documentation`_ for all the
923 versions between your original version and the new version. 1422 versions between your original version and the new version.
924 1423
925 Usually you should run `roundup_admin -i <tracker_home> migrate` 1424 Usually you should run `roundup_admin -i <tracker_home> migrate`
1228 single: roundup-admin; usage 1727 single: roundup-admin; usage
1229 single: roundup-admin; data formats 1728 single: roundup-admin; data formats
1230 single: roundup-admin; man page reference 1729 single: roundup-admin; man page reference
1231 pair: roundup-admin; designator 1730 pair: roundup-admin; designator
1232 1731
1732 .. _`roundup-admin templates`:
1733
1233 Using roundup-admin 1734 Using roundup-admin
1234 =================== 1735 ===================
1235 1736
1236 Part of the installation includes a man page for roundup-admin. Ypu 1737 Part of the installation includes a man page for roundup-admin. Ypu
1237 should be able to read it using ``man roundup-admin``. As shown above, 1738 should be able to read it using ``man roundup-admin``. As shown above,
1243 * install and initialize a new tracker 1744 * install and initialize a new tracker
1244 * export/import tracker data for migrating between backends 1745 * export/import tracker data for migrating between backends
1245 * creating a new user from the command line 1746 * creating a new user from the command line
1246 * list/find users in the tracker 1747 * list/find users in the tracker
1247 1748
1248 The basic usage is:: 1749 The basic usage is:
1750
1751 .. code-block:: text
1249 1752
1250 Usage: roundup-admin [options] [<command> <arguments>] 1753 Usage: roundup-admin [options] [<command> <arguments>]
1251 1754
1252 Options: 1755 Options:
1253 -i instance home -- specify the issue tracker "home directory" to administer 1756 -i instance home -- specify the issue tracker "home directory" to administer
1280 filter classname propname=value ... 1783 filter classname propname=value ...
1281 find classname propname=value ... 1784 find classname propname=value ...
1282 genconfig <filename> 1785 genconfig <filename>
1283 get property designator[,designator]* 1786 get property designator[,designator]*
1284 help topic 1787 help topic
1285 history designator [skipquiet] 1788 history designator [skipquiet] [raw]
1286 import import_dir 1789 import import_dir
1287 importtables export_dir 1790 importtables export_dir
1288 initialise [adminpw] 1791 initialise [adminpw]
1289 install [template [backend [key=val[,key=val]]]] 1792 install [template [backend [key=val[,key=val]]]]
1290 list classname [property] 1793 list classname [property]
1405 1908
1406 (for more details see https://issues.roundup-tracker.org/issue2550789.) 1909 (for more details see https://issues.roundup-tracker.org/issue2550789.)
1407 1910
1408 .. index:: ! roundup-admin; usage in scripts 1911 .. index:: ! roundup-admin; usage in scripts
1409 1912
1913 Using Interactively
1914 -------------------
1915
1916 You can edit the command line using left/right arrow keys to move the
1917 cursor. Using the up/down arrow keys moves among commands. It will
1918 save your commands between roundup-admin sessions. This is supported
1919 on Unix/Linux and Mac's. On windows you should install the pyreadline3
1920 package (see `installation documentation`_).
1921
1922 Using the ``history_length`` pragma you can set the saved history size
1923 for just one session.
1924
1925 You can add initialization commands to ``~/.roundup_admin_rlrc``. It
1926 will be loaded when roundup-admin starts. This is the mechanism to
1927 persistently set the number of history commands, change editing modes
1928 (Vi vs. Emacs). Note that redefining the history file will not work.
1929
1930 If you are using GNU readline, ``set history-size 10``. If your
1931 installation uses libedit (macs), it should be possible to
1932 persistently set the history size using ``history size
1933 10``. Pyreadline3 can set history length using
1934 ``history_length(10)``. See the documentation for example syntax:
1935 https://pythonhosted.org/pyreadline/usage.html#configuration-file.
1936
1937 History is saved to the file ``.roundup_admin_history`` in your home
1938 directory (for windows usually ``\Users\<username>``.
1939
1410 Using with the shell 1940 Using with the shell
1411 -------------------- 1941 --------------------
1412 1942
1413 With version 0.6.0 or newer of roundup (which introduced support for 1943 With version 0.6.0 or newer of roundup (which introduced support for
1414 multiple designators to display and the -d, -S and -s flags): 1944 multiple designators to display and the -d, -S and -s flags):
1550 However under certain circumstances, Roundup can skip an id 2080 However under certain circumstances, Roundup can skip an id
1551 number. This can lead to a difference of more than 1 between the 2081 number. This can lead to a difference of more than 1 between the
1552 Importing and setting numbers. It's not a problem. However setting 2082 Importing and setting numbers. It's not a problem. However setting
1553 can (and must) always be higher than the Importing number. 2083 can (and must) always be higher than the Importing number.
1554 2084
2085 Interactive Help
2086 ----------------
2087
2088 The help command produces the following output for all the commands.
2089
2090
2091 .. raw:: html
2092 :file: admin_help.html
1555 2093
1556 .. _`customisation documentation`: customizing.html 2094 .. _`customisation documentation`: customizing.html
1557 .. _`reference documentation`: reference.html 2095 .. _`reference documentation`: reference.html
1558 .. _`upgrading documentation`: upgrading.html 2096 .. _`upgrading documentation`: upgrading.html
1559 .. _`installation documentation`: installation.html 2097 .. _`installation documentation`: installation.html

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