aird 0.4.23.dev18__tar.gz → 0.4.23.dev20__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 (209) hide show
  1. {aird-0.4.23.dev18/aird.egg-info → aird-0.4.23.dev20}/PKG-INFO +1 -1
  2. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/__init__.py +1 -1
  3. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/file_op_handlers.py +1 -1
  4. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/browse/app.js +5 -5
  5. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/download-manager.js +6 -11
  6. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/file-transfer-ws.js +48 -7
  7. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/transfer-tracker.js +7 -0
  8. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/browse.html +0 -2
  9. {aird-0.4.23.dev18 → aird-0.4.23.dev20/aird.egg-info}/PKG-INFO +1 -1
  10. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/SOURCES.txt +0 -2
  11. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/setup.py +1 -1
  12. aird-0.4.23.dev18/aird/static/js/file-transfer-http.js +0 -98
  13. aird-0.4.23.dev18/aird/static/js/file-transfer.js +0 -55
  14. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/LICENSE +0 -0
  15. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/MANIFEST.in +0 -0
  16. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/README.md +0 -0
  17. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/__init__.py +0 -0
  18. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/__main__.py +0 -0
  19. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/app_context.py +0 -0
  20. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/__init__.py +0 -0
  21. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/__main__.py +0 -0
  22. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/authelia.py +0 -0
  23. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/config.py +0 -0
  24. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/main.py +0 -0
  25. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cli/session.py +0 -0
  26. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/cloud/__init__.py +0 -0
  27. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/config.py +0 -0
  28. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/admin.py +0 -0
  29. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/file_ops.py +0 -0
  30. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/input_limits.py +0 -0
  31. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/constants/media.py +0 -0
  32. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/__init__.py +0 -0
  33. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/events.py +0 -0
  34. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/file_operations.py +0 -0
  35. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/filter_expression.py +0 -0
  36. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/folder_size.py +0 -0
  37. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/input_validation.py +0 -0
  38. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/mmap_handler.py +0 -0
  39. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/security.py +0 -0
  40. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/share_root.py +0 -0
  41. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/websocket_manager.py +0 -0
  42. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/core/zip_download.py +0 -0
  43. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/database/__init__.py +0 -0
  44. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/database/db.py +0 -0
  45. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/database/feature_flags.py +0 -0
  46. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/database/ldap.py +0 -0
  47. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/__init__.py +0 -0
  48. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/audit.py +0 -0
  49. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/config.py +0 -0
  50. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/favorites.py +0 -0
  51. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/network_shares.py +0 -0
  52. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/policies.py +0 -0
  53. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/policy_decisions.py +0 -0
  54. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/policy_seeds.py +0 -0
  55. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/quota.py +0 -0
  56. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/resource_tags.py +0 -0
  57. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/schema.py +0 -0
  58. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/shares.py +0 -0
  59. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/user_attributes.py +0 -0
  60. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/db/users.py +0 -0
  61. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/domain/__init__.py +0 -0
  62. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/domain/contracts.py +0 -0
  63. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/domain/models.py +0 -0
  64. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/email/__init__.py +0 -0
  65. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/email/brevo.py +0 -0
  66. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/email/resolve.py +0 -0
  67. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/event_loop.py +0 -0
  68. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/__init__.py +0 -0
  69. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/abac_handlers.py +0 -0
  70. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/admin_handlers.py +0 -0
  71. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/api_handlers.py +0 -0
  72. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/auth_handlers.py +0 -0
  73. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/base_handler.py +0 -0
  74. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/constants.py +0 -0
  75. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/health_handler.py +0 -0
  76. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/p2p_handlers.py +0 -0
  77. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/share_handlers.py +0 -0
  78. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/transfer_ws_handlers.py +0 -0
  79. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/handlers/view_handlers.py +0 -0
  80. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/main.py +0 -0
  81. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/network_share_manager.py +0 -0
  82. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/server_runtime.py +0 -0
  83. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/__init__.py +0 -0
  84. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/audit_service.py +0 -0
  85. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/config_service.py +0 -0
  86. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/email_service.py +0 -0
  87. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/email_subscriber.py +0 -0
  88. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/event_subscribers.py +0 -0
  89. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/favorites_service.py +0 -0
  90. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/network_share_service.py +0 -0
  91. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/p2p_service.py +0 -0
  92. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/policy_service.py +0 -0
  93. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/quota_service.py +0 -0
  94. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/share_service.py +0 -0
  95. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/tag_service.py +0 -0
  96. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/services/user_service.py +0 -0
  97. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/sql_identifiers.py +0 -0
  98. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/css/app.css +0 -0
  99. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/favicon.png +0 -0
  100. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/favicon.svg +0 -0
  101. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/img/logo-icon.png +0 -0
  102. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/img/logo-mark.svg +0 -0
  103. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/img/logo-text.png +0 -0
  104. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/img/logo.png +0 -0
  105. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/aird-core.js +0 -0
  106. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/bg-canvas.js +0 -0
  107. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/common/command-palette.js +0 -0
  108. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/components/folder-picker.js +0 -0
  109. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/feature-flags-live.js +0 -0
  110. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/folder-size-scan.js +0 -0
  111. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/login-ui.js +0 -0
  112. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/media-view.js +0 -0
  113. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/app.js +0 -0
  114. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/mediator.js +0 -0
  115. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/qr-adapter.js +0 -0
  116. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/signaling-service.js +0 -0
  117. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/state-machine.js +0 -0
  118. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/p2p/transfer-service.js +0 -0
  119. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/pages/p2p-page.js +0 -0
  120. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/pages/super-search.js +0 -0
  121. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/share/app.js +0 -0
  122. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/theme.js +0 -0
  123. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/vendor/pdf.min.js +0 -0
  124. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/vendor/pdf.worker.min.js +0 -0
  125. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/static/js/vendor/qrcode-browser.js +0 -0
  126. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_admin_tabs.html +0 -0
  127. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_app_nav_header.html +0 -0
  128. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_bg_canvas.html +0 -0
  129. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_theme_early.html +0 -0
  130. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/_theme_login_corner.html +0 -0
  131. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin.html +0 -0
  132. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_audit.html +0 -0
  133. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_ldap.html +0 -0
  134. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_login.html +0 -0
  135. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_network_shares.html +0 -0
  136. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_policies.html +0 -0
  137. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_tags.html +0 -0
  138. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_user_attributes.html +0 -0
  139. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/admin_users.html +0 -0
  140. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/directory.html +0 -0
  141. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/edit.html +0 -0
  142. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/error.html +0 -0
  143. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/file.html +0 -0
  144. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/ldap_config_create.html +0 -0
  145. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/ldap_config_edit.html +0 -0
  146. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/login.html +0 -0
  147. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/media_view.html +0 -0
  148. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/p2p_transfer.html +0 -0
  149. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/profile.html +0 -0
  150. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/share.html +0 -0
  151. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/shared_list.html +0 -0
  152. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/super_search.html +0 -0
  153. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/tagged_files.html +0 -0
  154. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/token_verification.html +0 -0
  155. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/user_create.html +0 -0
  156. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/templates/user_edit.html +0 -0
  157. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/utils/__init__.py +0 -0
  158. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird/utils/util.py +0 -0
  159. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/dependency_links.txt +0 -0
  160. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/entry_points.txt +0 -0
  161. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/requires.txt +0 -0
  162. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/aird.egg-info/top_level.txt +0 -0
  163. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/setup.cfg +0 -0
  164. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/__init__.py +0 -0
  165. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/conftest.py +0 -0
  166. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/handler_helpers.py +0 -0
  167. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_admin_handlers.py +0 -0
  168. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_api_handlers.py +0 -0
  169. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_architecture_conformance.py +0 -0
  170. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_auth_handlers.py +0 -0
  171. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_auth_handlers_extended.py +0 -0
  172. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_base_handler.py +0 -0
  173. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_base_handler_pep.py +0 -0
  174. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_cli.py +0 -0
  175. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_cloud.py +0 -0
  176. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_config.py +0 -0
  177. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_core_file_operations.py +0 -0
  178. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_db.py +0 -0
  179. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_feature_flags.py +0 -0
  180. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_ldap.py +0 -0
  181. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_shares.py +0 -0
  182. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_users.py +0 -0
  183. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_database_users_hashing.py +0 -0
  184. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_db.py +0 -0
  185. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_email_service.py +0 -0
  186. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_file_op_handlers.py +0 -0
  187. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_filter_expression.py +0 -0
  188. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_folder_size.py +0 -0
  189. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_main.py +0 -0
  190. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_mmap_handler.py +0 -0
  191. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_multi_user.py +0 -0
  192. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_network_shares.py +0 -0
  193. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_p2p_handlers.py +0 -0
  194. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_password_hashing.py +0 -0
  195. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_policy_service.py +0 -0
  196. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_rate_limit.py +0 -0
  197. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_security.py +0 -0
  198. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_security_comprehensive.py +0 -0
  199. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_server_runtime.py +0 -0
  200. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_share_handlers.py +0 -0
  201. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_share_ownership.py +0 -0
  202. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_super_search_handler.py +0 -0
  203. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_tag_service.py +0 -0
  204. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_transfer_ws_handlers.py +0 -0
  205. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_util.py +0 -0
  206. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_view_handlers.py +0 -0
  207. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_websocket_manager.py +0 -0
  208. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_wheel_static_assets.py +0 -0
  209. {aird-0.4.23.dev18 → aird-0.4.23.dev20}/tests/test_zip_download.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aird
