invenio-app-rdm 13.0.0b3.dev4__py2.py3-none-any.whl → 13.0.0b3.dev6__py2.py3-none-any.whl

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 (30) hide show
  1. invenio_app_rdm/__init__.py +1 -1
  2. invenio_app_rdm/administration/audit_logs/__init__.py +12 -0
  3. invenio_app_rdm/administration/audit_logs/audit_logs.py +77 -0
  4. invenio_app_rdm/administration/templates/semantic-ui/invenio_app_rdm/administration/audit_logs.html +14 -0
  5. invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/details.html +2 -2
  6. invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/licenses.html +50 -36
  7. invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/detail.html +9 -0
  8. invenio_app_rdm/records_ui/views/__init__.py +2 -0
  9. invenio_app_rdm/records_ui/views/decorators.py +10 -7
  10. invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/auditLogs/ViewAction.js +0 -0
  11. invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/auditLogs/index.js +29 -0
  12. invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/auditLogs/search/SearchResultItemLayout.js +71 -0
  13. invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/auditLogs/search/index.js +9 -0
  14. invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/deposit/RDMDepositForm.js +8 -1
  15. invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessUsersGroups/AccessUsersGroups.js +1 -1
  16. invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessUsersGroups/UserGroupAccessSearchResultItem.js +1 -1
  17. invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/files_integrity_report/email/files_integrity_report.html +10 -11
  18. invenio_app_rdm/theme/webpack.py +1 -0
  19. {invenio_app_rdm-13.0.0b3.dev4.dist-info → invenio_app_rdm-13.0.0b3.dev6.dist-info}/METADATA +21 -6
  20. {invenio_app_rdm-13.0.0b3.dev4.dist-info → invenio_app_rdm-13.0.0b3.dev6.dist-info}/RECORD +29 -22
  21. {invenio_app_rdm-13.0.0b3.dev4.dist-info → invenio_app_rdm-13.0.0b3.dev6.dist-info}/WHEEL +1 -1
  22. {invenio_app_rdm-13.0.0b3.dev4.dist-info → invenio_app_rdm-13.0.0b3.dev6.dist-info}/entry_points.txt +1 -0
  23. tests/conftest.py +0 -41
  24. tests/mock_module/templates/mock_mail.html +3 -4
  25. tests/test_tasks.py +121 -16
  26. tests/ui/conftest.py +17 -5
  27. tests/ui/test_file_download.py +73 -0
  28. invenio_app_rdm/urls.py +0 -72
  29. {invenio_app_rdm-13.0.0b3.dev4.dist-info → invenio_app_rdm-13.0.0b3.dev6.dist-info}/licenses/LICENSE +0 -0
  30. {invenio_app_rdm-13.0.0b3.dev4.dist-info → invenio_app_rdm-13.0.0b3.dev6.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,17 @@
1
- invenio_app_rdm/__init__.py,sha256=thlWzdrC3YcR9NNgPa8dKY16F6keY30swQLNnUFlkoY,699
1
+ invenio_app_rdm/__init__.py,sha256=kJtcmQy4EcdGAs8fKNBkktlToihpPYxSR6rtNjBoJX8,699
2
2
  invenio_app_rdm/cli.py,sha256=G6QqNU2W6n6ICtTMnpeKFXIsdorncDmVXwwwsGH5F2k,2746
3
3
  invenio_app_rdm/config.py,sha256=Sv6Q8VEP-KYNuvC6kASLOYC-gYRByYN-hwPmbCxQWKc,50624
4
4
  invenio_app_rdm/ext.py,sha256=PkZhATGJDgYqBJQh41NdvBZWR83mgI3Eej6rj10UVJE,5278
5
5
  invenio_app_rdm/tasks.py,sha256=FyrIQXVuPjms-dNEnLrVmmdwrX_IykJ87gcSNgOR6O0,1373
6
- invenio_app_rdm/urls.py,sha256=8S95QSs4yS0rtORsd4veo--rF3LSLwZenoowJ5ubbmM,2496
7
6
  invenio_app_rdm/views.py,sha256=SDr9NwZEWQcgT_3GFRYdDf6eUaK9DfnoafIkhUf9nSI,785
8
7
  invenio_app_rdm/administration/__init__.py,sha256=8r9LeoE9fNHZSVS5QsCfVhRU7MAiEOWJk9MA3Y--4F8,251
8
+ invenio_app_rdm/administration/audit_logs/__init__.py,sha256=jsBXeKSY5YNn1juF9sFyHPYo_XYpwdP3Dye-de7cMK0,318
9
+ invenio_app_rdm/administration/audit_logs/audit_logs.py,sha256=vgrGQ1lLE5uSuoJCx9kIMQPshjxJzZlCZ4v5cZEcKus,2156
9
10
  invenio_app_rdm/administration/domains/__init__.py,sha256=Qob5kqjRPxpuSE5yDV2tesN6tmaKp5JcxCxGA8Mrcak,487
10
11
  invenio_app_rdm/administration/domains/domains.py,sha256=vafLa-mqkg_tQLjx328E64P_4mksB5kjBlsfunvdatg,5599
11
12
  invenio_app_rdm/administration/records/__init__.py,sha256=WpNHBm_Mk9FF8GzvrXWjL79URMSgBhpqgxvrLXNooqg,434
12
13
  invenio_app_rdm/administration/records/records.py,sha256=BFxxnB4acN8Fd3A6CWuyRUjo3bvdWmNSkcxuVZYzTaA,5357
14
+ invenio_app_rdm/administration/templates/semantic-ui/invenio_app_rdm/administration/audit_logs.html,sha256=kLP3lfZiwLB8N-78_xINymnD8TIjGMzeJIO1a1zO130,346
13
15
  invenio_app_rdm/administration/templates/semantic-ui/invenio_app_rdm/administration/domains_search.html,sha256=NP8HPfOQPIR9psNDMFRXJH8fjok2AbXCentD_3Q1wWw,338
14
16
  invenio_app_rdm/administration/templates/semantic-ui/invenio_app_rdm/administration/user_moderation.html,sha256=koXd8lV_KBgAl1Wll7aM3xR0NgYcOl2PiFqD2Xkcp2w,348
15
17
  invenio_app_rdm/administration/templates/semantic-ui/invenio_app_rdm/administration/user_moderation_details.html,sha256=g6YZh9yWqDfzd5kMgIrO4c5k4iKa61y04RsuT_ZbMJI,350
@@ -63,25 +65,25 @@ invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details
63
65
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/subjects.html,sha256=Wu7MCXzGj41K38-VXi-kStvc8fm3Ck68uJ1egfFK0dw,1509
64
66
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/citations.html,sha256=5Sdg_gwGOgm0qLRv4-CUmDNx7PYlOsa5XPGjDdx7k20,258
65
67
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/communities.html,sha256=GxxKbXxVg5lKcSEzVeYJXyz7qUL7yhsZnhXY3lE-vNU,1561
66
- invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/details.html,sha256=zQCx5x5AE_T8nywICNBzo-9K4vNtfPSyz_F_7cC6L8Y,1974
68
+ invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/details.html,sha256=Ip3wBnfpS8U9fBH2q9nZbt7znAzUKvVrbz3QkeBUMUM,1988
67
69
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/export.html,sha256=DoDrQFd_OJcJzqBEQ2FRbcfJpD3TLRjESU68mBLWVyU,1392
68
70
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/external_resources.html,sha256=Ia92YMRlxuGRTMsWU4hQTLJDeRy8BX8bnSSaLXKst4Y,1934
69
71
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/keywords_subjects.html,sha256=LvsA6JiosfwSSwUUg6--3xx1OZepvN7mxQdIWyl9caE,708
70
- invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/licenses.html,sha256=iideMdvDM-TQGqehzRk5W5NmfUBHO-HKjJu_cnVeOps,2702
72
+ invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/licenses.html,sha256=ktAwgEUpB6X8uMk9-ThNEg0_CkyTqfBurTudXNd6mFo,3131
71
73
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/locations.html,sha256=i1EnmQrnmSAYfocoMYtneAB7JyUI309whyu3bZJTR6M,715
72
74
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/manage_menu.html,sha256=CiqcUTXKnbcZASIweFCHeqaRqO0M0k_wjM9Q-S9z0i4,1297
73
75
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/metrics.html,sha256=3OptZ6iQYaQ3GjNw5O-h9FloISUzFE0nSNTmazjTQgQ,520
74
76
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/technical_metadata.html,sha256=N5VUwCygKG-zXvyu0YeFJb7A0eHIcKWuMAVm9Kbrb_M,658
75
77
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/details/side_bar/versions.html,sha256=sPYG81XFcU1ND6roeYmN4SY419iyvQj9ozCv9Pctw5E,932
76
78
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/creatibutors.html,sha256=N53nwtlEZjxweCx70qFJa1s6uL1pPSzWZgk8p1vodE4,4277
77
- invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/detail.html,sha256=1XF9DgxLADlpKY7vAcdXhtaOAyrCCupgi5p0AmnqDiQ,10447
79
+ invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/detail.html,sha256=YEF5tR22t2QUO-tKpjsS4gKhYMZpfyjbO6wWf8LKhJw,10598
78
80
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/doi.html,sha256=NZUtJSCwQScJsmz7vxglslEVqPwG7Ldul_wl7yce0fg,1489
79
81
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/files.html,sha256=Xsq_HiM_cTGKgmoE1HAXje8iYe3d0wIJoesk22Xn7vU,8761
80
82
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/locations.html,sha256=27-KyPqb05pu-yRXHvxCgZWRSi5bFP6xf7XBn91sbeA,1741
81
83
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/stats_popup.html,sha256=5SVzfIS15Aro2Itd2BiaLbMXm0cvvwk6ZCdYjuSwhBw,625
82
84
  invenio_app_rdm/records_ui/templates/semantic-ui/invenio_app_rdm/records/macros/version.html,sha256=eA8-n81XUezkwPXvcG5v2sgLPQNTgr7hB36-_Gr-tVI,758
83
- invenio_app_rdm/records_ui/views/__init__.py,sha256=fzRrhYImQg13KnHfxJgzDlJPe-DzE02GifP2j_Wt480,5726
84
- invenio_app_rdm/records_ui/views/decorators.py,sha256=XUSPpstYyh72IdNaIO4wz3sw1fjI_2DNGsKdUu3ueL4,15769
85
+ invenio_app_rdm/records_ui/views/__init__.py,sha256=9DaDls04IQv7fYttDjLofIWGsRRjk-FwUYnIfxV3OWk,5840
86
+ invenio_app_rdm/records_ui/views/decorators.py,sha256=MUUmgGuigmFMigcpyJbNvM0yPKUyeAw5LE6MJ69BoFA,15883
85
87
  invenio_app_rdm/records_ui/views/deposits.py,sha256=KRR_fpl98EhNZie0Q-_uZtgG2QKsQAW2fhb-kvnQ4s4,21561
86
88
  invenio_app_rdm/records_ui/views/filters.py,sha256=Rm55fXJv97cqq8B_6KCe-3PxxHUH4VRu-jd9fTea6r4,6994
87
89
  invenio_app_rdm/records_ui/views/records.py,sha256=GdxG3JnXrV1QT0KxOqeYWoDGIiZRZ9w5poihPPd-wTo,16428
@@ -103,9 +105,13 @@ invenio_app_rdm/requests_ui/views/requests.py,sha256=grC2bQWF36xzeftdOSjy_vBWAGS
103
105
  invenio_app_rdm/requests_ui/views/ui.py,sha256=DBysYQa__gOCg-pikO6HmoVLmRmMAVWeTBiYhPa7PmA,2359
104
106
  invenio_app_rdm/theme/__init__.py,sha256=QbkxNjjOmGKRlie96HfTXgnFeVQjOX0GdiZnHP7pIhs,277
105
107
  invenio_app_rdm/theme/views.py,sha256=Ucn6o7mF8qR7gtOeliKC73gIBhy5LgY65rvteC1Uiog,4312
106
- invenio_app_rdm/theme/webpack.py,sha256=5ucwIJQgM1y9EFdRcsxv_ThPs7hXRzdmipVBxoU1McI,5090
108
+ invenio_app_rdm/theme/webpack.py,sha256=5oi0YBD84y8246JYGtSNmNbRUH-bz_G8WrSRRDEyplw,5201
107
109
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/theme.js,sha256=LSswk1IkVgUxTT3Arw_QF-mNQ16vVYDf2B90h6FZfFw,4431
108
110
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/utils.js,sha256=oTCQkmr7j6FwVsOfM6hsKrPHfadW7m9IurrqYVDgxDw,3628
111
+ invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/auditLogs/ViewAction.js,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
+ invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/auditLogs/index.js,sha256=7glSWacd986Zu6l_Ob7IXp4uNWA0f51FBfRv4HZxjYU,965
113
+ invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/auditLogs/search/SearchResultItemLayout.js,sha256=wXwMfu8u02A3KT_xZbalntDGvLwVFc9AlorUTuiSqdQ,2268
114
+ invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/auditLogs/search/index.js,sha256=q1WaQ-kNNMvNdnsONMw2c4GWobizoPWsmIdWL2fRCPc,283
109
115
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/components/CompareRevisionsDropdown.js,sha256=BNdMxfFYPhlrGKPg47oc4X8ILllfCngN61L1b7Yt_8Q,2483
110
116
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/components/ImpersonateUser.js,sha256=1tnHc9PaCQvVS1PVsDWtfpWzVxJJ5_eltn9WJEYygiY,2366
111
117
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/administration/components/ImpersonateUserForm.js,sha256=Z21KrMyAJ1rKF5IEzM088-pTvTga21LBnG4GPYvh5g4,6890
@@ -160,7 +166,7 @@ invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/components/CopyButto
160
166
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/components/DisplayPartOfCommunities.js,sha256=bSmhuwSWk4CW80mqa4ZZbjfa-_NsiJ1IxQ9veDy6sAM,2751
161
167
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/components/DisplayVerifiedCommunity.js,sha256=m3rT8jJ3440ZX22zZog8bHatWltYXwvmw_tu6tJUM9k,1506
162
168
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/components/RecordsResultsListItem.js,sha256=RTSQBlGQY7ww7fVGHDvDfWQNyJ07mnEoyboTGIcCgD4,6694
163
- invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/deposit/RDMDepositForm.js,sha256=Z9VF1-4Y9GDY42Jhz9Se9CvY0Ahx_HkqcW-fn97UwKw,31881
169
+ invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/deposit/RDMDepositForm.js,sha256=92Mg5PAjOHZ8pMNHJjyqdHMXLXuaAF6FT12UTJzy9XQ,32295
164
170
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/deposit/ShareDraftButton.js,sha256=ICMV4Ixe-nTe6q7COZ0oyAQf2nVp2cez_-iUZobwUD0,1998
165
171
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/deposit/config.js,sha256=a9Im0S72ne6LGDzM8C-pP9fIhcMihIbOJ5Ez5SwSn9A,1456
166
172
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/deposit/index.js,sha256=gA0BaUFpaJr9nkmHSWoxuwKDfSD3JUTPcadj2TKHN24,1587
@@ -197,11 +203,11 @@ invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOp
197
203
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessLinks/LinksSearchResultContainer.js,sha256=xr5dfml-v7NU2PzCKIB2_BeYFnFghnsqwKMgLErONQI,6786
198
204
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessLinks/LinksTab.js,sha256=Ki1HN02B4_xFNy3YdPp3Mz2YLO-LxUhmNqRKKrvtVlQ,2883
199
205
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessRequests/AccessRequestsTab.js,sha256=tbSeqk7tnApZqLFi7NEegrwAGFKJ0sficF_3DB1Ld-0,8405
200
- invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessUsersGroups/AccessUsersGroups.js,sha256=NPKhCbPLU260vFTayQ0QA6x5JuIcEkLZkvvx8zxy5Iw,6885
206
+ invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessUsersGroups/AccessUsersGroups.js,sha256=tqUTVCNmfTZqY6aqDvZ3FOFl13EwT23AUWASpccdwMY,6886
201
207
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessUsersGroups/AddUserGroupAccessModal.js,sha256=qpaeKpIX2FUhztkBJtD03WlZ_YOziE0_1CF4cGwMb6Y,5839
202
208
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessUsersGroups/GroupsTab.js,sha256=ZqiuZjjr1SZnTs3cBhX7ZckixAVa2KErEZXKY00A3oE,2358
203
209
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessUsersGroups/PeopleTab.js,sha256=yk5anjYE7CNQ9_io3qIAgE_6oeFYvMn0hmc2McpEF_g,2348
204
- invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessUsersGroups/UserGroupAccessSearchResultItem.js,sha256=PRAouFDdR560x3-l6My5UjxG4L14wT76Xu5teAIRyDY,5749
210
+ invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/AccessUsersGroups/UserGroupAccessSearchResultItem.js,sha256=TYluO2lRliHcIoJBiTnAy8H4B-sEsa5h2TZ6mC1Xb7I,5750
205
211
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/landing_page/ShareOptions/api/api.js,sha256=WpRWWdlN_8TqeaMdB7RV2rQJSluetA91qIuJcAddfLY,926
206
212
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/overridableRegistry/index.js,sha256=xktX9vqs7xPTrKmGD93T-faSmg07LNsmK3GepA9F6j0,424
207
213
  invenio_app_rdm/theme/assets/semantic-ui/js/invenio_app_rdm/overridableRegistry/mapping.js,sha256=kRIVYx1pkzq6kNry3M6Cn5hykDkNJAaG7sQ0BdwGSj8,434
@@ -374,7 +380,7 @@ invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/page.html,sha256=zwI
374
380
  invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/page_cover.html,sha256=D-NNfCX38wRjHOq1kzPPncKKUd0b9U1al-NMy48dKvU,357
375
381
  invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/searchbar.html,sha256=tvzez_2CE86wl_lipD44MD1swZcZw5uYqXEvvPMkBIo,2222
376
382
  invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/site_footer.html,sha256=C0xluZe7KCkvRKeeMIt6P8v_EfWyuMCQ_JQvlI0M9Xw,1037
377
- invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/files_integrity_report/email/files_integrity_report.html,sha256=rKkdAZIyJoXp_ayE_8nemEvBvBnDaHEoorklmDS5UWA,1157
383
+ invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/files_integrity_report/email/files_integrity_report.html,sha256=mwbLrf2xabxq0dLQzUNWGHeYVoySo9GaaydT-FKC9g8,1237
378
384
  invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/help/search.de.html,sha256=gefXaGv-ylkBUbvXXJe5EcTS66qoY0-v0XesXICX5_E,9310
379
385
  invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/help/search.en.html,sha256=-EZdjhc4JslSq37_QN3KRL01LBwLJENkRtwBJ-PLSzc,8792
380
386
  invenio_app_rdm/theme/templates/semantic-ui/invenio_app_rdm/help/search.sv.html,sha256=PHSLAuYtRTtsDgArshe5SIDs_M-dw8MUrSIrnNky2gw,9123
@@ -469,10 +475,10 @@ invenio_app_rdm/users_ui/views/__init__.py,sha256=SMdY2NJj9GICfr3Xuok7qdNYVtA2bJ
469
475
  invenio_app_rdm/users_ui/views/dashboard.py,sha256=iUn2PrODAwb8ugmMosJKAjPhUzjCiWiAWoXQr9RUFuc,1793
470
476
  invenio_app_rdm/users_ui/views/ui.py,sha256=W_eXM8dLVIrNHQB2UEh37C9BYoHauft6RyvcDNFHovA,1742
471
477
  invenio_app_rdm/utils/files.py,sha256=CruDyO2gDVadSlWEJD-WHpWHeOQ0juh-Ei9jz3D9yjc,3923
472
- invenio_app_rdm-13.0.0b3.dev4.dist-info/licenses/LICENSE,sha256=AZXFHRrZa5s4m9DV7zZr4bPGTMUvcEPCodeV_AmFI8k,1204
478
+ invenio_app_rdm-13.0.0b3.dev6.dist-info/licenses/LICENSE,sha256=AZXFHRrZa5s4m9DV7zZr4bPGTMUvcEPCodeV_AmFI8k,1204
473
479
  tests/__init__.py,sha256=yKVf0yYRuxmXvyAtLjmfpHGVCsEkZOhs_FojAAM_w-8,244
474
- tests/conftest.py,sha256=6iR-l-DIpQDxN2LLMu6kbHnLsmAW1m8Lq-j8rNNucf8,8956
475
- tests/test_tasks.py,sha256=6l25lcMjL3ZuQr4hsxbAEjSTu_J1aKkOB3ZXqOZZIy0,3712
480
+ tests/conftest.py,sha256=FQ_aSBxGo0gNfV64RJ117GcmgjVbZKwpxF9_3VNdNJY,7931
481
+ tests/test_tasks.py,sha256=YAf2mryFK6Vfzk2053XLBA2e92vbNCTWqJ6ThWhGOuQ,6645
476
482
  tests/test_utils.py,sha256=nvj59DibjRZgLzwnch83tyCw9R1DEuDSQhU7v7mEOT0,1897
477
483
  tests/test_version.py,sha256=c_ayM-WLlD0Q6z939sBnFpMTY160TmFg-9-hGsPa7FE,410
478
484
  tests/test_views.py,sha256=Q0mSOqd6xVrAxQMdc0MAdZRUnxv7gFAkKcBQY-gQtUI,1420
@@ -490,20 +496,21 @@ tests/fixtures/app_data/pages.yaml,sha256=t4pyjwMBVI6MxEkwCtg9urMXo5fh0mzWy-Zr8N
490
496
  tests/fixtures/app_data/pages/about.html,sha256=obB_g3uL1ligwguh0a0-tRLRBB-eGXN1NE-3odp2j-E,11
491
497
  tests/mock_module/__init__.py,sha256=gu6vRcXqYTKCXZjvAIHZRv2w1IvpGiDs7atQJbij5M0,236
492
498
  tests/mock_module/views.py,sha256=TWJQfcql5XaBNtdR9phVl4tHB0YG6g5IG5n08VZTzXE,770
493
- tests/mock_module/templates/mock_mail.html,sha256=H_ya78ip4xS-9ZpBuzVpwD-QE8EKEZpoLayKe0u5rHQ,845
499
+ tests/mock_module/templates/mock_mail.html,sha256=w7eiZbbs1gErCXelGN7NeiTavcDM9yUM702Mygz0oAc,943
494
500
  tests/redirector/__init__.py,sha256=yKVf0yYRuxmXvyAtLjmfpHGVCsEkZOhs_FojAAM_w-8,244
495
501
  tests/redirector/conftest.py,sha256=KAbp0R8tgGoNvMr8mJ1G2AZX6PzLw-PChtbucrLn5_o,1676
496
502
  tests/redirector/test_redirector.py,sha256=iATYglIw3QSoUKpspQCAM4SaG_WmzjL7r1Nmew_KlGY,1002
497
503
  tests/ui/__init__.py,sha256=yKVf0yYRuxmXvyAtLjmfpHGVCsEkZOhs_FojAAM_w-8,244
498
- tests/ui/conftest.py,sha256=id6A9VbwHQtnr8bzQyQXDBDoKUHx8uufuhRVk02mqbk,3015
504
+ tests/ui/conftest.py,sha256=3Msw0lfBoboQ7X-oZv_wGN7UF6StUpHPRVzRvbjhpoI,3472
499
505
  tests/ui/test_deposits.py,sha256=BehQzo1r3_f4Uc9jcXRddd9bS5GfQ3jRRYOM0AMbi3w,3792
500
506
  tests/ui/test_export_formats.py,sha256=pCXJCTp9ykEWb2oB-ynGjQDhFaVsOs31ym0stwfWCaQ,909
507
+ tests/ui/test_file_download.py,sha256=o4JHkFyJxZDaQ5NHRZR_PV98jS9UtklbOZPpduzwWKw,2436
501
508
  tests/ui/test_filters.py,sha256=Q90wsJffjMVir7wNX8taGf2KZleLtPbXZXHLTkBpzLA,284
502
509
  tests/ui/test_signposting_ui.py,sha256=KCSjQlMD2VKlwQCyZYDwYjtVNL35x3u-ZC4ceD5y21w,3847
503
510
  tests/ui/test_static.py,sha256=vO3OQAOhrQESJifnQfM1pw7JYz3J874O8BAb7Cc_PPA,868
504
511
  tests/ui/test_stats_ui.py,sha256=LHa_0hjvpYvliSk_jknWy-90CO82jVElUfK5Ua_ZmfA,3554
505
- invenio_app_rdm-13.0.0b3.dev4.dist-info/METADATA,sha256=vhxrTA79CScM1kPJVbakn9zGiiOnAD6i_dAcJgQUVqQ,12578
506
- invenio_app_rdm-13.0.0b3.dev4.dist-info/WHEEL,sha256=MAQBAzGbXNI3bUmkDsiV_duv8i-gcdnLzw7cfUFwqhU,109
507
- invenio_app_rdm-13.0.0b3.dev4.dist-info/entry_points.txt,sha256=r1vTqYNABeWqRMWitzyR9FnBsAy-KYZKZCp95IziyLY,2070
508
- invenio_app_rdm-13.0.0b3.dev4.dist-info/top_level.txt,sha256=NqTqrntInEAci7EXcNBvouXFMqwyjVQhEI0b7izYRBY,22
509
- invenio_app_rdm-13.0.0b3.dev4.dist-info/RECORD,,
512
+ invenio_app_rdm-13.0.0b3.dev6.dist-info/METADATA,sha256=0IFV1dDonrTlILr6xmZMYIm1o3Ff2EkJ4t1IT8WVzb0,13139
513
+ invenio_app_rdm-13.0.0b3.dev6.dist-info/WHEEL,sha256=oSJJyWjO7Z2XSScFQUpXG1HL-N0sFMqqeKVVbZTPkWc,109
514
+ invenio_app_rdm-13.0.0b3.dev6.dist-info/entry_points.txt,sha256=rfzEeOEdtGy99NlpWzeW-32CoO5XrEpBvlZwLD2Th88,2158
515
+ invenio_app_rdm-13.0.0b3.dev6.dist-info/top_level.txt,sha256=NqTqrntInEAci7EXcNBvouXFMqwyjVQhEI0b7izYRBY,22
516
+ invenio_app_rdm-13.0.0b3.dev6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
@@ -2,6 +2,7 @@
2
2
  rdm = invenio_app_rdm.cli:rdm
3
3
 
4
4
  [invenio_administration.views]
5
+ invenio_app_rdm_audit_logs = invenio_app_rdm.administration.audit_logs:AuditLogListView
5
6
  invenio_app_rdm_drafts_list = invenio_app_rdm.administration.records:DraftAdminListView
6
7
  invenio_app_rdm_records_list = invenio_app_rdm.administration.records:RecordAdminListView
7
8
  invenio_requests_user_moderation_detail = invenio_app_rdm.administration.user_moderation:UserModerationRequestDetailView
tests/conftest.py CHANGED
@@ -27,8 +27,6 @@ except AttributeError:
27
27
 
28
28
  security.safe_str_cmp = hmac.compare_digest
29
29
 
30
- import shutil
31
- import tempfile
32
30
  from collections import namedtuple
33
31
 
34
32
  import pytest
@@ -41,7 +39,6 @@ from invenio_accounts.proxies import current_datastore
41
39
  from invenio_accounts.testutils import login_user_via_session
42
40
  from invenio_app.factory import create_app as _create_app
43
41
  from invenio_db import db
44
- from invenio_files_rest.models import Bucket, FileInstance, Location, ObjectVersion
45
42
  from invenio_records_resources.proxies import current_service_registry
46
43
  from invenio_vocabularies.contrib.subjects.api import Subject
47
44
  from invenio_vocabularies.proxies import current_service as vocabulary_service
@@ -273,41 +270,3 @@ RunningApp = namedtuple(
273
270
  def running_app(app, location, resource_type_item, language_item, subject_item):
274
271
  """Fixture mimicking a running app."""
275
272
  return RunningApp(app, location, resource_type_item, language_item, subject_item)
276
-
277
-
278
- @pytest.yield_fixture()
279
- def dummy_location(db):
280
- """File system location."""
281
- tmppath = tempfile.mkdtemp()
282
-
283
- loc = Location(name="testloc", uri=tmppath, default=True)
284
- db.session.add(loc)
285
- db.session.commit()
286
-
287
- yield loc
288
-
289
- shutil.rmtree(tmppath)
290
-
291
-
292
- @pytest.fixture
293
- def invalid_file_instance(db, dummy_location):
294
- """Creates a file instance."""
295
- # Create a Bucket and ObjectVersion
296
- b1 = Bucket.create(location=dummy_location)
297
- with open("README.rst", "rb") as fp:
298
- obj = ObjectVersion.create(b1, "README.rst", stream=fp)
299
- db.session.commit()
300
- file_id = obj.file_id
301
-
302
- # Get FileInstance from file ID
303
- f = FileInstance.query.get(file_id)
304
-
305
- # Force an invalid checksum
306
- f.checksum = "invalid"
307
- f.verify_checksum()
308
- db.session.commit()
309
-
310
- # Retrieve the file instance (with updated last_check)
311
- f = FileInstance.query.get(file_id)
312
-
313
- return f
@@ -2,13 +2,12 @@
2
2
  # -*- coding: utf-8 -*-
3
3
  #
4
4
  # Copyright (C) 2022 CERN.
5
+ # Copyright (C) 2025 Northwestern University.
5
6
  #
6
7
  # Invenio App RDM is free software; you can redistribute it and/or modify it
7
8
  # under the terms of the MIT License; see LICENSE file for more details.
8
9
  -#}
9
10
 
10
- {% set BASE_URL = config.SITE_UI_URL %}
11
-
12
11
  {%- for entry in entries -%}
13
12
  {{ "ID: %s" | format(entry.file.id) }}
14
13
  {{ "URI: %s" | format(entry.file.uri) }}
@@ -19,10 +18,10 @@
19
18
  {{ "Checksum: %s" | format(entry.file.checksum) }}
20
19
  {{ "Last check: %s" | format(entry.file.last_check_at) }}
21
20
  {%- if 'record' in entry %}
22
- {{ "Record: %s/records/%s" | format(BASE_URL, entry.record.id) }}
21
+ {{ "Record: %s" | format(invenio_url_for("invenio_app_rdm_records.record_detail", pid_value=entry.record.id)) }}
23
22
  {%- endif %}
24
23
  {%- if 'draft' in entry %}
25
- {{ "Draft: %s/uploads/%s" | format(BASE_URL, entry.draft.id) }}
24
+ {{ "Draft: %s" | format(invenio_url_for("invenio_app_rdm_records.deposit_edit", pid_value=entry.draft.id)) }}
26
25
  {%- endif %}
27
26
  {{ "-" * 80 }}
28
27
  {% endfor %}
tests/test_tasks.py CHANGED
@@ -1,16 +1,102 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
3
  # Copyright (C) 2022-2024 CERN.
4
+ # Copyright (C) 2025 Northwestern University.
4
5
  #
5
6
  # Invenio App RDM is free software; you can redistribute it and/or modify it
6
7
  # under the terms of the MIT License; see LICENSE file for more details.
7
8
  """Test invenio-app-rdm celery tasks."""
8
9
 
9
- from invenio_app_rdm.tasks import file_integrity_report
10
+ from io import BytesIO
11
+
12
+ import pytest
13
+ from invenio_access.permissions import system_identity
14
+ from invenio_db import db
15
+ from invenio_files_rest.models import Bucket, FileInstance, Location, ObjectVersion
16
+ from invenio_rdm_records.proxies import current_rdm_records
10
17
 
18
+ from invenio_app_rdm.tasks import file_integrity_report
11
19
 
12
- def test_task_file_integrity_report(app, invalid_file_instance):
20
+ # Fixtures
21
+
22
+
23
+ @pytest.fixture
24
+ def draft_with_file_instance(running_app, minimal_record):
25
+ """Create draft with file and return (Draft, FileInstance)."""
26
+ minimal_record["files"] = {"enabled": True}
27
+
28
+ record_service = current_rdm_records.records_service
29
+ file_service = record_service.draft_files
30
+
31
+ draft = record_service.create(system_identity, minimal_record)
32
+ file_to_initialise = [
33
+ {
34
+ "key": "article.txt",
35
+ "checksum": "md5:c785060c866796cc2a1708c997154c8e",
36
+ "size": 17, # 2kB
37
+ "metadata": {
38
+ "description": "Published article PDF.",
39
+ },
40
+ }
41
+ ]
42
+ file_service.init_files(system_identity, draft.id, file_to_initialise)
43
+ content = BytesIO(b"test file content")
44
+ file_service.set_file_content(
45
+ system_identity,
46
+ draft.id,
47
+ file_to_initialise[0]["key"],
48
+ content,
49
+ content.getbuffer().nbytes,
50
+ )
51
+ file_item = file_service.commit_file(system_identity, draft.id, "article.txt")
52
+ # fmt: off
53
+ id_of_file_instance = (
54
+ file_item
55
+ ._record
56
+ .files
57
+ .entries["article.txt"]
58
+ .object_version.file_id
59
+ )
60
+ # fmt: on
61
+ f = FileInstance.query.get(id_of_file_instance)
62
+ return draft, f
63
+
64
+
65
+ @pytest.fixture
66
+ def draft_with_invalid_file_instance(draft_with_file_instance):
67
+ # Force an invalid checksum
68
+ draft, f = draft_with_file_instance
69
+ f.checksum = "invalid"
70
+ f.verify_checksum()
71
+ db.session.commit()
72
+
73
+ # Retrieve the file instance (with updated last_check)
74
+ f = FileInstance.query.get(f.id)
75
+
76
+ return draft, f
77
+
78
+
79
+ @pytest.fixture
80
+ def record_with_invalid_file_instance(draft_with_invalid_file_instance):
81
+ draft, f = draft_with_invalid_file_instance
82
+ record_service = current_rdm_records.records_service
83
+ return record_service.publish(system_identity, draft.id), f
84
+
85
+
86
+ @pytest.fixture
87
+ def invalid_file_instance(record_with_invalid_file_instance):
88
+ draft, f = record_with_invalid_file_instance
89
+ return f
90
+
91
+
92
+ # Tests
93
+
94
+
95
+ def test_task_file_integrity_report(
96
+ app, record_with_invalid_file_instance, set_app_config_fn_scoped
97
+ ):
13
98
  """Test celery task for file integrity reports."""
99
+ record, invalid_file_instance = record_with_invalid_file_instance
14
100
  assert invalid_file_instance.last_check is False
15
101
 
16
102
  # A report must be generated for the file
@@ -20,7 +106,6 @@ def test_task_file_integrity_report(app, invalid_file_instance):
20
106
  recipients = "test@invenio.org"
21
107
  sender = "test@invenio.org"
22
108
 
23
- file_name = invalid_file_instance.objects[0].key
24
109
  uri = invalid_file_instance.uri
25
110
  file_id = invalid_file_instance.id
26
111
  file_name = invalid_file_instance.objects[0].key
@@ -28,9 +113,13 @@ def test_task_file_integrity_report(app, invalid_file_instance):
28
113
 
29
114
  with mail.record_messages() as outbox:
30
115
  # Configure email and validate that email was sent
31
- app.config["APP_RDM_FILES_INTEGRITY_REPORT_TEMPLATE"] = "mock_mail.html"
32
- app.config["APP_RDM_ADMIN_EMAIL_RECIPIENT"] = recipients
33
- app.config["MAIL_DEFAULT_SENDER"] = sender
116
+ set_app_config_fn_scoped(
117
+ {
118
+ "APP_RDM_FILES_INTEGRITY_REPORT_TEMPLATE": "mock_mail.html",
119
+ "APP_RDM_ADMIN_EMAIL_RECIPIENT": recipients,
120
+ "MAIL_DEFAULT_SENDER": sender,
121
+ }
122
+ )
34
123
 
35
124
  file_integrity_report()
36
125
  assert len(outbox) == 1
@@ -41,9 +130,12 @@ def test_task_file_integrity_report(app, invalid_file_instance):
41
130
  assert "URI: {}".format(uri) in mail_sent.body
42
131
  assert "ID: {}".format(str(file_id)) in mail_sent.body
43
132
  assert "Name: {}".format(file_name) in mail_sent.body
133
+ assert f"Record: https://127.0.0.1:5000/records/{record.id}" in mail_sent.body
44
134
 
45
135
 
46
- def test_integrity_report_invalid_template(app, invalid_file_instance):
136
+ def test_integrity_report_invalid_template(
137
+ app, invalid_file_instance, set_app_config_fn_scoped
138
+ ):
47
139
  """Test non-existant e-mail template."""
48
140
  assert invalid_file_instance.last_check is False
49
141
 
@@ -52,12 +144,15 @@ def test_integrity_report_invalid_template(app, invalid_file_instance):
52
144
 
53
145
  with mail.record_messages() as outbox:
54
146
  # Remove the template, no e-mail is sent
55
- app.config["APP_RDM_FILES_INTEGRITY_REPORT_TEMPLATE"] = None
147
+ set_app_config_fn_scoped({"APP_RDM_FILES_INTEGRITY_REPORT_TEMPLATE": None})
148
+
56
149
  file_integrity_report()
57
150
  assert len(outbox) == 0
58
151
 
59
152
 
60
- def test_integrity_report_invalid_addresses(app, invalid_file_instance):
153
+ def test_integrity_report_invalid_addresses(
154
+ app, invalid_file_instance, set_app_config_fn_scoped
155
+ ):
61
156
  """Test invalid recipient address."""
62
157
  assert invalid_file_instance.last_check is False
63
158
 
@@ -65,17 +160,24 @@ def test_integrity_report_invalid_addresses(app, invalid_file_instance):
65
160
  assert mail
66
161
 
67
162
  with mail.record_messages() as outbox:
68
- # Use mock template
69
- app.config["APP_RDM_FILES_INTEGRITY_REPORT_TEMPLATE"] = "mock_mail.html"
163
+ set_app_config_fn_scoped(
164
+ {
165
+ # Use mock template
166
+ "APP_RDM_FILES_INTEGRITY_REPORT_TEMPLATE": "mock_mail.html",
167
+ # Recipient is not set, mail is not sent.
168
+ "APP_RDM_ADMIN_EMAIL_RECIPIENT": None,
169
+ }
170
+ )
70
171
 
71
- # Recipient is not set, mail is not sent.
72
- app.config["APP_RDM_ADMIN_EMAIL_RECIPIENT"] = None
73
172
  file_integrity_report()
74
173
  assert len(outbox) == 0
75
174
 
76
175
 
77
- def test_integrity_report_default_template(app, invalid_file_instance):
176
+ def test_integrity_report_default_template(
177
+ app, draft_with_invalid_file_instance, set_app_config_fn_scoped
178
+ ):
78
179
  """Test invalid recipient address."""
180
+ draft, invalid_file_instance = draft_with_invalid_file_instance
79
181
  assert invalid_file_instance.last_check is False
80
182
 
81
183
  mail = app.extensions.get("mail")
@@ -91,8 +193,10 @@ def test_integrity_report_default_template(app, invalid_file_instance):
91
193
 
92
194
  with mail.record_messages() as outbox:
93
195
  # Use default template
94
- app.config["APP_RDM_ADMIN_EMAIL_RECIPIENT"] = recipients
95
- app.config["MAIL_DEFAULT_SENDER"] = sender
196
+ set_app_config_fn_scoped(
197
+ {"APP_RDM_ADMIN_EMAIL_RECIPIENT": recipients, "MAIL_DEFAULT_SENDER": sender}
198
+ )
199
+
96
200
  file_integrity_report()
97
201
  assert len(outbox) == 1
98
202
  mail_sent = outbox[0]
@@ -102,3 +206,4 @@ def test_integrity_report_default_template(app, invalid_file_instance):
102
206
  assert "URI: {}".format(uri) in mail_sent.body
103
207
  assert "ID: {}".format(str(file_id)) in mail_sent.body
104
208
  assert "Name: {}".format(file_name) in mail_sent.body
209
+ assert f"Draft: https://127.0.0.1:5000/uploads/{draft.id}" in mail_sent.body
tests/ui/conftest.py CHANGED
@@ -12,12 +12,13 @@
12
12
  from io import BytesIO
13
13
 
14
14
  import pytest
15
+ from flask_principal import Identity
15
16
  from flask_webpackext.manifest import (
16
17
  JinjaManifest,
17
18
  JinjaManifestEntry,
18
19
  JinjaManifestLoader,
19
20
  )
20
- from invenio_access.permissions import system_identity
21
+ from invenio_access.permissions import any_user, authenticated_user, system_identity
21
22
  from invenio_app.factory import create_ui
22
23
  from invenio_rdm_records.proxies import current_rdm_records
23
24
  from invenio_search import current_search
@@ -74,14 +75,18 @@ def record(running_app, minimal_record):
74
75
 
75
76
 
76
77
  @pytest.fixture()
77
- def record_with_file(running_app, minimal_record):
78
- """Create and publish a record with file."""
78
+ def draft_with_file(running_app, minimal_record, users):
79
+ """Create a draft with a file."""
79
80
  minimal_record["files"] = {"enabled": True}
80
81
 
82
+ # Use a user's identity to make sure the record has an owner
83
+ user_identity = Identity(users["user1"].id)
84
+ user_identity.provides.add(any_user)
85
+ user_identity.provides.add(authenticated_user)
81
86
  record_service = current_rdm_records.records_service
82
87
  file_service = record_service.draft_files
83
88
 
84
- draft = record_service.create(system_identity, minimal_record)
89
+ draft = record_service.create(user_identity, minimal_record)
85
90
  file_to_initialise = [
86
91
  {
87
92
  "key": "article.txt",
@@ -102,4 +107,11 @@ def record_with_file(running_app, minimal_record):
102
107
  content.getbuffer().nbytes,
103
108
  )
104
109
  file_service.commit_file(system_identity, draft.id, "article.txt")
105
- return record_service.publish(system_identity, draft.id)
110
+ return draft
111
+
112
+
113
+ @pytest.fixture()
114
+ def record_with_file(draft_with_file):
115
+ """Create and publish a record with file."""
116
+ record_service = current_rdm_records.records_service
117
+ return record_service.publish(system_identity, draft_with_file.id)
@@ -0,0 +1,73 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2025 CERN.
4
+ # Copyright (C) 2025 KTH Royal Institute of Technology.
5
+ #
6
+ # Invenio-App-RDM is free software; you can redistribute it and/or modify
7
+ # it under the terms of the MIT License; see LICENSE file for more details.
8
+
9
+ from flask import url_for
10
+
11
+
12
+ def test_file_download_with_and_without_preview_flag(
13
+ client_with_login, draft_with_file
14
+ ):
15
+ """Test file download both with and without preview flag."""
16
+ client = client_with_login
17
+ draft_id = draft_with_file["id"]
18
+ file_name = "article.txt"
19
+
20
+ # The draft's owner should be able to download its file from the preview page
21
+ url_with_preview = url_for(
22
+ "invenio_app_rdm_records.record_file_download",
23
+ pid_value=draft_id,
24
+ filename=file_name,
25
+ download=1,
26
+ preview=1,
27
+ )
28
+ response = client.get(url_with_preview)
29
+ assert (
30
+ response.status_code == 200
31
+ ), "File download with preview flag should return 200"
32
+
33
+ # But since the draft isn't published yet, it can't be found without preview=1
34
+ url_without_preview = url_for(
35
+ "invenio_app_rdm_records.record_file_download",
36
+ pid_value=draft_id,
37
+ filename=file_name,
38
+ download=1,
39
+ )
40
+ response = client.get(url_without_preview)
41
+ assert (
42
+ response.status_code == 404
43
+ ), "File download without preview flag should return 404"
44
+
45
+
46
+ def test_nonexistent_file_returns_404(client_with_login, draft_with_file):
47
+ """Test that requesting a non-existent file returns 404 via the NoResultFound handler."""
48
+ client = client_with_login
49
+ draft_id = draft_with_file["id"]
50
+ fake_file = "nonexistent-file.pdf"
51
+
52
+ # Downloads for files that don't exist should return a 404, both without...
53
+ url_without_preview = url_for(
54
+ "invenio_app_rdm_records.record_file_download",
55
+ pid_value=draft_id,
56
+ filename=fake_file,
57
+ download=1,
58
+ )
59
+ response = client.get(url_without_preview)
60
+ assert response.status_code == 404, "Non-existent file should return 404"
61
+
62
+ # ... as well as with the preview=1 flag
63
+ url_with_preview = url_for(
64
+ "invenio_app_rdm_records.record_file_download",
65
+ pid_value=draft_id,
66
+ filename=fake_file,
67
+ download=1,
68
+ preview=1,
69
+ )
70
+ response = client.get(url_with_preview)
71
+ assert (
72
+ response.status_code == 404
73
+ ), "Non-existent file with preview flag should return 404"
invenio_app_rdm/urls.py DELETED
@@ -1,72 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2023 Northwestern University.
4
- #
5
- # This file is lifted from Invenio-RDM-Records .
6
- #
7
- # Invenio-RDM-Records is free software; you can redistribute it and/or modify
8
- # it under the terms of the MIT License; see LICENSE file for more details.
9
-
10
- """Convenient URL generation.
11
-
12
- InvenioRDM poses challenges to url generation that Flask's url_for cannot handle out
13
- of the gate.
14
-
15
- - InvenioRDM is actually 2 applications mounted on different url_prefixes:
16
- `url_for` in the API application isn't aware of the UI application endpoints
17
- - The endpoint names are relatively hidden / spread out and APP_RDM_ROUTES is usually
18
- the interface to name them.
19
- - Need to be able to generate urls outside of request context without thinking about it,
20
-
21
- This module contains minimal methods to generate URLs correctly without much
22
- engineering. Over time, it can be made more abstract, complex and powerful and even
23
- extracted into its own package to solve url generation across InvenioRDM once and for
24
- all.
25
-
26
- Design decisions:
27
-
28
- - Generated urls are absolute for now
29
- """
30
-
31
- import unicodedata
32
- from urllib.parse import quote
33
-
34
- from flask import current_app
35
-
36
-
37
- def record_url_for(_app="ui", pid_value=""):
38
- """Return url for record route."""
39
- assert _app in ["ui", "api"]
40
-
41
- site_app = _app.upper()
42
- url_prefix = current_app.config.get(f"SITE_{site_app}_URL", "")
43
-
44
- # We use [] so that this fails and brings to attention the configuration
45
- # problem if APP_RDM_ROUTES.record_detail is missing
46
- url_path = current_app.config["APP_RDM_ROUTES"]["record_detail"].replace(
47
- "<pid_value>", pid_value
48
- )
49
-
50
- return "/".join(p.strip("/") for p in [url_prefix, url_path])
51
-
52
-
53
- def download_url_for(pid_value="", filename=""):
54
- """Return url for download route."""
55
- url_prefix = current_app.config.get("SITE_UI_URL", "")
56
-
57
- # see https://github.com/pallets/werkzeug/blob/main/src/werkzeug/utils.py#L456-L465
58
- try:
59
- filename.encode("ascii")
60
- except UnicodeEncodeError:
61
- # safe = RFC 5987 attr-char
62
- filename = quote(filename, safe="!#$&+-.^_`|~")
63
-
64
- # We use [] so that this fails and brings to attention the configuration
65
- # problem if APP_RDM_ROUTES.record_file_download is missing
66
- url_path = (
67
- current_app.config["APP_RDM_ROUTES"]["record_file_download"]
68
- .replace("<pid_value>", pid_value)
69
- .replace("<path:filename>", filename)
70
- )
71
-
72
- return "/".join(p.strip("/") for p in [url_prefix, url_path])