diff --git a/.github/workflows/anchore.yml b/.github/workflows/anchore.yml index a1c2e6a5f..e0ba3d102 100644 --- a/.github/workflows/anchore.yml +++ b/.github/workflows/anchore.yml @@ -37,20 +37,20 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Build the Docker image run: docker pull python:3-alpine; docker build . --file scripts/Docker/Dockerfile --tag localbuild/testimage:latest - name: List the Docker image run: docker image ls - name: Run the Anchore scan action itself with GitHub Advanced Security code scanning integration enabled - uses: anchore/scan-action@c35e932c2a7c572bfdb1c3dbcdadb2d4fc62418d # 3.6.1 + uses: anchore/scan-action@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2 # 7.4.0 id: scan with: image: "localbuild/testimage:latest" fail-build: true - name: Upload Anchore Scan Report if: always() - uses: github/codeql-action/upload-sarif@65c74964a9ed8c44ed9f19d4bbc5757a6a8e9ab9 # v2.16.1 + uses: github/codeql-action/upload-sarif@b1e4dc3db58c9601794e22a9f6d28d45461b9dbf # v2.22.0 with: sarif_file: ${{ steps.scan.outputs.sarif }} - name: Inspect action SARIF report diff --git a/.github/workflows/build-xapian.yml b/.github/workflows/build-xapian.yml index 2441a1a8a..262a542da 100644 --- a/.github/workflows/build-xapian.yml +++ b/.github/workflows/build-xapian.yml @@ -26,7 +26,7 @@ concurrency: jobs: test: name: build xapian - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: # get colorized pytest output even without a controlling tty @@ -42,11 +42,11 @@ jobs: # if: {{ false }} # continue running if step fails # continue-on-error: true - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # Setup version of Python to use - name: Set Up Python 3.13 - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: 3.13 allow-prereleases: true @@ -82,7 +82,7 @@ jobs: # Sphinx required to build the xapian python bindings. Use 1.8.5 on # older python and newest on newer. pip install sphinx - XAPIAN_VER="1.4.25"; echo $XAPIAN_VER; + XAPIAN_VER="1.4.22"; echo $XAPIAN_VER; cd /tmp curl -s -O https://oligarchy.co.uk/xapian/$XAPIAN_VER/xapian-bindings-$XAPIAN_VER.tar.xz tar -Jxvf xapian-bindings-$XAPIAN_VER.tar.xz diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 0132c1853..b15986016 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -52,38 +52,49 @@ jobs: # Run in all these versions of Python python-version: # - "2.7" + - "3.14" - "3.13" - # - 3.6 run via include on ubuntu 20.04 - # - "3.7" - - "3.8" + # - "3.7" run via include for ubuntu-22.04 + # - "3.8" run via include for ubuntu-22.04 # - "3.9" - "3.10" - - "3.11" - - "3.12" + # - "3.11" + # - "3.12" # use for multiple os or ubuntu versions #os: [ubuntu-latest, macos-latest, windows-latest] # ubuntu latest 22.04 12/2022 - os: [ubuntu-latest, ubuntu-20.04] + # ubuntu latest 24.04 12/2024 + os: [ubuntu-latest] # if the ones above fail. fail the build experimental: [ false ] include: - # example: if 3.13 fails the jobs still succeeds + # example: if this version fails the jobs still succeeds # allow-prereleases in setup-python allows alpha/beta - # releases to run - #- python-version: 3.13 - # os: ubuntu-22.04 - # experimental: true + # releases to run. Also allow free threaded python testing + - python-version: 3.14t + os: ubuntu-24.04 + experimental: true - # 3.6 not available on new 22.04 runners, so run on 20.04 ubuntu - - python-version: 3.6 - os: ubuntu-20.04 + # 3.7 not available on new 22.04 runners, so run on 22.04 ubuntu + - python-version: 3.7 + os: ubuntu-22.04 - exclude: - # skip all python versions on 20.04 except explicitly included - - os: ubuntu-20.04 + # 3.8 not available on new 24.04 runners, so run on 22.04 ubuntu + - python-version: 3.8 + os: ubuntu-22.04 + + #exclude: + # skip all python versions on explicit 20.04/24.04 unless + # explicitly included + #- os: ubuntu-20.04 + #- os: ubuntu-24.04 + + # disable when testing ubuntu-24.04 to speed up + # runs. + # - os: ubuntu-latest # run the finalizer for coveralls even if one or more # experimental matrix runs fail. @@ -105,11 +116,11 @@ jobs: # if: {{ false }} # continue running if step fails # continue-on-error: true - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # Setup version of Python to use - name: Set Up Python ${{ matrix.python-version }} - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python-version }} allow-prereleases: true @@ -121,10 +132,17 @@ jobs: # Display the Python version being used - name: Display Python and key module versions run: | - python -c "import sys; print('python version: ', sys.version)" + python --version --version + python -c "import sysconfig; print('GIL IS DISABLED: ', sysconfig.get_config_vars().get('Py_GIL_DISABLED', 'not defined'));" python -c "import sqlite3; print('sqlite version: ', sqlite3.sqlite_version)" python -c "import setuptools; print('setuptools version: ', setuptools.__version__);" + # from: + # https://hugovk.dev/blog/2025/free-threaded-python-on-github-actions/ + - name: Set PYTHON_GIL when freethreaded + if: endsWith(matrix.python-version, 't') + run: | + echo "PYTHON_GIL=0" >> "$GITHUB_ENV" - name: Update pip run: python -m pip install --upgrade pip @@ -206,25 +224,48 @@ jobs: pip install mysqlclient pip install psycopg2 + # https://github.com/mxschmitt/action-tmate + # allow remote ssh into the CI container. I need this to debug + # some xfail cases + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }} + timeout-minutes: 10 + with: + limit-access-to-actor: true + - name: Install auxiliary packages run: | - sudo apt-get install swig gpgsm libgpgme-dev + sudo apt-get install swig gpg gpgsm libgpgme-dev # pygments for markdown2 to highlight code blocks pip install markdown2 pygments # docutils for ReStructuredText - pip install beautifulsoup4 brotli docutils gpg jinja2 \ + pip install beautifulsoup4 brotli docutils jinja2 \ mistune==0.8.4 pyjwt pytz whoosh + # gpg on PyPi is currently broken with newer OS platform + # ubuntu 24.04 + # used for newer Python versions. Temporarily use the + # testing index, which contains a newer version of the + # bindings on 24.04 or released version for other OS + # versions. See issue2551368. 'pip install gpg' should work + # at some point when things are released to the production repo. + pip install --index-url https://test.pypi.org/simple/ \ + --extra-index-url https://pypi.org/simple gpg; - name: Install aux packages that need versions differences # if zstd fails install, keep going with test, don't abort run: | set -xv pip install zstd || true + # justhtml supports python 3.10 or newer according to pypi + # page, but will install on 3.8 (and maybe 3.9) but formats + # differently. So skip install if before 3.10. + if echo $PYTHON_VERSION | grep '^3\...'; then + pip install justhtml || true; fi if [[ "$PYTHON_VERSION" != "2."* ]]; then pip install Markdown; fi - name: Install xapian - if: matrix.python-version != '3.13' run: | set -xv sudo apt-get install libxapian-dev @@ -232,11 +273,7 @@ jobs: # older python and newest on newer. if [[ $PYTHON_VERSION == "2."* ]]; then pip install sphinx==1.8.5; fi if [[ $PYTHON_VERSION == '3.'* ]] ; then pip install sphinx; fi - if [[ $PYTHON_VERSION != "3.13" ]]; then - XAPIAN_VER=$(dpkg -l libxapian-dev | tail -n 1 | awk '{print $3}' | cut -d '-' -f 1); echo $XAPIAN_VER; - else - XAPIAN_VER="1.4.25"; echo $XAPIAN_VER; - fi + XAPIAN_VER=$(dpkg -l libxapian-dev | tail -n 1 | awk '{print $3}' | cut -d '-' -f 1); echo $XAPIAN_VER; cd /tmp curl -s -O https://oligarchy.co.uk/xapian/$XAPIAN_VER/xapian-bindings-$XAPIAN_VER.tar.xz tar -Jxvf xapian-bindings-$XAPIAN_VER.tar.xz @@ -259,7 +296,7 @@ jobs: diff -u configure.FCS configure || true; \ ./configure --prefix=$VIRTUAL_ENV --with-python3 --disable-documentation; \ fi - case "$PYTHON_VERSION" in "3.13") echo skipping xapian build;; *) make && sudo make install; esac + make && sudo make install - name: Test build roundup and install locale so lang tests work. run: | @@ -280,10 +317,7 @@ jobs: -W "ignore:unclosed:ResourceWarning:roundup.roundup.demo" \ -W "ignore:unclosed file:ResourceWarning:enum" \ -v test/ --cov=roundup - if [[ "$PYTHON_VERSION" != "3.6" ]]; then - # coverage before 3.6 doesn't support lcov output coverage lcov - fi else # python2 case pytest -v -r a --durations=20 test/ --cov=roundup @@ -294,7 +328,7 @@ jobs: - name: Upload coverage to Codecov # see: https://github.com/codecov/codecov-action#usage - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # v3.1.5 + uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 with: verbose: true token: ${{ secrets.CODECOV_TOKEN }} @@ -302,7 +336,7 @@ jobs: - name: Upload coverage to Coveralls # python 2.7 and 3.6 versions of coverage can't produce lcov files. if: matrix.python-version != '2.7' && matrix.python-version != '3.6' - uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949 # v2.2.3 + uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7 with: github-token: ${{ secrets.GITHUB_TOKEN }} path-to-lcov: coverage.lcov @@ -338,7 +372,7 @@ jobs: steps: - name: Coveralls Finished - uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949 # v2.2.3 + uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7 with: github-token: ${{ secrets.github_token }} parallel-finished: true diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 321f5d54f..8d4599924 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,11 +49,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@65c74964a9ed8c44ed9f19d4bbc5757a6a8e9ab9 # v2.16.1 + uses: github/codeql-action/init@b1e4dc3db58c9601794e22a9f6d28d45461b9dbf # v2.22.0 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -64,7 +64,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@65c74964a9ed8c44ed9f19d4bbc5757a6a8e9ab9 # v2.16.1 + uses: github/codeql-action/autobuild@b1e4dc3db58c9601794e22a9f6d28d45461b9dbf # v2.22.0 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -78,4 +78,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@65c74964a9ed8c44ed9f19d4bbc5757a6a8e9ab9 # v2.16.1 + uses: github/codeql-action/analyze@b1e4dc3db58c9601794e22a9f6d28d45461b9dbf # v2.22.0 diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index a5bca1faf..5bfa6d50a 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -35,12 +35,12 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.10 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v5.2.1 with: results_file: results.sarif results_format: sarif @@ -62,7 +62,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: SARIF file path: results.sarif @@ -70,6 +70,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@65c74964a9ed8c44ed9f19d4bbc5757a6a8e9ab9 # v2.16.1 + uses: github/codeql-action/upload-sarif@b1e4dc3db58c9601794e22a9f6d28d45461b9dbf # v2.22.0 with: sarif_file: results.sarif diff --git a/.hgignore b/.hgignore index 75ef4674b..5f09b9db2 100644 --- a/.hgignore +++ b/.hgignore @@ -47,3 +47,4 @@ website/www/COPYING.txt website/www/docs website/www/html/ .pytest_cache +.hypothesis diff --git a/.hgtags b/.hgtags index 75c9cd063..e0d4f7130 100644 --- a/.hgtags +++ b/.hgtags @@ -154,3 +154,5 @@ a377590eba34724c5d30d80692257e5ae68aab13 2.4.0b0 0000000000000000000000000000000000000000 2.4.1b1 c10df5dfed95dc37e8092861886bf66614b77062 2.4.0b1 4dfc07ee489ad000c8ffe7ee97b506c94fae6774 2.4.0 +3bf6ad421347c87ae3a6bebe288f8f1dfa7bd6ba 2.5.0b1 +c7a2e01793cdb5228d44df085e3b2f8a73e51c28 2.5.0 diff --git a/.travis.yml b/.travis.yml index 018e399bb..a51097b6a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -132,6 +132,7 @@ install: - pip install redis - pip install pytz whoosh pyjwt requests - pip install jinja2 + - pip install psycopg2 # note pytest-env is not needed for redis password as there is # no password on CI's redis. - pip install pytest-cov diff --git a/CHANGES.txt b/CHANGES.txt index c07a86f6f..558a2fc9d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -13,10 +13,106 @@ Roundup 2.0 supports Python 3.4 and later. Roundup 2.1.0 supports python 3.6 or newer (3.4/3.5 might work, but they are not tested). Roundup 2.4.0 is the last release to support Python 2. -2025-XX-XX 2.5.0 +2026-XX-XX 2.6.0 Fixed: +- performance improvement to session_dbm.py:clean(). Also add warning + log message if clean takes longer than 3 seconds. (John Rouillard) +- move RateLimitExceeded exception from roundup.exceptions to + roundup.cgi.exceptions. Also it now inherits from HTTPException + rather than Exception since it is an HTTP exception. (John + Rouillard) +- cleaned up repo. Close obsolete branches and close a split head due + to an identical merge in two different working copies. (John + Rouillard) +- in roundup-admin, using 'pragma history_length interactively now + sets readline history length. Using -P history_length=10 on the + command line always worked. (John Rouillard) +- enhanced error reporting for errors in ini style logging + configuration. (John Rouillard) +- fix bogus javascript emitted by user_src_input macro. (John + Rouillard) +- replaced hostname localhost with 127.0.0.1 in docker healthcheck + script. Found/patch by Norbert Schlemmer. (John Rouillard) +- change some internal classes to use __slots__ for hopefully a small + performance improvement. (John Rouillard) +- issue2551413 - Broken MultiLink columns in CSV export. CSV export of + a multilink link "messages" that does not have a 'name' property + causes a crash. (found/fix by cmeerw; commit and better handling of + non-labeled multilink by John Rouillard) +- in cgi/client.py, set self.language attribute when translator passed + into Client(). (John Rouillard) +- issue2551393 - Named searches lose their name in title when next + page is selected. (John Rouillard) +- code cleanup replace bare except: with except Exception:. (patch by + Sense_wang (haosenwang1018) applied by John Rouillard) +- handle "null" values in json objects sent to a rest endpoint by + filtering them from the object before processing. A "null" value + will not unset an attribute. The 'remove' action using the + PATCH verb can unset the value. Before this change "null" values + retrieved from the REST interface would cause errors when sent + using POST or PUT verbs. Also guard against password being set to + None. (John Rouillard) +- change the html templates so that the password is not required if + the ``login_empty_passwords`` setting is enabled in ``config.ini``. + Directions for your tracker are in upgrading.txt. (John Rouillard) +- fix traceback displayed when roundup-admin install was used with + invalid settings for config.ini. It now reports the error and + provides the usage output. Also usage output starts with a newline + to provide a blank line between the command and the output to + improve readability. (John Rouillard) +- fix bug in 2.5.0 where roundup-admin import (or importtable) fails + to properly set the next available id for the class. (John Rouillard + broke it and fixed it 8-)) +- refactor mime detection/handling in the rest interface. Better + supports some mime types, ads default mime type for files without a + mime type (e.g. message contents). Cleaner code. (John Rouillard) + +Features: + +- add support for authorized changes. User can be prompted to enter + their password to authorize a change. If the user's password is + properly entered, the change is committed. (John Rouillard) +- add support for dictConfig style logging configuration. Ini/File + style configs will still be supported. (John Rouillard) +- add 'q' as alias for quit in roundup-admin interactive mode. (John + Rouillard) +- add readline command to roundup-admin to list history, control input + mode etc. Also support bang (!) commands to rerun commands in history + or put them in the input buffer for editing. (John Rouillard) +- add format to logging section in config.ini. Used to set default + logging format. (John Rouillard) +- the default logging format template includes an identifier unique + for a request. This identifier (trace_id) can be use to identify + logs for a specific transaction. Will use nanoid if installed, uses + uuid.uuid4 otherwise. Logging also supports a trace_reason log token + with the url for a web request. The logging format can be changed in + config.ini. (John Rouillard) +- issue2551152 - added basic PGP setup/use info to admin_guide. (John + Rouillard) +- add support for the 'justhtml' html 5 parser library for python >= + 3.10. It is written in pure Python. Used to convert html emails into + plain text. Faster then beautifulsoup4 and it passes the html 5 + standard browser test suite. Beautifulsoup is still supported. (John + Rouillard) +- add a new detector: immutable_file_contents.py that prevents changes + to file contents. By default, the permissions assigned to FileClass + based classes (files, msgs) do not prevent editing of file contents. + While the usual HTML templates don't provide a way to modify files, + the REST interface allows changing file contents without an audit + trail. Manually driving the HTML interface (via curl for example) + also allows content changes. The new detector prevents changes to + file contents via Roundup even by a user with admin rights. +- Added documentation on doing an in place database migration. This is + faster for large databases. (John Rouillard) + +2025-07-13 2.5.0 + +Fixed: + +- XSS issue in devel and responsive templates. Reported by 4bug of + ChaMd5 Security Team H1 Group. (John Rouillard). - issue2551343 - Remove support for PySQLite. It is unmaintained and sqlite3 is used which is the default for a Python distribution. (John Rouillard) @@ -26,6 +122,78 @@ Fixed: - issue2551131 - Return accept-patch if patch body not accepted (415 code). Accept-Patch returned with acceptable values. (John Rouillard) +- issue2551074 - In "responsive" template: click on hide comment leads + to a red error msg. (Report by Ludwig Reiter; fix John Rouillard) +- issue2550698 - added documentation on filtering using RPN property + expressions. (John Rouillard) +- issue2551372 - Better document necessary headers for REST and fix + logging to log missing Origin header (Ralf Schlatterbeck with + suggestions on documentation by John Rouillard) +- issue2551289 - Invalid REST Accept header with post/put performs + change before returning 406. Error before making any changes to the + db if we can't respond with requested format. (John Rouillard) +- issue2551356 - Add etag header when If-Modified-Since GET request + returns not-modified (304). Breaking change to function signature + for client.py-Client::_serve_file(). (John Rouillard) +- issue2551381 - roundup-server parses URI's with multiple '?" + incorrectly. (John Rouillard) +- issue2551382 - invalid @verbose, @page_* values in rest uri's + generate 409 not 400 error. (John Rouillard) +- fix issues with rest doc and use of PUT on a property item. Response + is similar to use of PUT on the item, not a GET on the + item. Discovered while fuzz testing. (John Rouillard) +- issue2551383 - Setting same address via REST PUT command results in + an error. Now the userauditor does not trigger an error if a user + sets the primary address to the existing value. (John Rouillard) +- issue2551253 - Modify password PBKDF2 method to use SHA512. The + default password hashing algorithm has been upgraded to + PBKDF2-SHA512 from PBKDF2-SHA1. The default pbkdf2 rounds in the + config file has been changed to 250000. The admin should change it + manually if it is at 2 million. PBKDF2-SHA512 (PBKDF2S5) has been + available since release 2.3, but it required a manual step to make + it the default. (John Rouillard) +- fixed a crash with roundup-admin perftest password when rounds not set + on command line. (John Rouillard) +- issue2551374 - Add error handling for filter expressions. Filter + expression errors are now reported. (John Rouillard) +- issue2551384: Modify flow in client.py's REST handler to verify + authorization earlier. The validation order for REST requests + has been changed. Checking user authorization to use the REST + interface is done before validating the Origin header. As a + result, incorrectly formatted CORS preflight requests + (e.g. missing Origin header) can now return HTTP status 403 as + well as status 400. (John Rouillard) +- issue2551387 - TypeError: not indexable. Fix crash due to + uninitialized list element on a (Mini)FieldStorage when unexpected + input is posted via wsgi. (Reported and debugged by Christof + Meerwald; fix John Rouillard) +- close http socket and send a 408 status when a timeout exception + is handed in roundup-server. This prevents another exception + caused by using a timed out socket. (John Rouillard) +- issue2551391, partial fix for issue1513369. input fields were + not getting id's assigned. Fixed automatic id assignment to + input fields. Thinko in the code. (John Rouillard) +- issue1895197 - translated help texts in admin.py not displayed + correctly. (Initial patch tobias-herp, John Rouillard) +- issue2551238 - roundup-server should exit with error if -d + is used without -l . Added code to report + the issue. Added issue with relative paths for log file whn + using -L and -d with roundup-server. (John Rouillard) +- Allow the specification of a "form" parameter for Date fields to make + the popup calendar work when the enclosing form has a name different + from "itemSynopsis". (Ralf Schlatterbeck) +- issue2551376: Fix tracebacks in item templates (Ralf Schlatterbeck) +- issue2551396: Use of os.path.stat.ST_MTIME in python 3.13 crashes + roundup on windows. Replaced with equivalent stat.ST_MTIME. (Randy + on IRC, fix: John Rouillard and R. David Murray (bitdancer)) +- issue2551323: remove functions used for XHTML template + support. XHTML was deprecated in Roundup 2.3.0 and an invalid value + in 2.4.0. (John Rouillard) +- issue2551406: 'Templating Error: too many values to unpack' crash + fixed. (reported by and patch Christof Meerwald, commit/test John + Rouillard) +- fix potential HTTP Response Splitting issue in + roundup-server. Discovered by CodeQL in CI. (John Rouillard) Features: @@ -36,7 +204,54 @@ Features: Marcus Priesch, cleanup to remove python 2 issues, John Rouillard.) - issue2551315 - Document use of RestfulInstance.max_response_row_size to limit data returned - from rest request. + from rest request. (John Rouillard) +- issue2551330 - Add an optional 'filter' function to the Permission + objects and the addPermission method. This is used to optimize search + performance by not checking items returned from a database query + one-by-one (using the check function) but instead offload the + permission checks to the database. For SQL backends this performs the + filtering in the database. (Ralf Schlatterbeck) +- issue2551370 - mark roundup session cookie with __Secure- + prefix. (John Rouillard) +- add -P flag to roundup-server to log client address from + X-Forwarded-For reverse proxy header rather than connecting + address. This logs the actual client address when + roundup-server is run behind a reverse proxy. It also appends a + + sign to the logged address/name. (John Rouillard) +- issue2551068 - Provide way to retrieve file/msg data via rest + endpoint. Raw file/msg data can be retrieved using the + /binary_content attribute and an Accept header to select the mime + type for the data (e.g. image/png for a png file). The existing html + interface method still works and is supported, but is legacy. (John + Rouillard) +- added fuzz testing for some code. Found issue2551382 and + others. (John Rouillard) +- issue2551116 - Replace xmlrpclib (xmlrpc.client) with defusedxml. + Added support for defusedxml to better secure the xmlrpc + endpoint. (John Rouillard) +- Added new instance.registerUtilMethod() method to make using complex + templating easier as it provides a default Client instance to the + templating method. (John Rouillard) +- Added new templating utils.set_http_response(integer) method to + allow reporting an error to the user from a template. (John + Rouillard) +- issue2551390 - Replace text input/calendar popup with native + date input. Also add double-click and exit keyboard handlers to + allow copy/paste/editing the text version of the date. Configurable + via the use_browser_date_input setting in the [web] section of + config.ini. By default browser native dates are turned off. + (John Rouillard, Ralf Schlatterbeck) +- Use native number type input for Number() and Integer() + properties. Integer() uses step=1 as well. Configurable via the + use_browser_number_input setting in the [web] section of config.ini. + Set off by default. See + https://issues.roundup-tracker.org/issue2551398 for discussion of + issues with native number inputs. (John Rouillard, Ralf + Schlatterbeck) +- issue2551231 - template.py-HTMLClass::classhelp doesn't merge + user defined classes. It now merges them in. (John Rouillard) +- re-enable support for GPG/PGP encrypted emails using new python gpg + package on the test pypi instance. (Paul Schwabauer) 2024-07-13 2.4.0 diff --git a/COPYING.txt b/COPYING.txt index ac8764339..18d9f1c3b 100644 --- a/COPYING.txt +++ b/COPYING.txt @@ -5,7 +5,7 @@ Roundup, exclusive of the Zope page templates, is `MIT licensed`_. Roundup Licensing ----------------- -| Copyright (c) 2009-2024 Roundup-Team (https://opensource.org/license/mit) +| Copyright (c) 2009-2025 Roundup-Team (https://opensource.org/license/mit) | Copyright (c) 2003-2009 Richard Jones (richard@mechanicalcat.net) | Copyright (c) 2002 eKit.com Inc | Copyright (c) 2001 Bizar Software Pty Ltd diff --git a/RELEASE.txt b/RELEASE.txt index 1b1a4b173..9410a721b 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -72,13 +72,7 @@ Roundup release checklist: python3 setup.py check --restructuredtext --metadata --strict -6. Clean out all *.orig, *.rej, .#* files from the source. - - find . -name '*.orig' -exec rm {} \; - find . -name '*.rej' -exec rm {} \; - find . -name '.#*' -exec rm {} \; - -6a. Rebuild .mo translation files in distribution +6. Rebuild .mo translation files in distribution cd locale make @@ -89,7 +83,15 @@ Roundup release checklist: python3 setup.py clean --all rm -rf build/share # deletes locale .mo files - Build including new .mo files built in 6a. + Clean out all *.orig, *.rej, .#* files from the source. + + find . -name '*.orig' -exec rm {} \; + find . -name '*.rej' -exec rm {} \; + find . -name '.#*' -exec rm {} \; + +7a. + + Build including new .mo files built in 6. python3 setup.py build @@ -97,7 +99,16 @@ Roundup release checklist: 8. Rebuild documentation in "share/doc/roundup/html" - python3 setup.py build_doc + cd doc + make + cd .. + + runs commands to turn man pages into html files and adds them to + html_extra/man_pages subdir. Then it generates html text from + running roundup_admin. Then it generates a current copy of a + config.ini file. Then it runs: + + python3 setup.py build_doc 9. Generate source distribution: @@ -105,10 +116,11 @@ Roundup release checklist: (if you find sdist a little verbose, add "--quiet" to the end of the command) + 9a. 2021/04/17 skip this for now. Need to make sure that whl installs executable scripts properly and update these directions to test. - python2 setup.py bdist_wheel; python3 setup.py bdist_wheel + python3 setup.py bdist_wheel to create binary distributions in wheel format. (egg format is deprecated.) @@ -135,14 +147,15 @@ Roundup release checklist: any file with a count of 2 or more needs to be removed from MANIFEST.in and possibly cleaned out of the build tree. + 10b: if you added/removed files rebuild starting at step 6a. 11. Unpack the new tarball created in dist/roundup-.tar.gz file in /tmp then - a) run tests using installed pytest run under python2 and - python3. (python2 -m pytest test/; python3 -m pytest test/) + a) run tests using installed pytest run under + python3. (python3 -m pytest test/) b) demo.py - with all available Python versions. + with all available Python 3 versions. 11a. (TBD how to test wheel binary distribution before uploading.) 11b. Generate GPG signature file @@ -154,10 +167,10 @@ Roundup release checklist: can add --local=roundup-devel@lists.sourceforge.net. This will create a file by the name .tar.gz.asc. - Move file to website/www/signature directory + Move file to website/www/signatures directory mv .tar.gz.asc ../website/www/signatures/. - hg add ../website/www/signature/.tar.gz.asc + hg add ../website/www/signatures/.tar.gz.asc # commiting the file will be done in step 12 cd .. @@ -261,12 +274,26 @@ Roundup release checklist: You may need to explicitly update/refresh the scanners with: "docker pull anchore/grype:latest" and similarly for aquasec/trivy if used. + + Note that some security issues may show up. If they are in the + underlying OS package we can't do anything but make sure the + latest python:3-alpine package is used to build the image. Look + at the index digest on the image release page and compare it to + the sha256 at the top of the Dockerfile. + 17d. test roundup in demo mode: docker run -it --rm -p 8917:8080 \ -v $PWD/tracker:/usr/src/app/tracker \ rounduptracker/roundup:2.4.0 demo + FIXME: right now the external port number (8917) in the above + command is hardcoded in DOCKER. It can be overridden usng + PORT_8080=9017 for example. However the host is always + localhost. Consider replacing PORT_8080 with ORIGIN="host:port" + or ORIGIN="port" so that the web URL can be made correct when + running docker on a remote server. + 17e. push to DockerHub login (login using 'docker login ' first and user must be member of rounduptracker org with ability to publish). Replace -N with the release number (e.g. -1, -2, -3...) diff --git a/detectors/README.txt b/detectors/README.txt index fde325dd6..508299ce4 100644 --- a/detectors/README.txt +++ b/detectors/README.txt @@ -19,6 +19,10 @@ creator_resolution.py - only allow the creator of the issue to resolve it emailauditor.py - Rename .eml files (from email multi-part bodies) to .mht so they can be downloaded/viewed in Internet Explorer. +immutable_file_contents.py - prevent changes to the contents property + of file and msg classes including by + people with the admin role. + irker.py - communicate with irkerd to allow roundtup to send announcements to an IRC channel. diff --git a/detectors/immutable_file_contents.py b/detectors/immutable_file_contents.py new file mode 100644 index 000000000..d5a8dc391 --- /dev/null +++ b/detectors/immutable_file_contents.py @@ -0,0 +1,22 @@ +# HTML pages don't provide a way to change the contents of a file. +# However REST does allow setting content and the HTML interface can +# be directed to update the content as well. This detector +# prevents changes to file content. + +from roundup.exceptions import UsageError + +def immutable_file_contents(db, cl, nodeid, newvalues): + ''' Prevent content changes to a file + ''' + if 'content' in newvalues: + raise UsageError("File contents are immutable. " + "Rejecting change to contents.") + + +def init(db): + """If you have other FileClass based classes add them here.""" + + # fire before changes are made + db.file.audit('set', immutable_file_contents) + db.msg.audit('set', immutable_file_contents) + diff --git a/detectors/irker.py b/detectors/irker.py index 57ce2bfb1..ff330cbbc 100644 --- a/detectors/irker.py +++ b/detectors/irker.py @@ -1,6 +1,6 @@ # This detector sends notification on IRC through an irker daemon -# (http://www.catb.org/esr/irker/) when issues are created or messages -# are added. +# (https://gitlab.com/esr/irker formerly http://www.catb.org/esr/irker/) +# when issues are created or messages are added. # # Written by Ezio Melotti # diff --git a/doc/Makefile b/doc/Makefile index c4378bb3a..c9db7af88 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,8 +1,10 @@ -all: man_html tracker_config.txt admin_help.html +##@ Default target +all: man_html tracker_config.txt admin_help.html ## make all docs under share cd ..; ./setup.py build_doc -tracker_config.txt: ../roundup/configuration.py - # generate a current config file +##@ build doc parts +tracker_config.txt: ../roundup/configuration.py format_config.awk ## generate a current config file + python3 ../roundup/scripts/roundup_admin.py \ genconfig _temp_config.txt @@ -15,7 +17,7 @@ tracker_config.txt: ../roundup/configuration.py MAN_ROFF=$(wildcard ../share/man/man1/*.1) MAN_HTML=$(patsubst ../share/man/man1/%.1,html_extra/man_pages/%.1.html,$(MAN_ROFF)) -man_html: $(MAN_HTML) +man_html: $(MAN_HTML) ## generate html versions of man pages for docs html_extra/man_pages/%.1.html: ../share/man/man1/%.1 man --html=cat $< > $@ @@ -27,10 +29,17 @@ html_extra/man_pages/%.1.html: ../share/man/man1/%.1 sed -i '//,/<\/head>/s#^\n $@ -admin_help.html: ../roundup/admin.py - python3 ../roundup/scripts/roundup_admin.py htmlhelp > admin_help.py +admin_help.html: ../roundup/admin.py ## generate html version of roundup-admin help (WIP) + python3 ../roundup/scripts/roundup_admin.py htmlhelp > admin_help.html + +##@ Utilties -clean: +clean: ## clean all generated docs rm -f _temp_config.txt tracker_config.txt \ html_extra/man_pages/*.1.html \ admin_help.py + +# from https://www.thapaliya.com/en/writings/well-documented-makefiles/ via +# https://til.jakelazaroff.com/make/list-all-commands-in-a-makefile/ +help: ## this output + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[.a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) diff --git a/doc/_static/style.css b/doc/_static/style.css index ac0a6a9b9..73f30b110 100644 --- a/doc/_static/style.css +++ b/doc/_static/style.css @@ -51,6 +51,15 @@ * + * { margin-block-start: 1.2em;} +/* shrink spacing between first and following paragraph in a list item + when the first paragraph is bold/strong. Try to tie the first paragraph + pseudo header closer to the following paragraph. */ +li > p:has(strong):first-child + { + /* background: red; */ + margin-block-end: -0.75em; +} + /* shrink spacing between list elements in tables of contents, badge displays */ div.toctree-wrapper * + *, div.contents * + *, div.release_info * { @@ -177,6 +186,8 @@ div[class^=highlight-], div[class^=highlight-] * { width: /* style */ :link { color: rgb(220,0,0); text-decoration: none;} +/* improve contrast to AA */ +.admonition.note :link { color: rgb(170,1,1); text-decoration: none;} :link:hover { text-decoration: underline solid clamp(1px, .3ex, 4px); text-underline-position: under; @@ -429,6 +440,14 @@ dd > ul:first-child { white-space: break-spaces; }*/ +/* improve color contrast to AA against yellowish highlight bg */ +div.highlight .c1 { + color: rgb(3,114,3); +} +div.highlight .na { + color: rgb(220,2,2); +} + /* Forcing wrap in a pre leads to some confusing line breaks. Use a horizontal scroll. Indicate the scroll by using rounded scroll shadows. @@ -446,9 +465,9 @@ div.highlight > pre { linear-gradient(to right, #f5f4d8, #f5f4d8), /* Shadow */ radial-gradient(farthest-side at 0px 50%, - rgba(0, 0, 20, 0.5), rgba(255, 255, 255, 0)), + rgba(181, 181, 113, 0.75), rgba(255, 255, 255, 0)), radial-gradient(farthest-side at 100% 50%, - rgba(0, 0, 20, 0.5), rgba(255, 255, 255, 0)); + rgba(181, 181, 113, 0.75), rgba(255, 255, 255, 0)); /* square shadows */ /* linear-gradient(to right, rgba(0, 0, 0, 0.25), rgba(255, 255, 255, 0)), @@ -474,6 +493,9 @@ ul.multicol { ul.multicol > * { margin-block-start: 0; /* remove spacing added by * + * here */ } +ul.multicol > li > p { /* remove spacing around paragraphs to tighten up list */ + margin: 0; +} div.file_insert { /* use to insert COPYING into license.txt */ background: #f3f1cc; @@ -500,3 +522,14 @@ aside.footnote > span + p { margin-block-start: unset; } } */ +/* move the target off the top of the viewport by a little */ +:target { + scroll-margin-block-start: 2em; +} + + +/* Make feature blocks look like raised cards for some variety. */ +div.card { + box-shadow: rgba(6, 24, 44, 0.4) 0px 0px 0px 2px, rgba(6, 24, 44, 0.65) 0px 4px 6px -1px, rgba(255, 255, 255, 0.08) 0px 1px 0px inset; + padding: 1em; +} diff --git a/doc/acknowledgements.txt b/doc/acknowledgements.txt index af3e8029a..13e871ca3 100644 --- a/doc/acknowledgements.txt +++ b/doc/acknowledgements.txt @@ -16,6 +16,38 @@ ideas and everything else that helped! .. _`Announcement with changelog for current release.`: announcement.html +2.5 +--- + +2.5.0 +~~~~~ + +Maintainer: John Rouillard + +Release Manager: John Rouillard + +Developer activity by changesets:: + + + rouilj@ieee.org 222 ***************************************************** + rsc@runtux.com 27 ****** + +Other contributers: + +Christof Meerwald - reported issue 2551387 + +Ludwig Reiter - reported issue 2551074 + +Marcus Priesch - patch for issue 2551287 + +Paul Schwabauer - updates to gpg python module so it still works for Roundup. + +Randy - reported issue 2551396 + +Tobias Herp - patch for issue 1895197 + +4bug of ChaMd5 Security Team H1 Group - XSS vulnerability report + 2.4 --- diff --git a/doc/admin_guide.txt b/doc/admin_guide.txt index 75d9fa06d..bafcdcfe2 100644 --- a/doc/admin_guide.txt +++ b/doc/admin_guide.txt @@ -46,31 +46,542 @@ There's two "installations" that we talk about when using Roundup: both choosing your "tracker home" and the ``main`` -> ``database`` variable in the tracker's config.ini. +.. _rounduplogging: + +Configuring Roundup Message Logging +=================================== + +You can control how Roundup logs messages using your tracker's +config.ini file. Roundup uses the standard Python logging +implementation. The config file and ``roundup-server`` provide +very basic control over logging. + +``roundup-server``'s logging is controlled from the command +line. You can: + +- specify the location of a log file or +- enable logging using the standard Python logging library under + the tag/channel ``roundup.http`` + +Configuration for "BasicLogging" implementation for your tracker +is done using the settings in the tracker's ``config.ini`` under +the ``logging`` section: + +- ``filename`` setting: specifies the location of a log file +- ``level`` setting: specifies the minimum level to log +- ``disable_loggers`` setting: disable other loggers (e.g. when + running under a wsgi framework) +- ``format`` setting: set the log format template. See + :ref:`logFormat` for more info. + +In either case, if logfile is not specified, logging is sent to +sys.stderr. If level is not set, only ERROR or higher priority +log messages will be reported. + +You can get more control over logging by using the ``config`` +setting in the tracker's ``config.ini``. Using a logging config +file overrides all the rest of the other logging settings in +``config.ini``. You get more control over the logs by supplying +a log config file in ini or json (dictionary) format. + +Using this, you can set different levels by channel. For example +roundup.hyperdb can be set to WARNING while other Roundup log +channels are set to INFO and the roundup.mailgw channel logs at +the DEBUG level. You can also control the distribution of +logs. For example roundup.mailgw logs to syslog, other channels +log to an automatically rotating log file, or are submitted to +your log aggregator over https. + +.. _logFormat: + +Defining the Log Format +----------------------- + +Starting with Roundup 2.6 you can specify the logging format in +config.ini. The ``logging`` -> ``format`` setting of config.ini +supports all of the `standard logging LogRecord attributes +`_ +or Roundup logging attributes. However you must double any ``%`` +format markers. The default value is:: + + %%(asctime)s %%(trace_id)s %%(levelname)s %%(message)s + +Roundup Logging Attributes +-------------------------- + +The `logging package has a number of attributes +`_ +that can be expanded in the format template. In addition to the +ones supplied by Python's logging module, Roundup defines +additional attributes: + + trace_id + a unique string that is generated for each request. It is + unique per thread. + + trace_reason + a string describing the reason for the trace/request. + + * the URL for a web triggered (http, rest, xmlrpc) request + * the email message id for an email triggered request + * the roundup-admin os user and start of command. Only first + two words in command are printed so seting a password will + not be leaked to the logs. + + sinfo + the stack traceback information at the time the log call id + made. + + This must be intentionally activated by using the extras + parameter. For example calling:: + + logging.get_logger('roundup.something').warning( + "I am here\n%(sinfo)s", extra={"sinfo": 2}) + + in the function confirmid() of the file detectors/reauth.py + in your demo tracker will print 2 items on the stack + including the log call. It results in the following (5 lines + total in the log file):: + + 2025-09-14 23:07:58,668 Cm0ZPlBaklLZ3Mm6hAAgoC WARNING I am here + File "[...]/roundup/hyperdb.py", line 1924, in fireAuditors + audit(self.db, self, nodeid, newvalues) + File "demo/detectors/reauth.py", line 7, in confirmid + logging.getLogger('roundup.something').warning( + + Note that the output does not include the arguments to + ``warning`` because they are on the following line. If you + want arguments to the log call included, they have to be on + the same line. + + Setting ``sinfo`` to an integer value N includes N lines up + the stack ending with the logging call. Setting it to 0 + includes all the lines in the stack ending with the logging + call. + + If the value is less than 0, the stack dump doesn't end at + the logging call but continues to the function that + generates the stack report. So it includes functions inside + the logging module. + + Setting it to a number larger than the stack trace will + print the trace down to the log call. So using ``-1000`` + will print up to 1000 stack frames and start at the function + that generates the stack report. + + Setting ``sinfo`` to a non-integer value ``{"sinfo": None}`` + will produce 5 lines of the stack trace ending at the + logging call. + + pct_char + produces a single ``%`` sign in the log. The usual way of + embedding a percent sign in a formatted string is to double + it like: ``%%``. However when the format string is specified + in the config.ini file percent signs are manipulated. So + ``%%(pct_char)s`` can be used in config.ini to print a + percent sign. + +The default logging template is defined in config.ini in the +``logging`` -> ``format`` setting. It includes the ``trace_id``. +When searching logs, you can use the trace_id to see all the log +messages associated with a request. + +If you want to log from a detector, extension or other code, you +can use these tokens in your messages when calling the logging +functions. (Note that doubling ``%`` signs is only required when +defining the log format in a config file, not when defining a +msg.) For example:: + + logging.getLogger('roundup.myextension').error('problem with ' + '%(trace_reason)s') + +will include the url in the message when triggered from the +web. This also works with other log methods: ``warning()``, +``debug()``, .... + +Note you must **not** use positional arguments in your +message. Using:: + + logging.getLogger('roundup.myextension').error( + '%s problem with %(trace_reason)s', "a") + +will not properly substitute the argument. You must use mapping +key based arguments and define the local values as part of the +extra dictionary. For example:: + + logging.getLogger('roundup.myextension').error('%(article)s ' + 'problem with %(trace_reason)', + extra={"article": some_local_variable}) + +Also if you are logging any data supplied by a user, you must not +log it directly. If the variable ``url`` contains the url typed in +by the user, never use: + + logger.info(url) + +or + + logger.info("Url is %s" % url) + +Use: + + logger.info("Url is %s", url) -Configuring Roundup's Logging of Messages For Sysadmins -======================================================= +or -You may configure where Roundup logs messages in your tracker's config.ini -file. Roundup will use the standard Python (2.3+) logging implementation. + logger.info("Url is %(url)s", extra={"url": url) -Configuration for standard "logging" module: - - tracker configuration file specifies the location of a logging - configration file as ``logging`` -> ``config`` - - ``roundup-server`` specifies the location of a logging configuration - file on the command line -Configuration for "BasicLogging" implementation: - - tracker configuration file specifies the location of a log file - ``logging`` -> ``filename`` - - tracker configuration file specifies the level to log to as - ``logging`` -> ``level`` - - ``roundup-server`` specifies the location of a log file on the command - line - - ``roundup-server`` specifies the level to log to on the command line +This prevents printf style tokens in ``url`` from being processed +where it can raise an exception. This could be used to prevent +the log message from being generated. -(``roundup-mailgw`` always logs to the tracker's log file) +More on trace_id +~~~~~~~~~~~~~~~~ -In both cases, if no logfile is specified then logging will simply be sent -to sys.stderr with only logging of ERROR messages. +The trace_id provides a unique token (a UUID4 encoded to make it +shorter or a nanoid) for each transaction in the database. It is +unique to each thread or transaction. A transaction: + + for the web interface is + each web, rest or xmlrpc request + + for the email interface is + each email request. Using pipe mode will generate one + transaction. Using pop/imap etc can generate multiple + transactions, one for each email. Logging that occurs prior + to processing an email transaction has the default + ``not_set`` value for trace_id + + for the roundup-admin interface is + each command in the interactive interface or on the command + line. Plus one transaction when/if a commit happens on + roundup-admin exit. + +When creating scripts written using the roundup package the entry +point should use the ``@gen_trace_id`` decorator. For example to +decorate the entry point that performs one transaction:: + + from roundup.logcontext import gen_trace_id + + # stuff ... + + @gen_trace_id() + def main(...): + ... + +If your script does multiple processing operations, decorate the entry +point for the processing operation:: + + from roundup.logcontext import gen_trace_id + + @gen_trace_id() + def process_one(thing): + ... + + def main(): + for thing in things: + process_one(thing) + +You can change the format of the trace_id if required using the +tracker's interfaces.py file. See the :ref:`module docs for the +logcontext module ` for details. + +Advanced Logging Setup +---------------------- + +If the settings in config.ini are not sufficient for your logging +requirements, you can specify a full logging configuration in one +of two formats: + + * `dictConfig format + `_ + using json with comment support + * `fileConfig format + `_ + in ini style + +The dictConfig format allows more control over configuration +including loading your own log handlers and disabling existing +handlers. If you use the fileConfig format, the ``logging`` -> +``disable_loggers`` flag in the tracker's config is used to +enable/disable pre-existing loggers as there is no way to do this +in the logging config file. + +.. _`dictLogConfig`: + +dictConfig Based Logging Config +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +dictConfigs are specified in JSON format with support for +comments. The file name in the tracker's config for the +``logging`` -> ``config`` setting must end with ``.json`` to +choose the correct processing. + +Comments have to be in one of two forms based on javascript line +comments: + +1. A ``//`` possibly indented with whitespace on a line is + considereda a comment and is stripped from the file before + being passed to the json parser. This is a "line comment". + +2. A ``//`` with at least three white space characters before it + is stripped from the end of the line before being passed to + the json parser. This is an "inline comment". + +Block style comments are not supported. + +Other than this the file is a standard json file that matches the +`Configuration dictionary schema +`_ +defined in the Python documentation. + + +Example dictConfig Logging Config +................................. + +Note that this file is not actually JSON format as it include +comments. However by using javascript style comments, some tools +that treat JSON like javascript (editors, linters, formatters) +might work with it. A command like:: + + sed -e 's#^\s*//.*##' -e 's#\s*\s\s\s//.*##' logging.json + +can be used to strip comments for programs that need it. + +The config below works with the `Waitress wsgi server +`_ configured to use the +roundup.wsgi channel. It also controls the `TransLogger +middleware `_ configured to +use roundup.wsgi.translogger, to produce httpd style combined +logs. + +The log file is specified relative to the current working +directory not the tracker home. The tracker home is the +subdirectory demo under the current working directory. + +The config also expects the ``python-json-logger`` package to be +installed so that it can produce a jsonl (json line) formatted +output log file. This format is useful for sending to log +management/observability platforms like elasticsearch, splunk, +logly, or honeycomb. + +The commented config is:: + + { + "version": 1, // only supported version + "disable_existing_loggers": false, // keep the wsgi loggers + + "formatters": { + // standard format for Roundup messages + "standard": { + "format": "%(asctime)s %(trace_id)s %(levelname)s %(name)s:%(module)s %(message)s" + }, + // Used to dump all log requests in jsonl format. + // Each json object is on one line. Can be pretty printed + // using: + // python -m json.tool --json-lines --sort-keys < roundup.json.log + // jq --slurp --sort-keys . < roundup.json.log + // requires that you pip install python-json-logger + // * does not report the fields in reserved_attrs + // * example to remap a field in the log to traceID in + // the output json. (note trace_id_eg is not defined by + // logging + // * also adds the env atribute to json with the value of demo + "json": { + "()": "pythonjsonlogger.json.JsonFormatter", + "reserved_attrs": ["ROUNDUP_CONTEXT_FILTER_CALLED", + "msg", "pct_char", "relativeCreated"], + "rename_fields": { + "trace_id_eg": "traceID" + }, + "static_fields": { + "env": "demo" + } + }, + // used for waitress wsgi server to produce httpd style logs + "http": { + "format": "%(message)s %(trace_id)" + + } + }, + "handlers": { + // create an access.log style http log file + "access": { + "level": "INFO", + "formatter": "http", + "class": "logging.FileHandler", + "filename": "demo/access.log" + }, + // logging for roundup.* loggers + "roundup": { + "level": "DEBUG", + "formatter": "standard", + "class": "logging.FileHandler", + "filename": "demo/roundup.log" + }, + // handler for json output log file + "roundup_json": { + "level": "DEBUG", // "DEBUG", + "formatter": "json", + "class": "logging.FileHandler", + "filename": "demo/roundup.json.log" + }, + // print to stdout - fall through for other logging + "default": { + "level": "DEBUG", + "formatter": "standard", + "class": "logging.StreamHandler", + "stream": "ext://sys.stdout" + } + }, + "loggers": { + "": { + "handlers": [ + "default", + "roundup_json" // add json formatted logging + ], + "level": "DEBUG", + "propagate": false + }, + // used by roundup.* loggers + "roundup": { + "handlers": [ + "roundup", + "roundup_json" + ], + "level": "DEBUG", + "propagate": false // note pytest testing with caplog requires + // this to be true + }, + "roundup.hyperdb": { + "handlers": [ + "roundup" + ], + "level": "INFO", // can be a little noisy use INFO for production + "propagate": false + }, + "roundup.wsgi": { // using the waitress framework + "handlers": [ + "roundup" + ], + "level": "DEBUG", + "propagate": false + }, + "roundup.wsgi.translogger": { // httpd style logging + "handlers": [ + "access" + ], + "level": "DEBUG", + "propagate": false + }, + "root": { + "handlers": [ + "default" + ], + "level": "DEBUG", + "propagate": false + } + } + } + +fileConfig Based Logging Config +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The file config is an older and more limited method of +configuring logging. It is described by the `Configuration file +format +`_ +in the Python documentation. The file name in the tracker's +config for the ``logging`` -> ``config`` setting must end with +``.ini`` to choose the correct processing. + +Example fileConfig LoggingConfig +................................ + +This is an example .ini used with roundup-server configured to use +``roundup.http`` channel. It also includes some custom logging +qualnames/tags/channels for logging schema/permission detector and +extension output:: + + [loggers] + #other keys: roundup.hyperdb.backend + keys=root,roundup,roundup.http,roundup.hyperdb,actions,schema,extension,detector + + [logger_root] + #also for root where channlel is not set (NOTSET) aka all + level=DEBUG + handlers=rotate + + [logger_roundup] + # logger for all roundup.* not otherwise configured + level=DEBUG + handlers=rotate + qualname=roundup + propagate=0 + + [logger_roundup.http] + level=INFO + handlers=rotate_weblog + qualname=roundup.http + propagate=0 + + [logger_roundup.hyperdb] + level=WARNING + handlers=rotate + qualname=roundup.hyperdb + propagate=0 + + [logger_actions] + level=INFO + handlers=rotate + qualname=actions + propagate=0 + + [logger_detector] + level=INFO + handlers=rotate + qualname=detector + propagate=0 + + [logger_schema] + level=DEBUG + handlers=rotate + qualname=schema + propagate=0 + + [logger_extension] + level=INFO + handlers=rotate + qualname=extension + propagate=0 + + [handlers] + keys=basic,rotate,rotate_weblog + + [handler_basic] + class=StreamHandler + args=(sys.stderr,) + formatter=basic + + [handler_rotate] + class=logging.handlers.RotatingFileHandler + args=('roundup.log','a', 5120000, 2) + formatter=basic + + [handler_rotate_weblog] + class=logging.handlers.RotatingFileHandler + args=('httpd.log','a', 1024000, 2) + formatter=plain + + [formatters] + keys=basic,plain + + [formatter_basic] + format=%(asctime)s %(trace_id)s %(process)d %(name)s:%(module)s.%(funcName)s,%(levelname)s: %(message)s + datefmt=%Y-%m-%d %H:%M:%S + + [formatter_plain] + format=%(process)d %(message)s Configuring roundup-server @@ -223,6 +734,20 @@ Additional notes for each keyword: ``-----END CERTIFICATE-----``. If not specified, roundup will generate a temporary, self-signed certificate for use. +**loghttpvialogger** section + If you: + + * have **loghttpvialogger** enabled + * use **pidfile** + * use a logging config file in the tracker's config.ini + + it is essential to specify absolute paths for log files in the + tracker's logging.config file. The use of pidfile causes the + server to switch to the root directory ('/'). As a result + relative paths in the logging ini configuration file (as + opposed to the tracker's config.ini) will be written to the + system's root directory. The access error will cause the server + to exit. **trackers** section Each line denotes a mapping from a URL component to a tracker home. Make sure the name part doesn't include any url-unsafe characters like @@ -256,7 +781,7 @@ on the fly, compression is enabled by default, to disable it set:: dynamic_compression = No in the tracker's ``config.ini``. You should disable compression if -your proxy (e.g. nginx or apache) or wsgi server (uwsgi) is configured +your proxy (e.g. nginx or apache) is configured to compress responses on the fly. The python standard library includes gzip support. For brotli or zstd you will need to install packages. See the `installation documentation`_ for details. @@ -418,9 +943,9 @@ There are two ways to add a CSP: Fixed CSP --------- -If you are using a web server (Apache, Nginx) to run Roundup, you can -add a ``Content-Security-Policy`` header using that server. WSGI -servers like uWSGI can also be configured to add headers. An example +If you are using a web server (Apache, Nginx) to run Roundup, you +can add a ``Content-Security-Policy`` header using that +server. WSGI middleware can be written to add headers. An example header would look like:: Content-Security-Policy: default-src 'self' 'unsafe-inline' 'strict-dynamic'; @@ -443,6 +968,8 @@ when invoked. More secure CSPs can also be created. However because of the ability to customise the web interface, it is difficult to provide guidance. +.. _dynamic_csp: + Dynamic CSP ----------- @@ -469,7 +996,7 @@ directory that generates the CSP on the fly. For example:: } - def AddHtmlHeaders(client, header_dict=None): + def AddHtmlHeaders(self, header_dict=None): ''' Generate https headers from dict use default security headers Setting the header with a value of None will not inject the @@ -477,36 +1004,41 @@ directory that generates the CSP on the fly. For example:: Header values will be formatted with a dictionary including a nonce. Use to set a nonce for inline scripts. + + self is an instance of the TemplatingUtilities class, so + you have access to self.client as well as any functions added + using registerUtil. ''' try: - if client.client_nonce is None: + if self.client.client_nonce is None: # logger.warning("client_nonce is None") - client.client_nonce = client.session_api._gen_sid() + self.client.client_nonce = self.client.session_api._gen_sid() except AttributeError: - # client.client_nonce doesn't exist, create it + # self.client.client_nonce doesn't exist, create it # logger.warning("client_nonce does not exist, creating") - client.client_nonce = client.session_api._gen_sid() + self.client.client_nonce = client.session_api._gen_sid() headers = default_security_headers.copy() if isinstance(header_dict, dict): headers.update(header_dict) - client_headers = client.additional_headers + client_headers = self.client.additional_headers for header, value in list(headers.items()): if value is None: continue client_headers[header] = value.format( - nonce=client.client_nonce) + nonce=self.client.client_nonce) def init(instance): - instance.registerUtil('AddHtmlHeaders', AddHtmlHeaders) + # Note the use of the new (in version 2.5) registerUtilMethod + instance.registerUtilMethod('AddHtmlHeaders', AddHtmlHeaders) Adding the following to ``page.html`` right after the opening ```` tag:: - + will invoke ``AddHtmlHeaders()`` to add the CSP header with the nonce. @@ -523,6 +1055,42 @@ to:: for each script, object or style tag. +If you are using a version of Roundup before version 2.5, you need to +replace ``instance.registerUtilMethod`` with +``instance.registerUtil``. For example:: + + def init(instance): + instance.registerUtil('AddHtmlHeaders', AddHtmlHeaders) + +The AddHtmlHeaders function needs to be changed so that ``self.client`` +is replaced by ``client``:: + + # replace self parameter with client + def AddHtmlHeaders(client, header_dict=None): + ''' Generate https headers from dict use default security headers + + Setting the header with a value of None will not inject the + header and can override the default set. + + Header values will be formatted with a dictionary including a + nonce. Use to set a nonce for inline scripts. + ''' + + ### Then change all references to self.client to client + + try: + if client.client_nonce is None: # note self.client -> client + # logger.warning("client_nonce is None") + client.client_nonce = self.client.session_api._gen_sid() + + ... + +Lastly the client must be passed explicitly when calling +AddHtmlHeaders. The call looks like:: + + + + Remediating ``unsafe-inline`` ----------------------------- .. _remediating unsafe-inline: @@ -1305,6 +1873,106 @@ Because environment variables can be inadvertently exposed in logs or process listings, Roundup does not currently support loading secrets from environment variables. +.. _pgpconfig: + +Configuring PGP Email Support +============================= + +.. note:: + This section was written with the help of the Devin/DeepWiki AI. + +You have to install the gpg module using pip. See :ref:`directions for +installing gpg ` +in the upgrading document for more information. + +In your tracker's config.ini configure the following settings in the +``[pgp]`` section:: + + enable = yes + homedir = /path/to/pgp/configdir + roles = admin + +This will allow any user with the admin role to send signed pgp +email. If ``roles`` is not set, all users will need to use signed +emails. If it is not signed it will be rejected. Note that ``homedir`` +must be an absolute path. Unlike other path settings, a relative path +is not interpreted relative to the tracker home. See the documentation +in config.ini for more information and other settings (e.g. to send +encrypted emails from the tracker). + +When PGP is enabled and a message is signed with a valid signature, +the database transaction source (db.tx_Source) is set to +``email-sig-openpgp`` instead of ``email``. This allows you to +restrict certain operations (e.g. changing a private flag) to +authenticated/signed emails. + +Creating GPG Keys for the Tracker +--------------------------------- + +To generate a keypair use:: + + gpg --homedir /path/to/pgp/configdir --gen-key + +where the homedir directory matches the one you set in +config.ini. Note the gpg homedir must be created before you run the +command. You will be prompted for the full name of your tracker and +the email address for your tracker. You also need to do with as the +user who runs roundup (aka the roundup user) and the roundup email +gateway. Do not encrypt the key. + +Roundup has no mechanism for reading the private key if it is +encrypted. So make sure the permissions on the homedir only allow the +roundup user to read the files. + +You can export the public key for use by clients using:: + + gpg --homedir /path/to/pgp/configdir --export -a tracker@example.com > tracker-public.key + +with homedir and email matching the values used to generate the +key. This will allow users to import the public key and encrypt emails +to the tracker. + +The public gpg key for each user's email address must be imported. To +do this, obtain the user's public key for their primary email address +and import it using:: + + gpg --homedir /path/to/tracker/gpg --import user-public-key.asc + +You may also be able to get it from a public keyserver using:: + + gpg --recv-keys KEYID + +where the ``KEYID`` is supplied by the roundup user. + +While Roundup supports multiple addresses for each user, only the +primary address supports PGP signed or encrypted messages. + +You should verify that the public key is sane and has few signatures +attached. You can import a key into a throw away keystore:: + + mkdir throwaway + gpg --homedir throwaway -- import user-public-key.asc + gpg --homedir throwaway --list-sigs + +and verify that the number of sig lines is small (under 10 or so). If +it takes a long time to import you can kill the import without +affecting your production keystore. Large numbers of sig lines can +take a long time to import/access when compressed. See: +https://nvd.nist.gov/vuln/detail/CVE-2022-3219. + +.. comment: + Questions: + + Can roundup send signed emails? (looks like no, why??) + + Why are alternate addresses not supported for receiving PGP emails? + + Does Roundup ever send an email to an alternate email address? + + Should there be some way for a user to upload their own public key? + If so what ui (paste armored asci cert in textbox, upload ascii + file from user page and process)? + Tasks ===== @@ -1382,6 +2050,9 @@ reinstall the older version of the sofware using the same install command:: Migrating Backends ------------------ +Note that the ``[rdbms]`` section label was called ``[database]`` in +earlier versions of Roundup. + 1. Stop the existing tracker web and email frontends (preventing changes). 2. Use the roundup-admin tool "export" command to export the contents of your tracker to disk. (If you are running on windows see @@ -1390,7 +2061,7 @@ Migrating Backends export data.) 3. Copy the tracker home to a new directory. 4. Delete the "db" directory from the new directory. -5. Set the value of the ``backend`` key under the ``[database]`` +5. Set the value of the ``backend`` key under the ``[rdbms]`` section of the tracker's ``config.ini`` file. 6. Use the roundup-admin "import" command to import the previous export with the new tracker home. If non-interactively:: @@ -1415,6 +2086,57 @@ to set a higher or lower number in roundup-admin. In this example a commit will be done every 20,000 objects/rows. The pragma can also be set on the roundup-admin command line as described below. +Migrating Only Database Data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The method above is well tested and works. However because it +exports/imports file content and works on a copy of the tracker home +it is slow. An alternate way is to use the ``exporttables`` and +``importtables`` commands to export/import only the database entries +and do the migration in place. + +The untested steps using this method are: + +0. Backup your tracker. +1. Stop the existing tracker web and email frontends (preventing changes). +2. Use the roundup-admin tool's "exporttable" command to export the + database for your tracker to disk. (If you are running on windows see + `issue1441336 `_ + on how to use the command line rather than interactive mode to + export data.) +3. Set the value of the ``backend`` key under the ``[rdbms]`` + section of the tracker's ``config.ini`` file to the new database + backend. +4. Use the roundup-admin "importtable" command to import the + exporttable. The non-interactive command is:: + + roundup-admin -i importtable + + If running the importtable interactively, enter 'commit' before exiting. +5. Test each of the admin tool, web interface and mail gateway using the new + backend. +6. Restart web and email frontends. +7. Clean up the old database once you are confortable that the migration + has suceeded. + + If you are moving from an external database + (postgres/mysql/mariadb) to an embedded db, drop your external db + tables. + + If you are migrating from anydbm to sqlite, you can move/delete + files that match: + + - ``nodes.*`` + - ``_ids`` + - ``journals.*`` + - ``lock`` + + Keep the ``db/db`` file as that is your new sqlite database. + + Also if you run for a few days and find the ``otks`` and + ``sessions`` file change times are the same, you can move/delete + these as well. + Moving a Tracker ---------------- @@ -1672,6 +2394,8 @@ IMAPS_OAUTH: single: roundup-admin; man page reference pair: roundup-admin; designator +.. _`roundup-admin templates`: + Using roundup-admin =================== @@ -1749,6 +2473,9 @@ The basic usage is: Commands may be abbreviated as long as the abbreviation matches only one command, e.g. l == li == lis == list. +In interactive mode entering: ``q``, ``quit``, or ``exit`` alone on a +line will exit the program. + One thing to note, The ``-u user`` setting does not currently operate like a user logging in via the web. The user running roundup-admin must have read access to the tracker home directory. As a result the @@ -1839,13 +2566,16 @@ you can put the initialise command and password on the command line. But this allows others on the host to see the password (using the ps command). To initialise a tracker non-interactively without exposing the password, create a file (e.g init_tracker) set to mode -600 (so only the owner can read it) with the contents: +600 (so only the owner can read it) with the contents:: initialise admin_password -and feed it to roundup-admin on standard input. E.G. +and feed it to roundup-admin on standard input. E.G.:: - cat init_tracker | roundup-admin -i tracker_dir + cat init_tracker | roundup-admin -i tracker_dir -P history_features=2 + +setting the pragma ``history_features=2`` prevents storing the command +in the user's history file. (for more details see https://issues.roundup-tracker.org/issue2550789.) @@ -1878,6 +2608,57 @@ https://pythonhosted.org/pyreadline/usage.html#configuration-file. History is saved to the file ``.roundup_admin_history`` in your home directory (for windows usually ``\Users\``. +In Roundup 2.6.0 and newer, you can use the ``readline`` command to +make changes on the fly. + +* ``readline vi`` - change input mode to use vi key binding when + editing. It starts in entry mode. +* ``readline emacs`` - change input mode to emacs key bindings when + editing. This is also the default. +* ``readline reload`` - reloads the ``~/.roundup_admin_rlrc`` file so + you can test and use changes. +* ``readline history`` - dumps the history buffer and numbers all + commands. +* ``readline .inputrc_command_line`` can be used to make on the fly + key and key sequence bindings to readline commands. It can also be + used to change the internal readline settings using a set + command. For example:: + + readline set bell-style none + + will turn off a ``visible`` or ``audible`` bell. Single character + keybindings:: + + readline Control-o: dump-variables + + to list all the variables that can be set are supported. As are + multi-character bindings:: + + readline "\C-o1": "commit" + + will put "commit" on the input line when you type Control-o followed + by 1. See the `readline manual for details + `_ + on the command lines that can be used. + +Also a limited form of ``!`` (bang) history reference was added. The +reference must be at the start of the line. Typing ``!23`` will rerun +command number 23 from your history. + +Typing ``!23:p`` will load command 23 into the buffer so you can edit +and submit it. Using the bang feature will append the command to the +end of the history list. + +Pyreadline3 users can use ``readline history`` and the +bang commands (including ``:p``). Single character bindings can be +done. For example:: + + readline Control-w: history-search-backward + +The commands that are available are limited compared to Unix's +readline or libedit. Setting variables or entry mode (emacs, +vi) switching do not work in testing. + Using with the shell -------------------- diff --git a/doc/admin_help.html b/doc/admin_help.html index 082abc354..c5ff743a9 100644 --- a/doc/admin_help.html +++ b/doc/admin_help.html @@ -1,496 +1,530 @@ - +

+

- +

+

- +

+

- +

+

- +

+

- +

+

- +

+

- +

+Create a new tracker config file with default values in filename. +See also updateconfig. +

+

- +

+

- +

+

- +

+

- +

+

- +

+

- +

+

- +

+

- +

+

- +

+

- +
    2001-01-01
+

+

+

- +

+

+

- +

+

- +

+

- +

+

- +

+

- +

+

- +

+

- +

+

+

- +

+

- +

+

- +

+

- +

+

commit- commit -
-Commit changes made to the database during an interactive session.
+    

+

+Commit changes made to the database during an interactive session. +

The changes made during an interactive session are not automatically written to the database - they must be committed using this command. - +

One-off commands on the command-line are automatically committed if they are successful. - -

create- create classname property=value ... -
-Create a new entry of a given class.
+    

classname property=value ...

+

+Create a new entry of a given class. +

This creates a new entry of the given class using the property name=value arguments provided on the command line after the "create" command. - -

display- display designator[,designator]* -
-Show the property values for the given node(s).
+    

designator[,designator]*

+

+Show the property values for the given node(s). +

A designator is a classname and a nodeid concatenated, eg. bug1, user10, ... - +

This lists the properties and their associated values for the given node. - -

export- export [[-]class[,class]] export_dir -
-Export the database and file content.
+    

[[-]class[,class]] export_dir

+

+Export the database and file content. +

Database content is exported to colon separated files. To exclude the files (e.g. for the msg or file class), use the exporttables command. - +

Optionally limit the export to just the named classes or exclude the named classes, if the 1st argument starts with '-'. - +

This action exports the current data from the database into colon-separated-value files that are placed in the nominated export_dir directory. - -

exporttables- exporttables [[-]class[,class]] export_dir -
-Export only the database to files, no file content.
+    

[[-]class[,class]] export_dir

+

+Export only the database to files, no file content. +

Database content is exported to colon separated files. The files below $TRACKER_HOME/db/files/ (which can be archived separately) are not part of the export. To include the files, use the export command. - +

Optionally limit the export to just the named classes or exclude the named classes, if the 1st argument starts with '-'. - +

This action exports the current data from the database into colon-separated-value files that are placed in the export_dir destination directory. - -

filter- filter classname propname=value ... -
-Find the nodes of the given class with a given property value.
+    

classname propname=value ...

+

+Find the nodes of the given class with a given property value. +

Find the nodes of the given class with a given property value. Multiple values can be specified by separating them with commas. If property is a string, all values must match. I.E. it's an 'and' operation. If the property is a link/multilink any value matches. I.E. an 'or' operation. - -

find- find classname propname=value ... -
-Find the nodes of the given class with a given link property value.
+    

classname propname=value ...

+

+Find the nodes of the given class with a given link property value. +

Find the nodes of the given class with a given link property value. The value may be either the nodeid of the linked node, or its key value. - -

genconfig- genconfig filename -
-Create a new tracker config file with default values in filename.
+    

filename

-
get- get property designator[,designator]* -
-Get the given property of one or more designator(s).
+    

property designator[,designator]*

+

+Get the given property of one or more designator(s). +

A designator is a classname and a nodeid concatenated, eg. bug1, user10, ... - +

Retrieves the property value of the nodes specified by the designators. - -

help- help topic -
-Give help about topic.
+    

topic

+

+Give help about topic. +

commands -- list commands <command> -- help specific to a command initopts -- init command options all -- all available help - -

history- history designator [skipquiet] [raw] -
-Show the history entries of a designator.
+    

designator [skipquiet] [raw]

+

+Show the history entries of a designator. +

A designator is a classname and a nodeid concatenated, eg. bug1, user10, ... - +

Lists the journal entries viewable by the user for the node identified by the designator. If skipquiet is added, journal entries for quiet properties are not shown. If raw is added, the output is the raw representation of the journal entries. - -

import- import import_dir -
-Import a database and file contents from the directory.
+    

import_dir

+

+Import a database and file contents from the directory. +

The directory should have the same format as one containing the output of export. There are two files imported per class. The files used in the import are: - +

<class>.csv - This must define the same properties as the class (including - having a "header" line with those property names.) + This must define the same properties as the class + (including having a "header" line with those + property names.) +

<class>-journals.csv - This defines the journals for the items being imported. - + This defines the journals for the items + being imported. +

The imported nodes will have the same nodeid as defined in the import file, thus replacing any existing content. - +

The new nodes are added to the existing database - if you want to create a new database using the imported data, then create a new database (or, tediously, retire all the old data.) - -

importtables- importtables export_dir -
-This imports the database tables exported using exporttables.
+    

export_dir

+

+This imports the database tables exported using exporttables. +

It does not import the content of files like msgs and files. - -

initialise- initialise [adminpw] -
-Initialise a new Roundup tracker.
+    

[adminpw]

+

+Initialise a new Roundup tracker. +

The administrator details will be set at this step. - +

Execute the tracker's initialisation function dbinit.init() - -

install- install [template [backend [key=val[,key=val]]]] -
-Install a new Roundup tracker.
+    

[template [backend [key=val[,key=val]]]]

+

+Install a new Roundup tracker. +

The command will prompt for the tracker home directory (if not supplied through TRACKER_HOME or the -i option). The template and backend may be specified on the command-line as arguments, in that order. - +

Command line arguments following the backend allows you to pass initial values for config options. For example, passing "web_http_auth=no,rdbms_user=dinsdale" will override defaults for options http_auth in section [web] and user in section [rdbms]. Please be careful to not use spaces in this argument! (Enclose whole argument in quotes if you need spaces in option value). - +

The initialise command must be called after this command in order to initialise the tracker's database. You may edit the tracker's initial database contents before running that command by editing the tracker's dbinit.py module init() function. - +

See also initopts help. - -

list- list classname [property] -
-List the instances of a class.
+    

classname [property]

+

+List the instances of a class. +

Lists all instances of the given class. If the property is not specified, the "label" property is used. The label property is tried in order: the key, "name", "title" and then the first property, alphabetically. - +

With -c, -S or -s print a list of item id's if no property specified. If property specified, print list of that property for every class instance. - -

migrate- migrate -
+    

+ +

Update a tracker's database to be compatible with the Roundup codebase. - +

You should run the "migrate" command for your tracker once you've installed the latest codebase. - +

Do this before you use the web, command-line or mail interface and before any users access the tracker. - +

This command will respond with either "Tracker updated" (if you've not previously run it on an RDBMS backend) or "No migration action required" (if you have run it, or have used another interface to the tracker, or possibly because you are using anydbm). - +

It's safe to run this even if it's not required, so just get into the habit. - -

pack- pack period | date -
-Remove journal entries older than the date/period.
+    

period | date

+

+Remove journal entries older than the date/period. +

A period is specified using the suffixes "y", "m", and "d". The suffix "w" (for "week") means 7 days. - - "3y" means three years - "2y 1m" means two years and one month - "1m 25d" means one month and 25 days - "2w 3d" means two weeks and three days - +

+

    "3y" means three years
+
    "2y 1m" means two years and one month
+
    "1m 25d" means one month and 25 days
+
    "2w 3d" means two weeks and three days
+

Date format is "YYYY-MM-DD" eg: - 2001-01-01 - - -

perftest- perftest [mode] [arguments]* -
-Time operations in Roundup.
+    

[mode] [arguments]*

+

+Time operations in Roundup. +

Supported arguments: - - [password] [rounds=<integer>] [scheme=<scheme>] - +

+

    [password] [rounds=<integer>] [scheme=<scheme>]
+

'password' is the default mode. The tracker's config.ini setting for 'password_pbkdf2_default_rounds' is the default value for 'rounds'. On the command line, 'rounds' can include thousands separator of ',' or '.'. 'scheme' is the default coded into Roundup. List supported schemes by using 'scheme='. - - -

pragma- pragma setting=value | 'list' -
-Set internal admin settings to a value.
+    

setting=value | 'list'

+

+Set internal admin settings to a value. +

For example: - - pragma verbose=True - pragma verbose=yes - pragma verbose=on - pragma verbose=1 - +

+

    pragma verbose=True
+
    pragma verbose=yes
+
    pragma verbose=on
+
    pragma verbose=1
+

will turn on verbose mode for roundup-admin. - - pragma list - +

+

    pragma list
+

will show all settings and their current values. If verbose is enabled hidden settings and descriptions will be shown. - -

reindex- reindex [classname|classname:#-#|designator]* -
-Re-generate a tracker's search indexes.
+    

[classname|classname:#-#|designator]*

+

+Re-generate a tracker's search indexes. +

This will re-generate the search indexes for a tracker. This will typically happen automatically. - +

You can incrementally reindex using an argument like: - - reindex issue:23-1000 - +

+

    reindex issue:23-1000
+

to reindex issue class items 23-1000. Missing items are reported but do not stop indexing of the range. - -

restore- restore designator[,designator]* -
-Restore the retired node specified by designator.
+    

designator[,designator]*

+

+Restore the retired node specified by designator. +

A designator is a classname and a nodeid concatenated, eg. bug1, user10, ... - +

The given nodes will become available for users again. - -

retire- retire designator[,designator]* -
-Retire the node specified by designator.
+    

designator[,designator]*

+

+Retire the node specified by designator. +

A designator is a classname and a nodeid concatenated, eg. bug1, user10, ... - +

This action indicates that a particular node is not to be retrieved by the list or find commands, and its key value may be re-used. - -

rollback- rollback -
-Undo all changes that are pending commit to the database.
+    

+

+Undo all changes that are pending commit to the database. +

The changes made during an interactive session are not automatically written to the database - they must be committed manually. This command undoes all those changes, so a commit immediately after would make no changes to the database. - -

security- security [Role name] -
-Display the Permissions available to one or all Roles.
+    

[Role name]

+

+Display the Permissions available to one or all Roles. +

Also validates that any properties defined in a permission are valid. - +

Run this after changing your permissions to catch typos. - -

set- set items property=value [property=value ...] -
-Set the given properties of one or more items(s).
+    

items property=value [property=value ...]

+

+Set the given properties of one or more items(s). +

The items are specified as a class or as a comma-separated list of item designators (ie "designator[,designator,...]"). - +

A designator is a classname and a nodeid concatenated, eg. bug1, user10, ... - +

This command sets the properties to the values for all designators given. If a class is used, the property will be set for all items in the class. If the value is missing (ie. "property=") then the property is un-set. If the property is a multilink, you specify the linked ids for the multilink as comma-separated numbers (ie "1,2,3"). - - -

specification- specification classname -
-Show the properties for a classname.
+    

classname

+

+Show the properties for a classname. +

This lists the properties for a given class. - -

table- table classname [property[,property]*] -
-List the instances of a class in tabular form.
+    

classname [property[,property]*]

+

+List the instances of a class in tabular form. +

Lists all instances of the given class. If the properties are not specified, all properties are displayed. By default, the column widths are the width of the largest value. The width may be explicitly defined by defining the property as "name:width". For example:: - - roundup> table priority id,name:10 - Id Name - 1 fatal-bug - 2 bug - 3 usability - 4 feature - +

+

    roundup> table priority id,name:10
+
    Id Name
+
    1  fatal-bug
+
    2  bug
+
    3  usability
+
    4  feature
+

Also to make the width of the column the width of the label, leave a trailing : without a width on the property. For example:: - - roundup> table priority id,name: - Id Name - 1 fata - 2 bug - 3 usab - 4 feat - +

+

    roundup> table priority id,name:
+
    Id Name
+
    1  fata
+
    2  bug
+
    3  usab
+
    4  feat
+

will result in a the 4 character wide "Name" column. - -

templates- templates [trace_search] -
-List templates and their installed directories.
+    

[trace_search]

+

+List templates and their installed directories. +

With trace_search also list all directories that are searched for templates. - -

updateconfig- updateconfig <filename> -
-Merge existing tracker config with new settings.
+    

<filename>

+

+Merge existing tracker config with new settings. +

Output the updated config file to <filename>. Use current settings from existing roundup tracker in tracker home. - -

diff --git a/doc/announcement.txt b/doc/announcement.txt index f04286aba..0a4f07e16 100644 --- a/doc/announcement.txt +++ b/doc/announcement.txt @@ -1,15 +1,14 @@ -I'm proud to release version 2.4.0 of the Roundup issue +I'm proud to release version 2.5.0 of the Roundup issue tracker. This release is a bugfix and feature release, so make sure to read `docs/upgrading.txt `_ to bring your tracker up to date. -The 79 changes, as usual, include some new features and many +The 42 changes, as usual, include some new features and many bug fixes. -Version 2.4.0 will be the last release to support Python -2. The next minor release, planned for mid 2025, will occur -5 years after Roundup started supporting Python 3. +Version 2.5.0 does not support Python 2. The minimum Python +version is 3.7. Note that you should run ``roundup-admin ... migrate`` to update the database schema version. Do this before you use @@ -26,73 +25,109 @@ You can install it with:: then unpack and test/install from the tarball. -Among the notable improvements in 2.4.0 from the 2.3.0 -release are: +Among the significant enhancements in version 2.5.0 compared to +the 2.4.0 release are: + +* **XSS vulnerability with devel and responsive templates fixed** -* three CVE's have been fixed. One requires changes to your - tracker's home directory. The other two are fixed by - installing 2.4.0. See - https://www.roundup-tracker.org/docs/security.html for - details and instructions on how to fix these in 2.4.0 and - earlier releases. + Just before release an XSS security issue with trackers based on + the devel or responsive templates was discovered. The updating + directions include instructions on fixing this issue with the + html templates. -* new classhelper component thanks to a team of students - from CS682 at U-Mass Boston. This fixes many issues with - the old classhelper. It is implemented as a web-component - and needs REST interface access. It will fall back to the - classic classhelper if REST is not available or if the - browser does not support web-components. +* **The property/field advanced search expression feature has been + enhanced and documented.** -* fix Windows Python installation using pip. It used to go - into an infinite loop during install or download. Also fix - installation of shared files (templates) so roundup-admin - can find them. + Search expressions are usually built using the + expression editor on the search page. They can be built manually + by modifying the search URL but the RPN search expression format + was undocumented. Errors in expressions could return results that + didn't match the user's intent. This release documents the RPN + expression syntax, adds basic expression error detection, and + improves error reporting. -* using ``@current_user`` as a value in a search URL for a - user property will use the current logged in user. Now you - can share searches like: "My issues" as "my" will become - the current logged in user. +* **The default hash method for password storage is more secure.** -* login failures to the REST/XML-RPC interfaces are now rate - limited to limit password guessing attacks. + We use PBKDF2 with SHA512 (was SHA1). With this change you can + lower the value of password_pbkdf2_default_rounds in your + tracker's config.ini. Check the upgrading documentation for more + info. (Note this may cause longer authentication times, the + upgrade doc describes how to downgrade the hash method if required.) -* utf8mb4 is the default charset for MySQL. This requires - migrating your database using the mysql client. You can - choose to keep the older character set in config.ini. +* **Roundup's session token is now prefixed with the magic + ``__Secure__`` tag when using HTTPS.** -* PostgreSQL services defined in pg_service.conf can be - used. PostgreSQL schemas are supported to eliminate the - need for the roundup user to have database - creation/deletion privileges. + This adds another layer of protection in addition to the + existing ``Secure`` property that comes with the session cookie. -* fix out of memory issue when importing larger trackers - into PostgreSQL. +* **Data authorization can be done at the database level speeding up + display of index pages.** -* multiple roundup-admin improvements: display protected - properties (like creation date), better formatting of - output, command history. Also on windows, pyreadline3 is - supported to provide an editable interactive command line. + Roundup verifies the user's authorization for the data fetched + from the database after retrieving data from the database. A new + optional ``filter`` argument has been added to Permission + objects. When the administrator supplies a filter function, it + can boost performance with SQL server databases by pushing + selection criteria to the database. By offloading some + permission checks to the database, less data is retrieved from + the database. This leads to quicker display of index pages with + reduced CPU and network traffic. -* an experimental wsgi performance improvement in 2.3.0 is - now now the default and is opt-out. +* **The REST endpoint can supply binary data (images, pdf, ...) to + its clients.** -* new template functions: utils.readfile and - utils.expandfile. Javascript that is included in the - Python core will be moved to external files and be able to - have values from Roundup substituted in the Javascript. + Requesting binary data from a REST endpoint has been a + hassle. Since JSON can't handle binary data, images (and other + binary data) need to be encoded. This makes them significantly + larger. The workaround was to use a non-REST endpoint for fetching + non-text attachments. This update lets the REST endpoint return + raw message or file content data. You can utilize the + ``binary_content`` endpoint along with an appropriate ``Accept`` + header (e.g. ``image/jpeg``) in your request. -* allow content-type of a template to be set from inside the - template. This allows returning json or xml from a - template without a .json or .xml extention. +* **Extract translatable strings from your tracker easily.** -* fix import/export on windows to use Unix style line - endings fixing export/import on Windows and making exports - portable across platforms. + The ``roundup-gettext`` tool has been enhanced to extract + translatable strings from detectors and extensions. This will + simplify the process of translating your trackers. -* various other Windows platform fixes including test suite - fixes. +Other miscellaneous fixes include: -* sqlite version 1 and StructuredText support removed. +* Fix a crash bug on Windows with Python 3.13. + +* Update documentation on required REST headers, along with other + documentation updates. + +* Improve handling of an error condition generated when an invalid + REST response format is requested. For example if XML output is + requested, but dicttoxml is not installed, we now return an + error without doing any work. + +* Fix an incorrect error report when a PUT REST request sets + the user's email address to its current value. + +* Add support for the ``defusedxml`` Python module to enhance + security when using XML. + +* Introduce the templating function: + ``utils.set_http_response(integer)`` to set the HTTP return code + directly from your template. This allows the template logic to + return a 404 or other code when the user invokes a template + incorrectly. + +* Add a new ``registerUtilMethod('name', my_function)``. which + makes it easier to define and use complex templating utilities. + It passes a default argument that allows access to the client + instance, translation functions, and other templating utility + functions. Previously you had to pass the arguments explicitly + when calling the utility from the template. + +* Add the ability to generate native HTML date and + number/integer inputs. Check the upgrading document for caveats. + This feature is disabled by default. + +* Re-enable support for GPG/PGP signed emails, which requires + installation from the test PyPi repository. The file CHANGES.txt has a detailed list of feature additions and bug fixes for each release. The most recent @@ -117,12 +152,12 @@ all your trackers to update the database schema version. Do this before you use the web, command-line or mail interface and before any users access the tracker. -Roundup requires Python 2 newer than version 2.7.12 or Python 3 -newer than or equal to version 3.6 for correct operation. (Python -3.4 or 3.5 may work, but are not tested.) Note that Roundup 2.4.0 -will be the last release to support Python 2. You should deploy -new trackers with Python 3 and plan on upgrading older trackers -from Python 2 to Python 3. See the upgrade guide. +Roundup requires Python 3 newer than or equal to version 3.7 for +correct operation. (Python 3.4 or 3.5, or 3.6 may work, but are not +tested.) Note that Roundup 2.4.0 was the last release to support +Python 2. You should deploy new trackers with Python 3 and plan on +upgrading older trackers from Python 2 to Python 3. See the upgrade +guide. To give Roundup a try, just download (directions above), unpack and run:: @@ -164,7 +199,7 @@ The system facilitates communication among the participants by managing discussions and notifying interested parties when issues are edited. One of the major design goals for Roundup that it be simple to get going. Roundup is therefore -usable "out of the box" with any Python 3.6+ +usable "out of the box" with any Python 3.7+ installation. It doesn't even need to be "installed" to be operational, though an install script is provided. @@ -182,270 +217,146 @@ and postgresql). Recent Changes ============== -From 2.3.0 to 2.4.0 +From 2.4.0 to 2.5.0 Fixed: -- CVE-2024-39124 - The classhelpers (_generic.help.html) are - vulnerable to an XSS attack. A specially crafted URL that used - that endpoint would result in running a script embedded in the - URL. (Found/reported by Alec Romano (4rdr), fix/tests John - Rouillard) -- CVE-2024-39125 - If the Referer header is set to a script tag, - it will be executed when the error in the Referer header is - reported. (Found/reported by Alec Romano (4rdr), fix/tests John +- issue2551343 - Remove support for PySQLite. It is unmaintained + and sqlite3 is used which is the default for a Python + distribution. (John Rouillard) +- replace use of os.listdir with os.scandir. Performance + improvement. Using with Python 2 requires 'pip install + scandir'. (John Rouillard) +- issue2551131 - Return accept-patch if patch body not accepted + (415 code). Accept-Patch returned with acceptable values. (John Rouillard) -- CVE-2024-39126 - PDF, XML and SVG files attached to an issue can contain - embedded JavaScript. This JavaScript was executed when the file was - accessed. PDF files are now downloaded and not displayed in the - browser. A content security policy is added for all download files - which prevents code execution in SVG files. (Found/reported by Alec - Romano (4rdr), fix/tests John Rouillard) -- issue2551282 - MySQL utf8mb4 issues and - issue2551115 - Use utf8mb4 as a default for MySQL instead of utf8 - The default database type and collations have been set to: - utf8mb4, utf8mb4_unicode_ci and utf8mb4_0900_bin. They are (sadly) - configurable from config.ini. Require directions on upgrading the - MySQL db have been documented in upgrading.txt. -- issue2551063 - Rest/Xmlrpc interfaces needs failed login protection. - Failed API login rate limiting with expiring lockout added. (John +- issue2551074 - In "responsive" template: click on hide comment leads + to a red error msg. (Report by Ludwig Reiter; fix John Rouillard) +- issue2550698 - added documentation on filtering using RPN property + expressions. (John Rouillard) +- issue2551372 - Better document necessary headers for REST and fix + logging to log missing Origin header (Ralf Schlatterbeck with + suggestions on documentation by John Rouillard) +- issue2551289 - Invalid REST Accept header with post/put performs + change before returning 406. Error before making any changes to the + db if we can't respond with requested format. (John Rouillard) +- issue2551356 - Add etag header when If-Modified-Since GET request + returns not-modified (304). Breaking change to function signature + for client.py-Client::_serve_file(). (John Rouillard) +- issue2551381 - roundup-server parses URI's with multiple '?" + incorrectly. (John Rouillard) +- issue2551382 - invalid @verbose, @page_* values in rest uri's + generate 409 not 400 error. (John Rouillard) +- fix issues with rest doc and use of PUT on a property item. Response + is similar to use of PUT on the item, not a GET on the + item. Discovered while fuzz testing. (John Rouillard) +- issue2551383 - Setting same address via REST PUT command results in + an error. Now the userauditor does not trigger an error if a user + sets the primary address to the existing value. (John Rouillard) +- issue2551253 - Modify password PBKDF2 method to use SHA512. The + default password hashing algorithm has been upgraded to + PBKDF2-SHA512 from PBKDF2-SHA1. The default pbkdf2 rounds in the + config file has been changed to 250000. The admin should change it + manually if it is at 2 million. PBKDF2-SHA512 (PBKDF2S5) has been + available since release 2.3, but it required a manual step to make + it the default. (John Rouillard) +- fixed a crash with roundup-admin perftest password when rounds not set + on command line. (John Rouillard) +- issue2551374 - Add error handling for filter expressions. Filter + expression errors are now reported. (John Rouillard) +- issue2551384: Modify flow in client.py's REST handler to verify + authorization earlier. The validation order for REST requests + has been changed. Checking user authorization to use the REST + interface is done before validating the Origin header. As a + result, incorrectly formatted CORS preflight requests + (e.g. missing Origin header) can now return HTTP status 403 as + well as status 400. (John Rouillard) +- issue2551387 - TypeError: not indexable. Fix crash due to + uninitialized list element on a (Mini)FieldStorage when unexpected + input is posted via wsgi. (Reported and debugged by Christof + Meerwald; fix John Rouillard) +- close http socket and send a 408 status when a timeout exception + is handed in roundup-server. This prevents another exception + caused by using a timed out socket. (John Rouillard) +- issue2551391, partial fix for issue1513369. input fields were + not getting id's assigned. Fixed automatic id assignment to + input fields. Thinko in the code. (John Rouillard) +- issue1895197 - translated help texts in admin.py not displayed + correctly. (Initial patch tobias-herp, John Rouillard) +- issue2551238 - roundup-server should exit with error if -d + is used without -l . Added code to report + the issue. Added issue with relative paths for log file whn + using -L and -d with roundup-server. (John Rouillard) +- Allow the specification of a "form" parameter for Date fields to make + the popup calendar work when the enclosing form has a name different + from "itemSynopsis". (Ralf Schlatterbeck) +- issue2551376: Fix tracebacks in item templates (Ralf Schlatterbeck) +- issue2551396: Use of os.path.stat.ST_MTIME in python 3.13 crashes + roundup on windows. Replaced with equivalent stat.ST_MTIME. (Randy + on IRC, fix: John Rouillard and R. David Murray (bitdancer)) +- issue2551323: remove functions used for XHTML template + support. XHTML was deprecated in Roundup 2.3.0 and an invalid value + in 2.4.0. (John Rouillard) +- issue2551406: 'Templating Error: too many values to unpack' crash + fixed. (reported by and patch Christof Meerwald, commit/test John Rouillard) -- issue2551184 - improve i18n handling. Patch to test to make sure it - uses the test tracker's locale files and not other locale - files. (Marcus Priesch) -- issue2551283 - fail if version 2.4.9 of markdown2 is used, it broke - [issue1](issue1) style links. Support markdown2 2.4.8 and earlier - and 2.4.10 with its new schema filtering method. (John Rouillard) -- multiple flake8 fixes (John Rouillard) -- rename loop variable in 'for sendto in sendto:' (John Rouillard) -- issue2551193 - Fix roundup for removal of cgi and cgitb standard - python modules (and FieldStorage/MiniFieldStorage). Replaced imports - from cgi to use roundup.anypy.cgi\_ which will load the system cgi - unless it is missing. Then it will load roundup.anypy.vendored.cgi - and make \*FieldStorage symbols available. Roundup uses its own - cgitb.py and not the system cgitb.py. It looks like it's the - precursor to the system cgitb.py. (John Rouillard) -- issue2551278 - datetime.datetime.utcnow deprecation. Replace - calls with equivalent that produces timezone aware dates rather than - naive dates. (John Rouillard) -- when using "roundup-admin display" indent the listing only if - headers or protected fields are requested. This makes the output - look like it did previously to 2.3.0 if the new features aren't - used. Roundup-admin output was never meant to be machine parsed, but - don't break it unless required. (John Rouillard) -- issue2551290 - pip install roundup Hangs on Windows 10 - The install under windows goes into an infinite loop using pip or - source install. (John Rouillard) -- Document use of pyreadline3 to allow roundup-admin to have CLI editing - on windows. (John Rouillard) -- issue2551293 - remove schema_hook from Tracker instance. Looks like - it was an obsolete hook used for testing. Never documented and not - accessible from schema.py. -- Fix roundup-admin security command. Lowercase its optional - argument. Roles are indexed by lower case role name. So 'security - User' and 'security user' should generate the same output. (John - Rouillard from issue on mailing list by Chuck Cunningham) -- make roundup-server exit more quickly on ^C. This seems to be - limited to windows. (John Rouillard) -- Fix error handling so failure during import of a non-user item - doesn't cause a second traceback. (Found by Norbert Schlemmer, fix - John Rouillard) -- Handle out of memory error when importing large trackers in - PostgreSQL. (Found by Norbert Schlemmer, extensive testing by - Norbert, fix John Rouillard) -- use unittest.mock rather than mock for - test/test_hyperdbvals.py. (found by Ralf Schlatterbeck. Fix John - Rouillard) -- disable proxy with wget in roundup_healthcheck. (Norbert Schlemmer - Noschvie on github.com) -- support dicttoxml2.py for Roundup running on 3.7 and - newer. dicttoxml uses a type alias: collection.Iterator that is - dropped in Python 3.10. (found by Norbert Schlemmer, fix John - Rouillard) -- fix duplicate html id 'password' in user.item.html in all templates except - jinja2. (John Rouillard) -- fix unclosed file when saving index in indexer_dbm.py. (John Rouillard) -- fix task index in devel tracker so it doesn't cause a crash if all - fields are selected. (John Rouillard) -- fix windows install. When using pip share directory is installed in - a directory tree under the lib directory. Fix it so that Lib/share - is used to install the share tree. The lets Roundup find tracker - templates and translation files. (Found by Simon Eigeldinger, fix - John Rouillard) -- fix roundup-demo, interactive mode would nuke an existing tracker. - (Found Tonu Mikk, fix John Rouillard) -- fix detection/reporting when using a SQLite3 library without FTS5 - support. Install docs updated to state that FTS5 support is required - when using SQLite for back end. (Found Tonu Mikk, fix John - Rouillard) -- issue2551320: user.help-search.html doesn't respect - properties. Setting url parameter properties when using the - classhelp for users now shows the requested properties. (Found by - Patel Malav and Nikunj Thakkar of the UMass-Boston CS682 Spring - 2024 class; fix John Rouillard) -- use ast.eval_literal() rather than eval() to turn CSV exported - string values into Python object/values. -- use template's guess at Content-Type in headers only if Content-Type - is not already set. This allows a template to set its own content - type. For example: _generic.translate can set content type (via - request.client.additional_headers) to application/json and return - json from the template. This json could access the 1i18n functions - for a javascript helper. (John Rouillard) -- when template processing raises an exception the line number is - sometimes missing. This causes cgitb to raise a second exception - which clobbers the info about the template issue. As a stop-gap set - the line number to -1 so the original traceback can be seen. This - could be a bug in ZopeTAL. (John Rouillard) -- issue2551328 - REST results show next link if number of results is a - multiple of page size. There should be no next link. (Found by Patel - Malav and Bharath Kanama of the UMass-Boston CS682 Spring 2024 - class; fix John Rouillard) -- issue2551264 - REST X-Total-Count header and @total_size count - incorrect when paginated - correct values are now returned. - (John Rouillard) -- issue2551331 - Fix repeat first/last methods. (John Rouillard) -- Fix import/export on windows. Use unix line terminating characters. - (John Rouillard) -- Fix anydbm session/otks clear() method on windows when backed by - dumbdbm. Also make anydbm detect the initialized database when - using dumbdbm. (John Rouillard) -- Use of '-' directory in static_files config option under windows - Python fixed. (John Rouillard) -- issue2551334 - number of test bugs that prevented test suite from - running under Windows Python are fixed. WIP. (John Rouillard) -- issue2551302 - Remove support for sqlite version 1 from - back_sqlite.py. We have been using sqlite3 for over a decade. (John - Rouillard) -- issue2551285 - Remove StructuredText support. reStructuredText is - still supported. (John Rouillard) -- Use roundup-demo -p option to set listening port. Was ignored - before. (John Rouillard) -- issue2551346 - Classic tracker's statusauditor raises error if - detectors/config.ini missing - STATUSAUDITOR_CHATTING_REQUIRES_TWO_USERS. The statusauditor.py for - jinja2 and classic templates has been changed to assume that this - option is off when the setting is missing from - detectors/config.ini. Other templates do not implement this option. - (John Rouillard) -- issue2551350 - Python changes for 3.12 with roundup 2.3.0. Fixes for - cgitb.py crash due to pydoc.html.header() signature change. (Patch - by Andrew (kragacles), applied John Rouillard) -- issue2551350 - Python changes for 3.12 with roundup 2.3.0. Fixes for - mailer.py crash due to change in starttls signature change. (Patch - by Andrew (kragacles), modified and applied John Rouillard) -- make classhelper link open in a new window by setting - target="_blank". This prevents overwriting of current page with the - classhelper if javascript is disabled. (John Rouillard) -- issue2551341 - if @columns missing from an index url, the - group headers colspan property = 0. Add "or 100" in - stanza's so headers span all rows (up to 100). -- fix roundup-server response requiring a 301 redirect. Did - not set content length leading to hang/error. (John - Rouillard) -- report basename of filename when template file is invalid - rather than reporting a TypeError. (John Rouillard) -- Make Last-Modified header use GMT not -0000 timezone. Fix error - reported by redbot testing. (John Rouillard) -- Send Vary: Accept-Encoding on any file that could be compressed - even if the file is not encoded/compressed. Found by Redbot - testing. (John Rouillard) -- make If-None-Match work for static file (@@file) case. Found by - Redbot testing (John Rouillard) -- Send vary: accept-encoding for if-modified-since conditional - requests where the file is not modified. (John Rouillard) -- Update JWT example in rest.py to use replacement for - datetime.datetime.utcnow(). (John Rouillard) -- issue2551219 - document requirements of PEM file when using - roundup-server in SSL/TLS mode. Report better error messages - when PEM file is missing certificate or private key. (John - Rouillard) -- Cleanup tracker index generation by roundup-server. Send - correct Content-Length headers so HTTP/1.1 connections don't - hang. (John Rouillard) -- Fix delay when using csv export actions. The CSV file is written - incrementally, so we can't determine the Content-Length. When using - HTTP/1.1, this causes a delay while the browser waits for a timeout. - Forcing the connection to close after the CSV file is written - removes the delay. (John Rouillard) +- fix potential HTTP Response Splitting issue in + roundup-server. Discovered by CodeQL in CI. (John Rouillard) Features: -- issue2551323 - Remove XHTML support. Disabled option to set - html_version to xhtml. Running roundup commands with html_version - set to xhtml will result in an "Invalid value for HTML_VERSION: - 'xhtml'" error. (John Rouillard) -- issue2551103 - add pragma 'display_protected' to roundup-admin. If - true, print protected attributes like id, activity, actor... - when using display or specification subcommands. (John Rouillard) -- add -P pragma=value command line option to roundup-admin. Allows - setting pragmas when using non-interactive mode. (John Rouillard) -- issue685275 - add pragma show_retired to control display of retired - items when using list/table. Add pragma display_header to print - headers for display command. Header displays designator and - retired/active status. (John Rouillard) -- issue2551299 - support config.ini rdbms option 'service'. Allow use - of a PostgreSQL connection service file (pg_service.conf) for - configuring database on a per-tracker basis. Also replaces use of - PGSERVICE env variable for single instance trackers. (From ML - question by ivanov. John Rouillard) -- issue2550852 - support for specifying a PostgreSQL schema to use for - the Roundup database. (Patch by Stuart McGraw; slight modifications, - tests, docs: John Rouillard). -- issue2551274: add configurable logging for REST API when something - fails, we now log status code and error message. - (Ralf Schlatterbeck) -- issue2551317 - add some Jinja2 examples to customizing.txt - document. (John Rouillard) -- multiple scripts/... updates - Python3, linting, enhancements: - weekly-report,schema-dump.py, roundup-reminder, copy-user.py, - dump_dbm_sessions_db.py, contributors.py (John Rouillard) -- roundup/msgfile.py can now be called as 'python msgfmt.py de.po de.mo' - or 'python msgfmt.py -o de.mo de.po' to compile a translation file if - GNU msgfmt is missing. (John Rouillard) -- save roundup-admin history between sessions. Load - ~/.roundup_admin_rlrc file to set history-size persistently. Add - pragma history_length to override for a session. (John Rouillard) -- the roundup-admin history command now dumps the journal entries - in a more human readable format. Use the raw option to get the older - machine parsible output. (John Rouillard) -- Multiple JWT secrets are supported to allow key rotation. See - an updated config.ini for details. (John Rouillard) -- issue2551212 - wsgi performance improvement feature added in 2.2.0 - is active by default. Can be turned off if needed. See upgrading.txt - for info. (John Rouillard) -- issue2551270 - Better templating support for JavaScript. Add - utils.readfile(file, optional=False) and utils.expandfile(file, - token_dict=None, optional=False). Allows reading an external file - (e.g. JavaScript) and inserting it using tal:contents or equivalent - jinja function. expandfile allows setting a dictionary and tokens in - the file of the form "%(token_name)s" will be replaced in the file - with the values from the dict. (John Rouillard) -- add @group to rest interface collection queries. Useful when using - optgroup in select elements. (John Rouillard) -- roundup-demo can set the hostname in the URL using the -H - parameter. So you can start a demo tracker that is available from - your network using 'roundup-demo ... -B hostname -H hostname'. (John - Rouillard) -- issue2551347 - make _generic.help.html work without property - settings. THis applies to classic or minimal trackers. It allows use - of classhelp without the property seting for informtion only - (e.g. description of what a priority or status means) without being - able to select the property in the classhelper. Good for adding help - for Link properties. (John Rouilllard) -- issue1525113 - notation to filter by logged-in user. Use - @current_user with properties that are a Link to the 'user' class to - match the currently logged in user. Allows sharing of queries like - "Issues I created" or "Issues I am assigned to" by removing the - hard coded user id number and replacing it with the current user's - id. Tracker templates updated to use it. (John Rouillard from a - patch by Jon C. Thomason) -- Add a /rest/data/user/roles REST endpoint. (John Rouillard) -- issue2551353 - Add roundup-classhelper for 2.4.0 - release. Integrate new classhelper web component to wrap - existing classhelper link. This fixes a number of - outstanding bugs against the current classhelper using - current web features. (Patel Malav, Nikunj Thakkar, - Bharath Kanama with integration by John Rouillard) -- disable spellcheck on all password fields to try to prevent - browser from exposing passwords to external servers. (John +- issue2551287 - Enhance roundup_gettext.py to extract strings from + detectors/extensions. If the polib module is available, + roundup-gettext will extract translatable strings from the tracker's + Python code. If polib is missing, it will print a warning. (Patch + Marcus Priesch, cleanup to remove python 2 issues, John Rouillard.) +- issue2551315 - Document use of + RestfulInstance.max_response_row_size to limit data returned + from rest request. (John Rouillard) +- issue2551330 - Add an optional 'filter' function to the Permission + objects and the addPermission method. This is used to optimize search + performance by not checking items returned from a database query + one-by-one (using the check function) but instead offload the + permission checks to the database. For SQL backends this performs the + filtering in the database. (Ralf Schlatterbeck) +- issue2551370 - mark roundup session cookie with __Secure- + prefix. (John Rouillard) +- add -P flag to roundup-server to log client address from + X-Forwarded-For reverse proxy header rather than connecting + address. This logs the actual client address when + roundup-server is run behind a reverse proxy. It also appends a + + sign to the logged address/name. (John Rouillard) +- issue2551068 - Provide way to retrieve file/msg data via rest + endpoint. Raw file/msg data can be retrieved using the + /binary_content attribute and an Accept header to select the mime + type for the data (e.g. image/png for a png file). The existing html + interface method still works and is supported, but is legacy. (John + Rouillard) +- added fuzz testing for some code. Found issue2551382 and + others. (John Rouillard) +- issue2551116 - Replace xmlrpclib (xmlrpc.client) with defusedxml. + Added support for defusedxml to better secure the xmlrpc + endpoint. (John Rouillard) +- Added new instance.registerUtilMethod() method to make using complex + templating easier as it provides a default Client instance to the + templating method. (John Rouillard) +- Added new templating utils.set_http_response(integer) method to + allow reporting an error to the user from a template. (John Rouillard) +- issue2551390 - Replace text input/calendar popup with native + date input. Also add double-click and exit keyboard handlers to + allow copy/paste/editing the text version of the date. Configurable + via the use_browser_date_input setting in the [web] section of + config.ini. By default browser native dates are turned off. + (John Rouillard, Ralf Schlatterbeck) +- Use native number type input for Number() and Integer() + properties. Integer() uses step=1 as well. Configurable via the + use_browser_number_input setting in the [web] section of config.ini. + Set off by default. See + https://issues.roundup-tracker.org/issue2551398 for discussion of + issues with native number inputs. (John Rouillard, Ralf + Schlatterbeck) +- issue2551231 - template.py-HTMLClass::classhelp doesn't merge + user defined classes. It now merges them in. (John Rouillard) +- re-enable support for GPG/PGP encrypted emails using new python gpg + package on the test pypi instance. (Paul Schwabauer) diff --git a/doc/conf.py b/doc/conf.py index 70bb8b5c8..7dc41f5d7 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -51,7 +51,7 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. #extensions = ['toctree'] -extensions = ['sphinx_tabs.tabs'] +extensions = ['sphinx_tabs.tabs', 'sphinx.ext.autodoc'] sphinx_tabs_valid_builders = ['linkcheck'] sphinx_tabs_disable_tab_closing = True @@ -72,7 +72,7 @@ # General information about the project. project = u'Roundup' -copyright = u'2009-2024, Richard Jones, Roundup-Team' +copyright = u'2009-2025, Richard Jones, Roundup-Team' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/doc/customizing.txt b/doc/customizing.txt index 46226fb08..c3aa5fb29 100644 --- a/doc/customizing.txt +++ b/doc/customizing.txt @@ -94,7 +94,7 @@ caches the schema). Due Date - + 3. Add the property to the ``issue.index.html`` page:: @@ -1815,6 +1815,66 @@ Some simple javascript might help in the last step. If you have high volume you could search for all currently-Pending users and do a bulk edit of all their roles at once (again probably with some simple javascript help). +.. _sensitive_changes: + +Confirming Users Making Sensitive Account Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some changes to account data: user passwords or email addresses are +particularly sensitive. The `OWASP Authentication`_ recommendations +include asking for a re-authentication or confirmation step when making +these changes. This can be easily implemented using an auditor. + +Create a file in your detectors directory with the following +contents:: + + from roundup.cgi.exceptions import Reauth + + def confirmid(db, cl, nodeid, newvalues): + + if hasattr(db, 'reauth_done'): + # the user has confirmed their identity + return + + if db.tx_Source not in ("web"): + # the user is using rest, xmlrpc, command line, + # email (unlikely) which don't support interactive + # verification + return + + # if the password or email are changing, require id confirmation + if 'password' in newvalues: + raise Reauth('Add an optional message to the user') + + if 'address' in newvalues: + raise Reauth('Add an optional message to the user') + + def init(db): + db.user.audit('set', confirmid, priority=110) + +If a change is made to any user's password or address fields, the user +making the change will be shown a page where they have to enter an +identity verifier (by default the invoking user's account password). +If the verifier is successfully verified it will set the +``reauth_done`` attribute on the db object and reprocess the change. + +The default auditor priority is 100. This auditor is set to run +**after** most other auditors. This allows the user to correct any +failing information on the form before being asked to confirm their +identity. Once they confirm their identity the change is expected to +be committed without issue. See :ref:`Confirming the User` for +details on customizing the verification operation. + +Also you could use an existing auditor and add:: + + if 'someproperty' in newvalues and not hasattr(db, 'reauth_done'): + raise Reauth('Need verification before changing someproperty') + +at the end of the auditor (after all checks are done) to force user +verification. Just make sure you import Reauth at the top of the file. + +.. _`OWASP Authentication`: + https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html#require-re-authentication-for-sensitive-features Changes to the Web User Interface --------------------------------- @@ -1892,7 +1952,7 @@ To edit the status of all items in the item index view, edit the and at the bottom of that table add:: - making sure you match the ```` from the list table, not the navigation table or the subsequent form table. @@ -2436,6 +2496,10 @@ The `reference document`_ also has examples: `_. * `Adding a new Permission `_ +as does the design document: + +* `detector examples `_ + Examples on the Wiki ==================== diff --git a/doc/features.txt b/doc/features.txt index 1ca99fd39..2f3c1bb44 100644 --- a/doc/features.txt +++ b/doc/features.txt @@ -10,91 +10,118 @@ Roundup Features Roundup is an easy-to-use and -install issue-tracking system with web, e-mail and command-line interfaces. Based on the winning design -from Ka-Ping Yee in the :index:`Software Carpentry` "Track" design competition. - -**Installation and Setup** - -- Start using the software in `instant-gratification (demo) mode`_ with - ``python demo.py`` or `a Docker container`_ in under 5 minutes. -- Choose from `five included templates`_ for your tracker. -- `Customize`_ and use the demo as a template for your production tracker. -- No need for additional support software, just Python (3.6+ or 2.7) - to get started. -- Basic installation (including a web interface) takes about 30 minutes. -- Supports embedded databases like `SQLite`_ and dbm. Upgradable - to databases like `MySQL`_ or `PostgreSQL`_ if needed. -- Can be run in a container like Docker or kubernetes. -- Deploy in your network as a standalone web server or `through - various methods`_ like WSGI, FastCGI, plain CGI, etc. - -**Issue Tracking and Management** - -- Manage your issues your way. Handle bugs, features, milestones, - user feedback, fleet maintenance, office issues etc. -- Searches on specific properties (e.g. open issues with a high - priority) can be saved and reused or shared with outer users. -- Full Text Search for quick searches across messages. -- Keeps a detailed history of issue changes. -- Issues become a mini mailing list to keep everyone informed. -- Email is a first class method for interacting with issues. - -**Scalability and Performance** - -- Default trackers use simple HTML with low resource requirements. -- Fast and scalable with sqlite, mysql, and postgresql backends. -- Indexes are automatically configured. -- Supports full-text indexing engines (xapian, whoosh, SQLite, - PostgreSQL) for large trackers. - -**Customization** - -- The database schema can be updated to `track additional data`_. -- The web interface can be redesigned to fit your workflow. -- Extensible web interface with various features like `wizards`_, - bug displays, etc. -- Add business rules using `auditors and reactors`_ for actions before - and after database changes. -- Comprehensive documentation for customization, installation, - maintenance, and user guidance. - -**Data Security, Privacy and Authorization** - -- Your data remains on your servers. -- You can choose if AI can access the data. -- Can use HTTPS for security over the web. -- Fine-grained authorization (ABAC, PEBAC) based on user and resource - properties. - -**Documentation and User Management** - -- Users can sign up through the web interface or new user creation - can be limited to admin users. -- Can use an `external user database`_ (LDAP, password file) -- Self-server password reset for users via email. - -**Email Integration and Automation** - -- Update issues via email with new messages and the ability to - change properties of issues (e.g. close an issue). -- Secure email handling with features like TLS, APOP, IMAPS/OAUTH. -- Optional auto-registration for email users. -- Configurable nosy list for each issue controls email notifications. -- Proper handling of email attachments and content types. - -**Command-Line and API Access** - -- Manage database interactively from the command line. -- Automate modifications using standard shell scripting. -- Python programs can use the Roundup Python API to manage/automate issues. -- Sample scripts provided for various tasks. - -**Remote Access Interfaces** - -- `XMLRPC interface`_ for remote tracker access with basic - HTTP authentication. -- `RESTful API`_ accessible with basic HTTP authentication or optional JWT. -- Configurable CORS support for third-party web pages. -- Ability to generate and authenticate JSON Web Tokens (JWT). +from Ka-Ping Yee in the :index:`Software Carpentry` "Track" design +competition. + +.. container:: card + + **Installation and Setup** + + - Start using the software in `instant-gratification (demo) mode`_ with + ``python demo.py`` or `a Docker container`_ in under 5 minutes. + - Choose from `five included templates`_ for your tracker. + - `Customize`_ and use the demo as a template for your production tracker. + - No need for additional support software, just Python (3.7+) + to get started. + - Basic installation (including a web interface) takes about 30 minutes. + - Supports embedded databases like `SQLite`_ and dbm. Upgradable + to databases like `MySQL`_ or `PostgreSQL`_ if needed. + - Can be run in a container like Docker or kubernetes. + - Deploy in your network as a standalone web server or `through + various methods`_ like WSGI, FastCGI, plain CGI, etc. + - Essential tracking features depend on the Python standard + library. Supplementary packages from PyPI are optional and can be + tailored to fit your unique threat model and security needs. + +.. container:: card + + **Issue Tracking and Management** + + - Manage your issues your way. Handle bugs, features, milestones, + user feedback, fleet maintenance, office issues etc. + - Issues become a mini mailing list to keep everyone informed. + - Searches on specific properties (e.g. open issues with a high + priority) can be saved and reused or shared with other users. + - Full Text Search for quick searches across messages. + - Keeps a detailed history of issue changes. + - Email is a first class method for interacting with issues. + +.. container:: card + + **Scalability and Performance** + + - Default trackers use simple HTML with low resource requirements. + - Fast and scalable with sqlite, mysql, and postgresql backends. + - Indexes are automatically configured. + - Supports full-text indexing engines (xapian, whoosh, SQLite, + PostgreSQL) for large trackers. + +.. container:: card + + **Customization** + + - The database schema can be updated to `track additional data`_. + - The web interface can be redesigned to fit your workflow. + - Extensible web interface with various features like `wizards`_, + bug displays, etc. + - Add business rules using `auditors and reactors`_ for actions before + and after database changes. + - Comprehensive documentation for customization, installation, + maintenance, and user guidance. + +.. container:: card + + **Data Security, Privacy and Authorization** + + - Your data remains on your servers. + - You can choose if AI can access the data. + - Can use HTTPS for security over the web. + - Fine-grained authorization (`ABAC`_, `ReBAC`_, `RBAC`_) based on + user, resource, and external properties. + +.. _`ABAC`: https://en.wikipedia.org/wiki/Attribute-based_access_control +.. _`ReBAC`: https://en.wikipedia.org/wiki/Relationship-based_access_control +.. _`RBAC`: https://en.wikipedia.org/wiki/Role-based_access_control + +.. container:: card + + **Documentation and User Management** + + - Users can sign up through the web interface or new user creation + can be limited to admin users. + - Can use an `external user database`_ (LDAP, password file) + - Self-serve password reset for users via email. + +.. container:: card + + **Email Integration and Automation** + + - Update issues via email with new messages and the ability to + change properties of issues (e.g. close an issue). + - Secure email handling with features like TLS, APOP, IMAPS/OAUTH. + - Optional auto-registration for email users. + - Configurable nosy list for each issue controls email notifications. + - Proper handling of email attachments and content types. + +.. container:: card + + **Command-Line and API Access** + + - Manage database interactively from the command line. + - Automate modifications using standard shell scripting. + - Python programs can use the Roundup Python API to manage/automate issues. + - Sample scripts provided for various tasks. + +.. container:: card + + **Remote Access Interfaces** + + - `RESTful API`_ accessible with basic HTTP authentication or optional JWT. + - `XMLRPC interface`_ for remote tracker access with basic + HTTP authentication. + - Configurable CORS support for third-party web pages. + - Ability to `generate and authenticate JSON Web Tokens (JWT) + `_. .. _`auditors and reactors`: reference.html#auditor-or-reactor .. _`customize`: customizing.html diff --git a/doc/format_config.awk b/doc/format_config.awk index 932965c72..6886a6e35 100644 --- a/doc/format_config.awk +++ b/doc/format_config.awk @@ -1,8 +1,14 @@ #! /bin/awk +BEGIN {SECRET_KEY = "DWmbKgVUy6fF5D2Y5TD5Az+dnHhMYKCCpJzIY3H8nsU="} # delete first 8 lines NR < 9 {next} +# To prevent new file generation from causing the secret_key to +# change, we replace the secret key with a fixed value. +/^# Default: [0-9A-z+=/]{44}/ {sub(/[0-9A-z+=/]{44}/, SECRET_KEY)} +/^secret_key = [0-9A-z+=/]{44}/ {sub(/[0-9A-Za-z+=/]{44}/, SECRET_KEY)} + # When we see a section [label]: # emit section index marker, # emit section anchor @@ -43,3 +49,4 @@ NR < 9 {next} /^$/ { if (! prev_line_is_blank) {accumulate = accumulate $0}; prev_line_is_blank = 1; } + diff --git a/doc/glossary.txt b/doc/glossary.txt index b2969fb0a..ab0721b31 100644 --- a/doc/glossary.txt +++ b/doc/glossary.txt @@ -32,6 +32,29 @@ Roundup Glossary a dash '-', and a number. E.g. ``file-1``. These are used to create new instances of a class via the web interface. + detectors + There are two types of detectors that execute Python code in + response to changes to the database. + + auditors + are run before a permanent change is made to the database. + They validate that the change is allowed. For example is + the current user allowed to change the status field. + + reactors + are run after a change has been committed to the + database. They are used to perform actions like sending + notification messages, updating other tickets etc. + + html directory + there is a directory called **html** in tracker homes. This + contains html files (called templates) that are processed by the + templating processor (TAL or jinja2) for delivery to a web + client. However there is also a ``templates`` setting in the + tracker's ``config.ini`` file. The default value for this is + ``html``. However any directories listed as templates should be + considered an ``html directory`` + hyperdb a software layer between the user and the underlying :term:`db`. It is responsible for mutating the underlying db when the schema @@ -56,6 +79,31 @@ Roundup Glossary tracker. Contained in the file ``schema.py``. The permissions for the schema items are usually defined in the same file. + template + + this term has three meanings depending on context. + + 1. files that are processed by a templating engine to + produce output suitable for machine or human consumption. For + example a template could produce a html page that includes the + name of the user. + + 2. a property of the request object in the templating + system. Templates that are used with a specific class (e.g. + ``issue.item.html``) will have this entry set to the middle + element (``item`` in this example). For templates like + ``home.html`` the element will be set to the empty string. + + 3. a **Tracker template**. This is a set of files + used to install a new tracker. Tracker templates define a + tracker with a particular look and feel, :term:`schema`, + permissions model, and :term:`detectors`. Roundup ships with + five templates and people on the net `have produced other + templates`_. You can find the installed location of the + standard Roundup templates using the :ref:`roundup-admin + templates ` command. + + tracker the schema and hyperdb that forms one issue tracker @@ -68,5 +116,6 @@ Roundup Glossary Back to `Table of Contents`_ +.. _`have produced other templates`: https://wiki.roundup-tracker.org/TrackerTemplates .. _`Table of Contents`: ../docs.html diff --git a/doc/html_extra/accessibility-statement_2025-10-08.html b/doc/html_extra/accessibility-statement_2025-10-08.html new file mode 100644 index 000000000..f4e67e004 --- /dev/null +++ b/doc/html_extra/accessibility-statement_2025-10-08.html @@ -0,0 +1,75 @@ + +

Accessibility Statement for Roundup Issue Tracker Main Website

+

+ This is an accessibility statement from Roundup Issue Tracker. +

+

Conformance status

+

+ The Web Content Accessibility Guidelines (WCAG) defines requirements for designers and developers to improve accessibility for people with disabilities. It defines three levels of conformance: Level A, Level AA, and Level AAA. + Roundup Issue Tracker Main Website + is + partially conformant + with + WCAG 2.2 level AA. + + Partially conformant + means that + some parts of the content do not fully conform to the accessibility standard. + +

+

Feedback

+

+ We welcome your feedback on the accessibility of + Roundup Issue Tracker Main Website. + Please let us know if you encounter accessibility barriers on + Roundup Issue Tracker Main Website: +

+ +

Technical specifications

+

+ Accessibility of + Roundup Issue Tracker Main Website + relies on the following technologies to work with the particular combination of web browser and any assistive technologies or plugins installed on your computer: +

+
    +
  • HTML
  • +
  • WAI-ARIA
  • +
  • CSS
  • +
+

These technologies are relied upon for conformance with the accessibility standards used.

+

Limitations and alternatives

+

+ Despite our best efforts to ensure accessibility of + Roundup Issue Tracker Main Website , there may be some limitations. Below is a description of known limitations, and potential solutions. Please contact us if you observe an issue not listed below. +

+

+ Known limitations for + Roundup Issue Tracker Main Website: +

+
    +
  1. Search input does not have a visible label: The visible label is in the [Search] button next to the input but it not tied to the input directly. because The button acts as a visible label from proximity. The input has an aria-label describing the input.
  2. +
  3. Multi-language tab panel examples do not scroll: Multi-language example panels require two tabs to get to the element that will scroll. The Sphinx tab extension is used to show different language examples for the same item. It adds a focusable container around the example container. So the outer container must be tabbed/focused through to scroll the example when using the keyboard.
  4. +
+

Assessment approach

+

+ Roundup Issue Tracker + assessed the accessibility of + Roundup Issue Tracker Main Website + by the following approaches: +

+
    +
  • Self-evaluation
  • +
+
+

Date

+

+ This statement was created on + 8 November 2025 + using the W3C Accessibility Statement Generator Tool. +

diff --git a/doc/html_extra/man_pages/roundup-admin.1.html b/doc/html_extra/man_pages/roundup-admin.1.html index b8102a52b..5704aea0c 100644 --- a/doc/html_extra/man_pages/roundup-admin.1.html +++ b/doc/html_extra/man_pages/roundup-admin.1.html @@ -1,5 +1,5 @@ - + @@ -7,6 +7,7 @@ +