3
- Version: 0.4.23.dev18
3
+ Version: 0.4.23.dev20
4
4
  Summary: Aird - A lightweight web-based file browser, editor, and streamer with real-time capabilities
5
5
  Home-page: https://github.com/blinkerbit/aird
6
6
  Author: Viswantha Srinivas P
@@ -63,7 +63,7 @@ UPLOAD_CONFIG = {
63
63
 
64
64
  # File operation constants (derived from UPLOAD_CONFIG at startup)
65
65
  MAX_FILE_SIZE = UPLOAD_CONFIG["max_file_size_mb"] * 1024 * 1024
66
- # HTTP /upload body limit (browser uploads stream POST /upload; CLI may POST whole file)
66
+ # HTTP /upload body limit (browser uploads use WebSocket; CLI may POST whole file)
67
67
  UPLOAD_REQUEST_MAX_BODY_SIZE = MAX_FILE_SIZE + (1024 * 1024)
68
68
  MAX_READABLE_FILE_SIZE = 50 * 1024 * 1024 # 50 MB
69
69
 
@@ -349,7 +349,7 @@ def _process_bulk_action(
349
349
 
350
350
  @tornado.web.stream_request_body
351
351
  class UploadHandler(BaseHandler):
352
- """Streamed HTTP upload (browser, CLI, reverse proxy, or direct origin)."""
352
+ """Single-request HTTP upload (CLI / direct origin). Browser uses WebSocket."""
353
353
 
354
354
  def check_xsrf_cookie(self) -> None:
355
355
  """Streamed uploads send raw body; accept X-XSRFToken header or ?_xsrf= query param."""
@@ -258,7 +258,7 @@
258
258
  const raw = (err && err.message) ? String(err.message).trim() : "";
259
259
  if (!raw || raw === "cancelled") return raw;
260
260
  const lower = raw.toLowerCase();
261
- if (lower.includes("network") || lower.includes("websocket") || lower.includes("http")) {
261
+ if (lower.includes("network") || lower.includes("websocket")) {
262
262
  return "Upload interrupted. Check your connection and try again.";
263
263
  }
264
264
  if (lower.includes("403") || lower.includes("access denied")) {
@@ -271,15 +271,15 @@
271
271
  }
272
272
 
273
273
  async function uploadFile(item) {
274
- const FT = globalThis.AirdFileTransfer;
275
- if (!FT?.uploadFile) {
276
- throw new Error("Upload unavailable. Hard-refresh the page.");
274
+ const FTW = globalThis.AirdFileTransferWs;
275
+ if (!FTW?.uploadFile) {
276
+ throw new Error("WebSocket upload unavailable. Hard-refresh the page.");
277
277
  }
278
278
  const dir = item.uploadDir ?? document.getElementById('currentPath')?.value ?? '';
279
279
  const fname = item.uploadName ?? item.file.name;
280
280
  item.uploadSignal = { aborted: false };
281
281
  const cancelFn = () => abortActiveUploads(item);
282
- await FT.uploadFile(item.file, {
282
+ await FTW.uploadFile(item.file, {
283
283
  uploadDir: dir,
284
284
  filename: fname,
285
285
  signal: item.uploadSignal,
@@ -59,19 +59,9 @@
59
59
 
60
60
  cancelOne(item) {
61
61
  if (!item) return;
62
- if (item.status === 'downloading' && item.cancelSignal) {
62
+ if (item.status === 'downloading' || item.status === 'queued') {
63
63
  item.cancelSignal.aborted = true;
64
64
  item.status = 'cancelled';
65
- if (item.ttId != null) {
66
- global.AirdTransferTracker?.failTransfer(item.ttId, 'Cancelled');
67
- }
68
- return;
69
- }
70
- if (item.status !== 'queued') return;
71
- item.status = 'cancelled';
72
- item.cancelSignal.aborted = true;
73
- if (item.ttId != null) {
74
- global.AirdTransferTracker?.failTransfer(item.ttId, 'Cancelled');
75
65
  }
76
66
  }
77
67
 
@@ -103,9 +93,14 @@
103
93
  if (item.ws && FTW?.downloadFile) {
104
94
  item.status = 'downloading';
105
95
  item.downloadStart = Date.now();
96
+ const onCancel = () => {
97
+ item.cancelSignal.aborted = true;
98
+ item.status = 'cancelled';
99
+ };
106
100
  try {
107
101
  const result = await FTW.downloadFile(item.path, {
108
102
  signal: item.cancelSignal,
103
+ onCancel: onCancel,
109
104
  });
110
105
  if (item.cancelSignal?.aborted || this.cancelled) {
111
106
  item.status = 'cancelled';
@@ -155,22 +155,30 @@
155
155
 
156
156
  /**
157
157
  * @param {string} path relative file path
158
- * @param {{ onProgress?: (loaded: number, total: number) => void, signal?: { aborted: boolean } }} options
158
+ * @param {{ onProgress?: (loaded: number, total: number) => void, signal?: { aborted: boolean }, onCancel?: Function }} options
159
159
  */
160
160
  async function downloadFile(path, options) {
161
161
  options = options || {};
162
162
  const onProgress = options.onProgress || function () {};
163
- const signal = options.signal;
163
+ const signal = options.signal || { aborted: false };
164
164
  const ws = await openSocket();
165
165
  const chunks = [];
166
166
  let meta = null;
167
+ let settled = false;
168
+ let abortPoll = null;
167
169
 
168
170
  const TT = global.AirdTransferTracker;
169
171
  const fname = path.split('/').pop() || path;
170
- const ttId = TT ? TT.addTransfer(fname, 0, 'download') : null;
172
+ const ttId = TT
173
+ ? TT.addTransfer(fname, 0, 'download', { onCancel: options.onCancel })
174
+ : null;
171
175
 
172
176
  return new Promise((resolve, reject) => {
173
177
  function cleanup() {
178
+ if (abortPoll !== null) {
179
+ clearInterval(abortPoll);
180
+ abortPoll = null;
181
+ }
174
182
  ws.removeEventListener('message', onMessage);
175
183
  try {
176
184
  ws.close();
@@ -179,11 +187,38 @@
179
187
  }
180
188
  }
181
189
 
190
+ function finishCancel() {
191
+ if (settled) return;
192
+ settled = true;
193
+ signal.aborted = true;
194
+ try {
195
+ ws.send(JSON.stringify({ action: 'cancel' }));
196
+ } catch {
197
+ /* ignore */
198
+ }
199
+ cleanup();
200
+ if (TT && ttId) TT.failTransfer(ttId, 'Cancelled');
201
+ reject(new Error('cancelled'));
202
+ }
203
+
204
+ if (TT && ttId) {
205
+ TT.setCancelHandler(ttId, function () {
206
+ if (typeof options.onCancel === 'function') {
207
+ options.onCancel();
208
+ }
209
+ finishCancel();
210
+ });
211
+ }
212
+
213
+ if (signal) {
214
+ abortPoll = setInterval(() => {
215
+ if (signal.aborted) finishCancel();
216
+ }, 100);
217
+ }
218
+
182
219
  function onMessage(ev) {
183
- if (signal && signal.aborted) {
184
- cleanup();
185
- if (TT && ttId) TT.failTransfer(ttId, 'Cancelled');
186
- reject(new Error('cancelled'));
220
+ if (signal.aborted) {
221
+ finishCancel();
187
222
  return;
188
223
  }
189
224
  if (typeof ev.data === 'string') {
@@ -194,6 +229,8 @@
194
229
  return;
195
230
  }
196
231
  if (msg.type === 'error') {
232
+ if (settled) return;
233
+ settled = true;
197
234
  cleanup();
198
235
  if (TT && ttId) TT.failTransfer(ttId, msg.message);
199
236
  reject(new Error(msg.message || 'download failed'));
@@ -205,6 +242,8 @@
205
242
  return;
206
243
  }
207
244
  if (msg.type === 'download_end') {
245
+ if (settled) return;
246
+ settled = true;
208
247
  cleanup();
209
248
  if (TT && ttId) TT.completeTransfer(ttId);
210
249
  const blob = new Blob(chunks, {
@@ -229,6 +268,8 @@
229
268
 
230
269
  ws.addEventListener('message', onMessage);
231
270
  ws.addEventListener('error', () => {
271
+ if (settled) return;
272
+ settled = true;
232
273
  cleanup();
233
274
  if (TT && ttId) TT.failTransfer(ttId, 'WebSocket error');
234
275
  reject(new Error('WebSocket error'));
@@ -278,6 +278,12 @@
278
278
  }, 8000);
279
279
  }
280
280
 
281
+ function removeTransfer(id) {
282
+ if (_items.delete(id)) {
283
+ _render();
284
+ }
285
+ }
286
+
281
287
  function completeByExternalId(externalId) {
282
288
  var id = _findByExternalId(externalId);
283
289
  if (id != null) completeTransfer(id);
@@ -305,6 +311,7 @@
305
311
  setCancelHandler: setCancelHandler,
306
312
  completeTransfer: completeTransfer,
307
313
  failTransfer: failTransfer,
314
+ removeTransfer: removeTransfer,
308
315
  completeByExternalId: completeByExternalId,
309
316
  failByExternalId: failByExternalId,
310
317
  updateProgressByExternalId: updateProgressByExternalId,
@@ -342,8 +342,6 @@
342
342
  <input type="hidden" id="currentPath" value="{{ current_path or '' }}" />
343
343
  <script src="/static/js/aird-core.js?v={{ static_version }}"></script>
344
344
  <script src="/static/js/file-transfer-ws.js?v={{ static_version }}"></script>
345
- <script src="/static/js/file-transfer-http.js?v={{ static_version }}"></script>
346
- <script src="/static/js/file-transfer.js?v={{ static_version }}"></script>
347
345
  <script src="/static/js/download-manager.js?v={{ static_version }}"></script>
348
346
  <script src="/static/js/components/folder-picker.js?v={{ static_version }}"></script>
349
347
  <script nonce="{{ csp_nonce }}">
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aird
3
- Version: 0.4.23.dev18
3
+ Version: 0.4.23.dev20
4
4
  Summary: Aird - A lightweight web-based file browser, editor, and streamer with real-time capabilities
5
5
  Home-page: https://github.com/blinkerbit/aird
6
6
  Author: Viswantha Srinivas P
@@ -102,9 +102,7 @@ aird/static/js/aird-core.js
102
102
  aird/static/js/bg-canvas.js
103
103
  aird/static/js/download-manager.js
104
104
  aird/static/js/feature-flags-live.js
105
- aird/static/js/file-transfer-http.js
106
105
  aird/static/js/file-transfer-ws.js
107
- aird/static/js/file-transfer.js
108
106
  aird/static/js/folder-size-scan.js
109
107
  aird/static/js/login-ui.js
110
108
  aird/static/js/media-view.js
@@ -16,7 +16,7 @@ install_requires = [
16
16
 
17
17
  setup(
18
18
  name="aird",
19
- version="0.4.23.dev18",
19
+ version="0.4.23.dev20",
20
20
  packages=find_packages(),
21
21
  include_package_data=True,
22
22
  package_data={"aird": [
@@ -1,98 +0,0 @@
1
- /**
2
- * HTTP streaming upload (POST /upload). Works via Cloudflare HTTP/3 or direct to origin.
3
- */
4
- (function (global) {
5
- 'use strict';
6
-
7
- function getXSRFToken() {
8
- if (global.AirdCore?.getXSRFToken) {
9
- return global.AirdCore.getXSRFToken();
10
- }
11
- const match = document.cookie.match(/\b_xsrf=([^;]*)/);
12
- return match ? decodeURIComponent(match[1]) : '';
13
- }
14
-
15
- /**
16
- * @param {File|Blob} file
17
- * @param {{ uploadDir?: string, filename?: string, onProgress?: Function, signal?: { aborted: boolean }, onCancel?: Function }} options
18
- */
19
- function uploadFile(file, options) {
20
- options = options || {};
21
- const uploadDir = options.uploadDir ?? '';
22
- const filename = options.filename ?? (file.name || 'upload');
23
- const onProgress = options.onProgress || function () {};
24
- const signal = options.signal;
25
- const totalSize = file.size;
26
-
27
- const TT = global.AirdTransferTracker;
28
- const ttId = TT
29
- ? TT.addTransfer(filename, totalSize, 'upload', { onCancel: options.onCancel })
30
- : null;
31
- if (TT && ttId && options.onCancel) {
32
- TT.setCancelHandler(ttId, options.onCancel);
33
- }
34
-
35
- return new Promise((resolve, reject) => {
36
- const xhr = new XMLHttpRequest();
37
- let abortPoll = null;
38
-
39
- function cleanup() {
40
- if (abortPoll !== null) {
41
- clearInterval(abortPoll);
42
- abortPoll = null;
43
- }
44
- }
45
-
46
- function fail(err, httpStatus) {
47
- cleanup();
48
- const msg = err?.message || String(err);
49
- const error = err instanceof Error ? err : new Error(msg);
50
- error.httpStatus = httpStatus ?? 0;
51
- if (TT && ttId) TT.failTransfer(ttId, msg);
52
- reject(error);
53
- }
54
-
55
- xhr.upload.addEventListener('progress', (ev) => {
56
- if (!ev.lengthComputable) return;
57
- const loaded = ev.loaded;
58
- const pct = totalSize > 0 ? Math.round((loaded / totalSize) * 100) : 0;
59
- onProgress(pct, loaded, totalSize);
60
- if (TT && ttId) TT.updateProgress(ttId, loaded, totalSize);
61
- });
62
-
63
- xhr.addEventListener('load', () => {
64
- cleanup();
65
- if (xhr.status >= 200 && xhr.status < 300) {
66
- onProgress(100, totalSize, totalSize);
67
- if (TT && ttId) TT.completeTransfer(ttId);
68
- resolve({ message: xhr.responseText || 'Upload successful' });
69
- return;
70
- }
71
- const body = (xhr.responseText || '').trim();
72
- fail(new Error(body || `Upload failed (HTTP ${xhr.status})`), xhr.status);
73
- });
74
-
75
- xhr.addEventListener('error', () => fail(new Error('Network error during upload'), 0));
76
- xhr.addEventListener('abort', () => fail(new Error('cancelled'), 0));
77
-
78
- if (signal) {
79
- abortPoll = setInterval(() => {
80
- if (signal.aborted) {
81
- xhr.abort();
82
- }
83
- }, 100);
84
- }
85
-
86
- xhr.open('POST', '/upload');
87
- xhr.setRequestHeader('X-Upload-Dir', uploadDir);
88
- xhr.setRequestHeader('X-Upload-Filename', filename);
89
- xhr.setRequestHeader('X-XSRFToken', getXSRFToken());
90
- xhr.setRequestHeader('Content-Type', 'application/octet-stream');
91
- xhr.send(file);
92
- });
93
- }
94
-
95
- global.AirdFileTransferHttp = {
96
- uploadFile: uploadFile,
97
- };
98
- })(typeof globalThis !== 'undefined' ? globalThis : window);
@@ -1,55 +0,0 @@
1
- /**
2
- * Upload facade: HTTP first (CF or direct origin), WebSocket fallback when needed.
3
- */
4
- (function (global) {
5
- 'use strict';
6
-
7
- function isCancelled(err) {
8
- const msg = (err && err.message) ? String(err.message).toLowerCase() : '';
9
- return msg === 'cancelled';
10
- }
11
-
12
- /** Use WS when HTTP is blocked, proxied limits apply, or the connection failed. */
13
- function shouldFallbackToWs(err) {
14
- if (!err || isCancelled(err)) return false;
15
- const status = err.httpStatus ?? 0;
16
- if (status === 401 || status === 403 || status === 400) return false;
17
- if (status === 413 || status === 0 || status === 502 || status === 503 || status === 504) {
18
- return true;
19
- }
20
- const msg = String(err.message || '').toLowerCase();
21
- return msg.includes('network error');
22
- }
23
-
24
- /**
25
- * @param {File|Blob} file
26
- * @param {object} options passed to HTTP/WS upload helpers
27
- */
28
- async function uploadFile(file, options) {
29
- options = options || {};
30
- const http = global.AirdFileTransferHttp;
31
- const ws = global.AirdFileTransferWs;
32
-
33
- if (http?.uploadFile) {
34
- try {
35
- return await http.uploadFile(file, options);
36
- } catch (err) {
37
- if (ws?.uploadFile && shouldFallbackToWs(err)) {
38
- return ws.uploadFile(file, options);
39
- }
40
- throw err;
41
- }
42
- }
43
-
44
- if (ws?.uploadFile) {
45
- return ws.uploadFile(file, options);
46
- }
47
- throw new Error('No upload transport available. Hard-refresh the page.');
48
- }
49
-
50
- global.AirdFileTransfer = {
51
- uploadFile: uploadFile,
52
- saveBlob: global.AirdFileTransferWs?.saveBlob,
53
- downloadFile: global.AirdFileTransferWs?.downloadFile,
54
- };
55
- })(typeof globalThis !== 'undefined' ? globalThis : window);
File without changes
File without changes
File without changes
File without changes
File without changes