rdiffweb 2.11.2__tar.gz → 2.11.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. {rdiffweb-2.11.2/rdiffweb.egg-info → rdiffweb-2.11.4}/PKG-INFO +26 -5
  2. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/README.md +25 -4
  3. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/filter_authorization.py +2 -2
  4. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_admin_users.py +1 -0
  5. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_admin.py +1 -1
  6. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_admin_users.py +13 -0
  7. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_delete.py +1 -1
  8. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_status.py +1 -1
  9. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/_message.py +16 -3
  10. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/tests/test_db_after_create.py +43 -0
  11. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/tests/test_user.py +13 -4
  12. {rdiffweb-2.11.2 → rdiffweb-2.11.4/rdiffweb.egg-info}/PKG-INFO +26 -5
  13. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/FUNDING.yml +0 -0
  14. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/LICENSE +0 -0
  15. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/MANIFEST.in +0 -0
  16. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/SECURITY.md +0 -0
  17. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/babel.cfg +0 -0
  18. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/.gitignore +0 -0
  19. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/_static/banner.png +0 -0
  20. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/_static/banner.svg +0 -0
  21. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/_static/logo.png +0 -0
  22. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/access_tokens.md +0 -0
  23. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/api.md +0 -0
  24. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/conf.py +0 -0
  25. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/configuration-latest.md +0 -0
  26. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/configuration-ldap.md +0 -0
  27. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/configuration-oauth.md +0 -0
  28. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/configuration.md +0 -0
  29. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/development.md +0 -0
  30. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/fail2ban.md +0 -0
  31. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/faq-good-encoding.png +0 -0
  32. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/faq-wrong-encoding.png +0 -0
  33. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/faq.md +0 -0
  34. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/hardening.md +0 -0
  35. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/index.rst +0 -0
  36. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/installation.md +0 -0
  37. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/introduction.md +0 -0
  38. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/networking.md +0 -0
  39. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/quickstart.md +0 -0
  40. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/rdiffweb-users.png +0 -0
  41. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/repo-encoding.png +0 -0
  42. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/settings-user-role.png +0 -0
  43. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/settings.md +0 -0
  44. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/two_factor_authentication.md +0 -0
  45. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/doc/usage.rst +0 -0
  46. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/extras/init/rdiffweb +0 -0
  47. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/extras/nginx/rdiffweb.conf +0 -0
  48. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/extras/nginx/rdiffweb_root.conf +0 -0
  49. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/extras/systemd/rdiffweb.service +0 -0
  50. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/pyproject.toml +0 -0
  51. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/__init__.py +0 -0
  52. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/__init__.py +0 -0
  53. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/api.py +0 -0
  54. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/api_currentuser.py +0 -0
  55. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/api_openapi.py +0 -0
  56. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/dispatch.py +0 -0
  57. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/form.py +0 -0
  58. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/formdb.py +0 -0
  59. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_admin.py +0 -0
  60. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_admin_activity.py +0 -0
  61. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_admin_logs.py +0 -0
  62. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_admin_repos.py +0 -0
  63. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_admin_session.py +0 -0
  64. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_admin_sysinfo.py +0 -0
  65. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_browse.py +0 -0
  66. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_delete.py +0 -0
  67. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_graphs.py +0 -0
  68. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_history.py +0 -0
  69. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_locations.py +0 -0
  70. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_login.py +0 -0
  71. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_logs.py +0 -0
  72. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_mfa.py +0 -0
  73. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_pref_general.py +0 -0
  74. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_pref_mfa.py +0 -0
  75. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_pref_notification.py +0 -0
  76. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_pref_session.py +0 -0
  77. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_pref_sshkeys.py +0 -0
  78. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_pref_tokens.py +0 -0
  79. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_prefs.py +0 -0
  80. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_restore.py +0 -0
  81. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_settings.py +0 -0
  82. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_stats.py +0 -0
  83. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/page_status.py +0 -0
  84. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/__init__.py +0 -0
  85. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_api.py +0 -0
  86. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_check_links.py +0 -0
  87. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_controller.py +0 -0
  88. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_openapi.py +0 -0
  89. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_admin_activity.py +0 -0
  90. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_admin_logs.py +0 -0
  91. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_admin_repos.py +0 -0
  92. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_admin_session.py +0 -0
  93. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_admin_sysinfo.py +0 -0
  94. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_browse.py +0 -0
  95. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_error.py +0 -0
  96. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_graphs.py +0 -0
  97. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_history.py +0 -0
  98. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_login.py +0 -0
  99. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_logs.py +0 -0
  100. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_mfa.py +0 -0
  101. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_prefs_general.py +0 -0
  102. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_prefs_mfa.py +0 -0
  103. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_prefs_notification.py +0 -0
  104. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_prefs_session.py +0 -0
  105. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_prefs_ssh.py +0 -0
  106. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_prefs_tokens.py +0 -0
  107. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_restore.py +0 -0
  108. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_settings.py +0 -0
  109. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_page_stats.py +0 -0
  110. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/controller/tests/test_secure_headers.py +0 -0
  111. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/__init__.py +0 -0
  112. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/activity.py +0 -0
  113. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/authorizedkeys.py +0 -0
  114. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/config.py +0 -0
  115. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/dircache.py +0 -0
  116. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/librdiff.py +0 -0
  117. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/__init__.py +0 -0
  118. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/_callbacks.py +0 -0
  119. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/_repo.py +0 -0
  120. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/_session.py +0 -0
  121. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/_sshkey.py +0 -0
  122. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/_timestamp.py +0 -0
  123. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/_token.py +0 -0
  124. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/_update.py +0 -0
  125. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/_user.py +0 -0
  126. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/tests/__init__.py +0 -0
  127. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/tests/test_repo.py +0 -0
  128. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/model/tests/test_token.py +0 -0
  129. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/notification.py +0 -0
  130. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/passwd.py +0 -0
  131. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/quota.py +0 -0
  132. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/rdw_helpers.py +0 -0
  133. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/rdw_templating.py +0 -0
  134. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/remove_older.py +0 -0
  135. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/restore.py +0 -0
  136. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/__init__.py +0 -0
  137. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/rdiff-backup-data/error_log.2015-11-19T07:27:46-05:00.data +0 -0
  138. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/rdiff-backup-data/error_log.2015-11-20T07:27:46-05:00.data.gz +0 -0
  139. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/rdiff-backup-data/error_log.2019-05-22T09:19:09-04:00.data.gz +0 -0
  140. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/rdiff-backup-data/file_statistics.2014-11-05T16:05:07-05:00.data +0 -0
  141. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/rdiff-backup-data/file_statistics.2014-11-05T16:05:07-05:00.data.gz +0 -0
  142. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/rdiff-backup-data/session_statistics.2014-11-02T09:16:43-05:00.data +0 -0
  143. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/session_statistics.2014-11-02T09:16:43-05:00.data +0 -0
  144. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_authorized_keys +0 -0
  145. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_authorizedkeys.py +0 -0
  146. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_config.py +0 -0
  147. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_i18n.py +0 -0
  148. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_librdiff.py +0 -0
  149. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_login.py +0 -0
  150. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_notification.py +0 -0
  151. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_passwd.py +0 -0
  152. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_publickey_ssh_dsa.pub +0 -0
  153. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_publickey_ssh_rsa.pub +0 -0
  154. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_quota.py +0 -0
  155. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_rdw_helpers.py +0 -0
  156. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_rdw_templating.py +0 -0
  157. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_remove_older.py +0 -0
  158. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/core/tests/test_restore.py +0 -0
  159. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/ca/LC_MESSAGES/messages.mo +0 -0
  160. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/ca/LC_MESSAGES/messages.po +0 -0
  161. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/de/LC_MESSAGES/messages.mo +0 -0
  162. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/de/LC_MESSAGES/messages.po +0 -0
  163. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/en/LC_MESSAGES/messages.mo +0 -0
  164. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/en/LC_MESSAGES/messages.po +0 -0
  165. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/es/LC_MESSAGES/messages.mo +0 -0
  166. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/es/LC_MESSAGES/messages.po +0 -0
  167. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/fr/LC_MESSAGES/messages.mo +0 -0
  168. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/fr/LC_MESSAGES/messages.po +0 -0
  169. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/messages.pot +0 -0
  170. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/pt/LC_MESSAGES/messages.mo +0 -0
  171. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/pt/LC_MESSAGES/messages.po +0 -0
  172. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/ru/LC_MESSAGES/messages.mo +0 -0
  173. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/locales/ru/LC_MESSAGES/messages.po +0 -0
  174. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/main.py +0 -0
  175. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/__init__.py +0 -0
  176. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/db.py +0 -0
  177. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/ldap.py +0 -0
  178. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/oauth.py +0 -0
  179. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/restapi.py +0 -0
  180. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/scheduler.py +0 -0
  181. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/smtp.py +0 -0
  182. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/tests/__init__.py +0 -0
  183. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/tests/test_ldap.py +0 -0
  184. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/tests/test_oauth.py +0 -0
  185. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/tests/test_scheduler.py +0 -0
  186. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/plugins/tests/test_smtp.py +0 -0
  187. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/rdw_app.py +0 -0
  188. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/css/bootstrap.min.css +0 -0
  189. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/css/bootstrap.min.css.map +0 -0
  190. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/css/font-awesome.css.map +0 -0
  191. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/css/font-awesome.min.css +0 -0
  192. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/css/jquery.dataTables.min.css +0 -0
  193. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/css/responsive.dataTables.min.css +0 -0
  194. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/favicon.ico +0 -0
  195. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/favicon.svg +0 -0
  196. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/fonts/fontawesome-webfont.eot +0 -0
  197. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/fonts/fontawesome-webfont.svg +0 -0
  198. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/fonts/fontawesome-webfont.woff +0 -0
  199. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/fonts/fontawesome-webfont.woff2 +0 -0
  200. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/header-logo.png +0 -0
  201. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/header-logo.svg +0 -0
  202. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/images/sort_asc.png +0 -0
  203. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/images/sort_asc_disabled.png +0 -0
  204. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/images/sort_both.png +0 -0
  205. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/images/sort_desc.png +0 -0
  206. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/images/sort_desc_disabled.png +0 -0
  207. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/js/bootstrap.bundle.js.map +0 -0
  208. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/js/bootstrap.bundle.min.js +0 -0
  209. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/js/chart.min.js +0 -0
  210. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/js/chartkick.min.js +0 -0
  211. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/js/dataTables.buttons.min.js +0 -0
  212. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/js/dataTables.responsive.min.js +0 -0
  213. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/js/jquery.dataTables.min.js +0 -0
  214. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/js/jquery.min.js +0 -0
  215. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/js/main.js +0 -0
  216. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/logo1.png +0 -0
  217. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/logo1.svg +0 -0
  218. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/static/robots.txt +0 -0
  219. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin.html +0 -0
  220. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin_activity.html +0 -0
  221. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin_logs.html +0 -0
  222. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin_overview.html +0 -0
  223. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin_repos.html +0 -0
  224. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin_session.html +0 -0
  225. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin_sysinfo.html +0 -0
  226. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin_user_edit.html +0 -0
  227. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin_user_new.html +0 -0
  228. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/admin_users.html +0 -0
  229. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/browse.html +0 -0
  230. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/components/form.html +0 -0
  231. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/components/log.html +0 -0
  232. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/components/nav.html +0 -0
  233. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_access_token_added.html +0 -0
  234. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_authorizedkey_added.html +0 -0
  235. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_changed.html +0 -0
  236. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_latest.html +0 -0
  237. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_layout.html +0 -0
  238. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_mfa.html +0 -0
  239. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_notification.html +0 -0
  240. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_password_changed.html +0 -0
  241. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_repo_added.html +0 -0
  242. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_repo_deleted.html +0 -0
  243. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_report.html +0 -0
  244. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/email_verification_code.html +0 -0
  245. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/error_page_default.html +0 -0
  246. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/graphs.html +0 -0
  247. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/graphs_activities.html +0 -0
  248. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/graphs_errors.html +0 -0
  249. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/graphs_files.html +0 -0
  250. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/graphs_sizes.html +0 -0
  251. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/graphs_times.html +0 -0
  252. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/history.html +0 -0
  253. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/chartkick.html +0 -0
  254. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/datatables.html +0 -0
  255. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/empty.html +0 -0
  256. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/messages.html +0 -0
  257. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/modal_dialog.html +0 -0
  258. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/panel.html +0 -0
  259. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/session.html +0 -0
  260. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/storage_usage.html +0 -0
  261. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/table.html +0 -0
  262. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/include/timerange.html +0 -0
  263. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/layout.html +0 -0
  264. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/layout_repo.html +0 -0
  265. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/locations.html +0 -0
  266. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/login.html +0 -0
  267. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/logs.html +0 -0
  268. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/main.css +0 -0
  269. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/message.html +0 -0
  270. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/mfa.html +0 -0
  271. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/prefs.html +0 -0
  272. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/prefs_general.html +0 -0
  273. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/prefs_mfa.html +0 -0
  274. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/prefs_notification.html +0 -0
  275. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/prefs_session.html +0 -0
  276. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/prefs_sshkeys.html +0 -0
  277. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/prefs_tokens.html +0 -0
  278. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/restore.html +0 -0
  279. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/settings.html +0 -0
  280. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/stats.html +0 -0
  281. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/templates/status.html +0 -0
  282. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/test.py +0 -0
  283. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tests/__init__.py +0 -0
  284. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tests/rdw.conf +0 -0
  285. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tests/rdw.db +0 -0
  286. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tests/test_app.py +0 -0
  287. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tests/test_main.py +0 -0
  288. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tests/testcases.tar.gz +0 -0
  289. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/__init__.py +0 -0
  290. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/auth.py +0 -0
  291. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/auth_mfa.py +0 -0
  292. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/enrich_session.py +0 -0
  293. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/errors.py +0 -0
  294. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/i18n.py +0 -0
  295. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/poppath.py +0 -0
  296. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/ratelimit.py +0 -0
  297. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/required_scope.py +0 -0
  298. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/secure_headers.py +0 -0
  299. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb/tools/sessions_timeout.py +0 -0
  300. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb.egg-info/SOURCES.txt +0 -0
  301. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb.egg-info/dependency_links.txt +0 -0
  302. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb.egg-info/entry_points.txt +0 -0
  303. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb.egg-info/requires.txt +0 -0
  304. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdiffweb.egg-info/top_level.txt +0 -0
  305. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/rdw.conf +0 -0
  306. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/setup.cfg +0 -0
  307. {rdiffweb-2.11.2 → rdiffweb-2.11.4}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rdiffweb
3
- Version: 2.11.2
3
+ Version: 2.11.4
4
4
  Summary: A web interface to rdiff-backup repositories.
5
5
  Author-email: Patrik Dufresne <patrik@ikus-soft.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -851,7 +851,28 @@ We are passionate about developing and maintaining this open-source project to m
851
851
 
852
852
  # Changelog
853
853
 
854
- # 2.11.0 (2025-01-14)
854
+ ## 2.11.4 (2026-04-23)
855
+
856
+ * **Bug Fixes:**
857
+ * db: fix user deletion raising foreign key errors
858
+
859
+ ## 2.11.3 (2026-04-09)
860
+
861
+ * **Security Fixes:**
862
+ * api: restrict `/api/users` endpoint to administrators only
863
+
864
+ ## 2.11.2 (2026-04-07)
865
+
866
+ * **Bug Fixes:**
867
+ * smtp: fix encoding for email_from
868
+
869
+ ## 2.11.1 (2026-03-11)
870
+
871
+ * **Bug Fixes:**
872
+ * fix: add support for configargparse >= 1.7.5
873
+ * fix: bookwork test by pinning setuptools version
874
+
875
+ ## 2.11.0 (2025-01-14)
855
876
 
856
877
  * **New Features**
857
878
  * Administrators can disable user accounts (#313).
@@ -890,15 +911,15 @@ We are passionate about developing and maintaining this open-source project to m
890
911
  * Dropped Ubuntu Oracular
891
912
  * Dropped Debian Bullseye due to backports/EOL.
892
913
 
893
- # 2.10.6 (2025-10-02)
914
+ ## 2.10.6 (2025-10-02)
894
915
 
895
916
  * Security: fix token impersonation vulnerability (CVE-2025-67796).
896
917
 
897
- # 2.10.5 (2025-06-20)
918
+ ## 2.10.5 (2025-06-20)
898
919
 
899
920
  * Send deprecation warning into the logs
900
921
 
901
- # 2.10.4 (2025-06-13)
922
+ ## 2.10.4 (2025-06-13)
902
923
 
903
924
  * **New Features:**
904
925
  * Added Swagger documentation for the Rdiffweb API (#325).
@@ -128,7 +128,28 @@ We are passionate about developing and maintaining this open-source project to m
128
128
 
129
129
  # Changelog
130
130
 
131
- # 2.11.0 (2025-01-14)
131
+ ## 2.11.4 (2026-04-23)
132
+
133
+ * **Bug Fixes:**
134
+ * db: fix user deletion raising foreign key errors
135
+
136
+ ## 2.11.3 (2026-04-09)
137
+
138
+ * **Security Fixes:**
139
+ * api: restrict `/api/users` endpoint to administrators only
140
+
141
+ ## 2.11.2 (2026-04-07)
142
+
143
+ * **Bug Fixes:**
144
+ * smtp: fix encoding for email_from
145
+
146
+ ## 2.11.1 (2026-03-11)
147
+
148
+ * **Bug Fixes:**
149
+ * fix: add support for configargparse >= 1.7.5
150
+ * fix: bookwork test by pinning setuptools version
151
+
152
+ ## 2.11.0 (2025-01-14)
132
153
 
133
154
  * **New Features**
134
155
  * Administrators can disable user accounts (#313).
@@ -167,15 +188,15 @@ We are passionate about developing and maintaining this open-source project to m
167
188
  * Dropped Ubuntu Oracular
168
189
  * Dropped Debian Bullseye due to backports/EOL.
169
190
 
170
- # 2.10.6 (2025-10-02)
191
+ ## 2.10.6 (2025-10-02)
171
192
 
172
193
  * Security: fix token impersonation vulnerability (CVE-2025-67796).
173
194
 
174
- # 2.10.5 (2025-06-20)
195
+ ## 2.10.5 (2025-06-20)
175
196
 
176
197
  * Send deprecation warning into the logs
177
198
 
178
- # 2.10.4 (2025-06-13)
199
+ ## 2.10.4 (2025-06-13)
179
200
 
180
201
  * **New Features:**
181
202
  * Added Swagger documentation for the Rdiffweb API (#325).
@@ -19,13 +19,13 @@ import cherrypy
19
19
  def is_admin():
20
20
  # Validate the permissions.
21
21
  if not cherrypy.serving.request.currentuser or not cherrypy.serving.request.currentuser.is_admin:
22
- raise cherrypy.HTTPError(404)
22
+ raise cherrypy.HTTPError(403)
23
23
 
24
24
 
25
25
  def is_maintainer():
26
26
  # Validate the permissions.
27
27
  if not cherrypy.serving.request.currentuser or not cherrypy.serving.request.currentuser.is_maintainer:
28
- raise cherrypy.HTTPError(404)
28
+ raise cherrypy.HTTPError(403)
29
29
 
30
30
 
31
31
  # Make sure it's running after authentication (priority = 72)
@@ -414,6 +414,7 @@ class AdminUsersPage(Controller):
414
414
 
415
415
 
416
416
  @cherrypy.expose
417
+ @cherrypy.tools.is_admin()
417
418
  @cherrypy.tools.required_scope(scope='all,admin_read_users')
418
419
  class AdminApiUsers(Controller):
419
420
  ROLES_MAP = {v: k for k, v in UserObject.ROLES.items()}
@@ -39,4 +39,4 @@ class AdminPagesAsUser(rdiffweb.test.WebCase):
39
39
  )
40
40
  def test_forbidden_access(self, value):
41
41
  self.getPage(value)
42
- self.assertStatus(404)
42
+ self.assertStatus(403)
@@ -633,6 +633,19 @@ class AdminApiUsersTest(rdiffweb.test.WebCase):
633
633
 
634
634
  auth = [("Authorization", "Basic " + b64encode(b"admin:admin123").decode('ascii'))]
635
635
 
636
+ def test_not_admin(self):
637
+ # Given a user (not-admin)
638
+ user_obj = UserObject(username='newuser').add()
639
+ user_obj.set_password('gV3NJqqGr5wc8vh')
640
+ user_obj.commit()
641
+ auth = [("Authorization", "Basic " + b64encode(b"newuser:gV3NJqqGr5wc8vh").decode('ascii'))]
642
+
643
+ # When trying to access /api/users
644
+ self.getPage('/api/users', headers=auth)
645
+
646
+ # Then access is denied
647
+ self.assertStatus(403)
648
+
636
649
  @parameterized.expand(
637
650
  [
638
651
  ('with_userid', 0),
@@ -256,7 +256,7 @@ class DeleteRepoTest(rdiffweb.test.WebCase):
256
256
 
257
257
  # Try to delete own own repo
258
258
  self._delete('user', 'testcases', 'testcases')
259
- self.assertStatus(404)
259
+ self.assertStatus(403)
260
260
 
261
261
  # Check database don't change
262
262
  self.assertEqual(['broker-repo', 'testcases'], [r.name for r in user_obj.repo_objs])
@@ -117,7 +117,7 @@ class StatusTest(rdiffweb.test.WebCase):
117
117
 
118
118
  # Browse admin's repos
119
119
  self.getPage(url)
120
- self.assertStatus(404)
120
+ self.assertStatus(403)
121
121
 
122
122
  def test_with_invalid_username(self):
123
123
  # Given an invalid repo
@@ -18,7 +18,7 @@ import itertools
18
18
  import json
19
19
 
20
20
  import cherrypy
21
- from sqlalchemy import Column, String, and_, event, inspect
21
+ from sqlalchemy import Column, String, and_, event, inspect, text
22
22
  from sqlalchemy.orm import backref, declared_attr, foreign, relationship, remote
23
23
  from sqlalchemy.sql.functions import func
24
24
  from sqlalchemy.sql.schema import ForeignKey
@@ -27,7 +27,7 @@ from sqlalchemy.sql.sqltypes import Integer
27
27
  import rdiffweb.plugins.db # noqa
28
28
 
29
29
  from ._timestamp import Timestamp
30
- from ._update import column_add, column_exists
30
+ from ._update import column_add, column_exists, constraint_add, constraint_exists, is_sqlite
31
31
 
32
32
  Base = cherrypy.db.get_base()
33
33
  Session = cherrypy.db.get_session()
@@ -113,7 +113,9 @@ class Message(Base):
113
113
  model_name = Column(String, nullable=False)
114
114
  model_id = Column(Integer, nullable=False)
115
115
  model_summary = Column(String, nullable=False, default='', server_default='')
116
- author_id = Column(Integer, ForeignKey('users.UserID'), nullable=True)
116
+ author_id = Column(
117
+ Integer, ForeignKey('users.UserID', name='fk_messages_author_id', ondelete="SET NULL"), nullable=True
118
+ )
117
119
  author = relationship("UserObject", lazy=False)
118
120
  ip_address = Column(String, nullable=False, default='', server_default='')
119
121
  user_agent = Column(String, nullable=False, default='', server_default='')
@@ -265,3 +267,14 @@ def update_message_schema(target, conn, **kw):
265
267
  column_add(conn, Message.ip_address)
266
268
  if not column_exists(conn, Message.user_agent):
267
269
  column_add(conn, Message.user_agent)
270
+
271
+ # Since 2.11.4 - author_id ondelete="SET NULL"
272
+ fk_constraint = next(c for c in Message.__table__.foreign_key_constraints if c.name == 'fk_messages_author_id')
273
+ if not constraint_exists(conn, fk_constraint):
274
+ if not is_sqlite(conn):
275
+ # With postgresql drop previous constraint.
276
+ conn.execute(
277
+ text("ALTER TABLE %s DROP CONSTRAINT IF EXISTS %s" % (Message.__tablename__, fk_constraint.name))
278
+ )
279
+ # Then add the constraint.
280
+ constraint_add(conn, fk_constraint)
@@ -179,6 +179,48 @@ INSERT INTO sqlite_sequence VALUES('repos',3);
179
179
  COMMIT;
180
180
  """
181
181
 
182
+ # Test messages FOREIGN KEY ondelete="SET NULL".
183
+ SQL_2_11_3 = """
184
+ BEGIN TRANSACTION;
185
+ CREATE TABLE IF NOT EXISTS "messages" (
186
+ "id" INTEGER NOT NULL,
187
+ "model_name" VARCHAR NOT NULL,
188
+ "model_id" INTEGER NOT NULL,
189
+ "model_summary" VARCHAR NOT NULL DEFAULT '',
190
+ "author_id" INTEGER,
191
+ "ip_address" VARCHAR NOT NULL DEFAULT '',
192
+ "user_agent" VARCHAR NOT NULL DEFAULT '',
193
+ "type" VARCHAR NOT NULL DEFAULT 'comment',
194
+ "body" VARCHAR NOT NULL DEFAULT '',
195
+ "changes" VARCHAR,
196
+ "date" DATETIME,
197
+ PRIMARY KEY("id"),
198
+ FOREIGN KEY("author_id") REFERENCES "users"("UserID")
199
+ );
200
+ CREATE TABLE IF NOT EXISTS "users" (
201
+ "UserID" INTEGER NOT NULL,
202
+ "Username" VARCHAR NOT NULL,
203
+ "Password" VARCHAR NOT NULL,
204
+ "UserRoot" VARCHAR NOT NULL,
205
+ "IsAdmin" SMALLINT NOT NULL DEFAULT '0',
206
+ "UserEmail" VARCHAR NOT NULL DEFAULT '',
207
+ "RestoreFormat" SMALLINT NOT NULL DEFAULT '1',
208
+ "role" SMALLINT NOT NULL DEFAULT '10',
209
+ "fullname" VARCHAR NOT NULL DEFAULT '',
210
+ "mfa" SMALLINT NOT NULL DEFAULT '0',
211
+ "lang" VARCHAR NOT NULL DEFAULT '',
212
+ "timezone" VARCHAR NOT NULL DEFAULT '',
213
+ "report_time_range" SMALLINT NOT NULL DEFAULT '0',
214
+ "report_last_sent" DATETIME,
215
+ "notes" VARCHAR NOT NULL DEFAULT '',
216
+ "status" VARCHAR NOT NULL DEFAULT '',
217
+ PRIMARY KEY("UserID" AUTOINCREMENT),
218
+ CONSTRAINT "users_username_nan_ck" CHECK("Username" REGEXP '^[a-zA-Z][a-zA-Z0-9_.\\-]+$')
219
+ );
220
+ INSERT INTO "users" VALUES (1, 'admin', '$argon2id$v=19$m=65536,t=3,p=4$KrHpfwZ7l50byo6q59sdlA$l+yJKeZ8OxcGKtM8zcGVe5kXokRzKYvYBJSXjIXditc', '/backups/admin', 0, '', 1, 0, '', 0, '', '', 0, NULL, '', '');
221
+ COMMIT;
222
+ """
223
+
182
224
 
183
225
  @parameterized_class(
184
226
  [
@@ -187,6 +229,7 @@ COMMIT;
187
229
  {"name": "with_duplicate_users", "init_sql": SQL_WITH_DUPLICATE_USERS, "success": False},
188
230
  {"name": "with_invalid_usernames", "init_sql": SQL_WITH_INVALID_USERNAMES, "success": False},
189
231
  {"name": "with_null_fields", "init_sql": SQL_WITH_NULL_FIELDS, "success": True},
232
+ {"name": "with_fk_ondelete_set_null", "init_sql": SQL_2_11_3, "success": True},
190
233
  ]
191
234
  )
192
235
  @skipIf(os.environ.get('RDIFFWEB_TEST_DATABASE_URI'), 'custom database')
@@ -24,7 +24,7 @@ from sqlalchemy.exc import IntegrityError
24
24
 
25
25
  import rdiffweb.test
26
26
  from rdiffweb.core import authorizedkeys
27
- from rdiffweb.core.model import RepoObject, UserObject
27
+ from rdiffweb.core.model import Message, RepoObject, UserObject
28
28
  from rdiffweb.core.passwd import check_password
29
29
 
30
30
 
@@ -282,10 +282,19 @@ class UserObjectTest(rdiffweb.test.WebCase):
282
282
  self.listener.user_password_changed.assert_called_once_with(userobj)
283
283
 
284
284
  def test_delete_user(self):
285
- # Given an existing user in database
286
- userobj = UserObject.add_user('vicky')
285
+ # Given an existing user in database with some data
286
+ userobj = UserObject.add_user('vicky', password='test123', user_root=os.path.join(self.testcases, 'testcases'))
287
+ userobj.add_authorizedkey(self._read_ssh_key())
288
+ userobj.add_access_token('test')
289
+ userobj.refresh_repos()
290
+ userobj.commit()
291
+ self.assertTrue(userobj.authorizedkeys)
292
+ self.assertTrue(userobj.tokens)
293
+ self.assertTrue(userobj.repo_objs)
294
+ userobj.repo_objs[0].add_message(Message(body='foo bar', author=userobj))
287
295
  userobj.commit()
288
- self.assertIsNotNone(UserObject.get_user('vicky'))
296
+ # Wait for login message to be logged
297
+ cherrypy.scheduler.wait_for_jobs()
289
298
  # When deleting that user
290
299
  userobj.delete()
291
300
  userobj.commit()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rdiffweb
3
- Version: 2.11.2
3
+ Version: 2.11.4
4
4
  Summary: A web interface to rdiff-backup repositories.
5
5
  Author-email: Patrik Dufresne <patrik@ikus-soft.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -851,7 +851,28 @@ We are passionate about developing and maintaining this open-source project to m
851
851
 
852
852
  # Changelog
853
853
 
854
- # 2.11.0 (2025-01-14)
854
+ ## 2.11.4 (2026-04-23)
855
+
856
+ * **Bug Fixes:**
857
+ * db: fix user deletion raising foreign key errors
858
+
859
+ ## 2.11.3 (2026-04-09)
860
+
861
+ * **Security Fixes:**
862
+ * api: restrict `/api/users` endpoint to administrators only
863
+
864
+ ## 2.11.2 (2026-04-07)
865
+
866
+ * **Bug Fixes:**
867
+ * smtp: fix encoding for email_from
868
+
869
+ ## 2.11.1 (2026-03-11)
870
+
871
+ * **Bug Fixes:**
872
+ * fix: add support for configargparse >= 1.7.5
873
+ * fix: bookwork test by pinning setuptools version
874
+
875
+ ## 2.11.0 (2025-01-14)
855
876
 
856
877
  * **New Features**
857
878
  * Administrators can disable user accounts (#313).
@@ -890,15 +911,15 @@ We are passionate about developing and maintaining this open-source project to m
890
911
  * Dropped Ubuntu Oracular
891
912
  * Dropped Debian Bullseye due to backports/EOL.
892
913
 
893
- # 2.10.6 (2025-10-02)
914
+ ## 2.10.6 (2025-10-02)
894
915
 
895
916
  * Security: fix token impersonation vulnerability (CVE-2025-67796).
896
917
 
897
- # 2.10.5 (2025-06-20)
918
+ ## 2.10.5 (2025-06-20)
898
919
 
899
920
  * Send deprecation warning into the logs
900
921
 
901
- # 2.10.4 (2025-06-13)
922
+ ## 2.10.4 (2025-06-13)
902
923
 
903
924
  * **New Features:**
904
925
  * Added Swagger documentation for the Rdiffweb API (#325).
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes