rucio 35.7.0__py3-none-any.whl → 37.0.0__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.

Potentially problematic release.


This version of rucio might be problematic. Click here for more details.

Files changed (266) hide show
  1. rucio/alembicrevision.py +1 -1
  2. rucio/{daemons/c3po/collectors → cli}/__init__.py +1 -0
  3. rucio/cli/account.py +216 -0
  4. rucio-35.7.0.data/scripts/rucio → rucio/cli/bin_legacy/rucio.py +769 -486
  5. rucio-35.7.0.data/scripts/rucio-admin → rucio/cli/bin_legacy/rucio_admin.py +476 -423
  6. rucio/cli/command.py +272 -0
  7. rucio/cli/config.py +72 -0
  8. rucio/cli/did.py +191 -0
  9. rucio/cli/download.py +128 -0
  10. rucio/cli/lifetime_exception.py +33 -0
  11. rucio/cli/replica.py +162 -0
  12. rucio/cli/rse.py +293 -0
  13. rucio/cli/rule.py +158 -0
  14. rucio/cli/scope.py +40 -0
  15. rucio/cli/subscription.py +73 -0
  16. rucio/cli/upload.py +60 -0
  17. rucio/cli/utils.py +226 -0
  18. rucio/client/accountclient.py +0 -1
  19. rucio/client/baseclient.py +33 -24
  20. rucio/client/client.py +45 -1
  21. rucio/client/didclient.py +5 -3
  22. rucio/client/downloadclient.py +6 -8
  23. rucio/client/replicaclient.py +0 -2
  24. rucio/client/richclient.py +317 -0
  25. rucio/client/rseclient.py +4 -4
  26. rucio/client/uploadclient.py +26 -12
  27. rucio/common/bittorrent.py +234 -0
  28. rucio/common/cache.py +66 -29
  29. rucio/common/checksum.py +168 -0
  30. rucio/common/client.py +122 -0
  31. rucio/common/config.py +22 -35
  32. rucio/common/constants.py +61 -3
  33. rucio/common/didtype.py +72 -24
  34. rucio/common/dumper/__init__.py +45 -38
  35. rucio/common/dumper/consistency.py +75 -30
  36. rucio/common/dumper/data_models.py +63 -19
  37. rucio/common/dumper/path_parsing.py +19 -8
  38. rucio/common/exception.py +65 -8
  39. rucio/common/extra.py +5 -10
  40. rucio/common/logging.py +13 -13
  41. rucio/common/pcache.py +8 -7
  42. rucio/common/plugins.py +59 -27
  43. rucio/common/policy.py +12 -3
  44. rucio/common/schema/__init__.py +84 -34
  45. rucio/common/schema/generic.py +0 -17
  46. rucio/common/schema/generic_multi_vo.py +0 -17
  47. rucio/common/test_rucio_server.py +12 -6
  48. rucio/common/types.py +132 -52
  49. rucio/common/utils.py +93 -643
  50. rucio/core/account_limit.py +14 -12
  51. rucio/core/authentication.py +2 -2
  52. rucio/core/config.py +23 -42
  53. rucio/core/credential.py +14 -15
  54. rucio/core/did.py +5 -1
  55. rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
  56. rucio/core/did_meta_plugins/filter_engine.py +62 -3
  57. rucio/core/did_meta_plugins/json_meta.py +2 -2
  58. rucio/core/did_meta_plugins/mongo_meta.py +43 -30
  59. rucio/core/did_meta_plugins/postgres_meta.py +75 -39
  60. rucio/core/identity.py +6 -5
  61. rucio/core/importer.py +4 -3
  62. rucio/core/lifetime_exception.py +2 -2
  63. rucio/core/lock.py +8 -7
  64. rucio/core/message.py +6 -0
  65. rucio/core/monitor.py +30 -29
  66. rucio/core/naming_convention.py +2 -2
  67. rucio/core/nongrid_trace.py +2 -2
  68. rucio/core/oidc.py +11 -9
  69. rucio/core/permission/__init__.py +79 -37
  70. rucio/core/permission/generic.py +1 -7
  71. rucio/core/permission/generic_multi_vo.py +1 -7
  72. rucio/core/quarantined_replica.py +4 -3
  73. rucio/core/replica.py +464 -139
  74. rucio/core/replica_sorter.py +55 -59
  75. rucio/core/request.py +34 -32
  76. rucio/core/rse.py +301 -97
  77. rucio/core/rse_counter.py +1 -2
  78. rucio/core/rse_expression_parser.py +7 -7
  79. rucio/core/rse_selector.py +9 -7
  80. rucio/core/rule.py +41 -40
  81. rucio/core/rule_grouping.py +42 -40
  82. rucio/core/scope.py +5 -4
  83. rucio/core/subscription.py +26 -28
  84. rucio/core/topology.py +11 -11
  85. rucio/core/trace.py +2 -2
  86. rucio/core/transfer.py +29 -15
  87. rucio/core/volatile_replica.py +4 -3
  88. rucio/daemons/atropos/atropos.py +1 -1
  89. rucio/daemons/auditor/__init__.py +2 -2
  90. rucio/daemons/auditor/srmdumps.py +6 -6
  91. rucio/daemons/automatix/automatix.py +32 -21
  92. rucio/daemons/badreplicas/necromancer.py +2 -2
  93. rucio/daemons/bb8/nuclei_background_rebalance.py +1 -1
  94. rucio/daemons/bb8/t2_background_rebalance.py +1 -1
  95. rucio/daemons/common.py +15 -25
  96. rucio/daemons/conveyor/finisher.py +2 -2
  97. rucio/daemons/conveyor/poller.py +18 -28
  98. rucio/daemons/conveyor/receiver.py +2 -2
  99. rucio/daemons/conveyor/stager.py +1 -0
  100. rucio/daemons/conveyor/submitter.py +3 -3
  101. rucio/daemons/hermes/hermes.py +91 -30
  102. rucio/daemons/judge/evaluator.py +2 -2
  103. rucio/daemons/oauthmanager/oauthmanager.py +3 -3
  104. rucio/daemons/reaper/dark_reaper.py +7 -3
  105. rucio/daemons/reaper/reaper.py +12 -16
  106. rucio/daemons/rsedecommissioner/config.py +1 -1
  107. rucio/daemons/rsedecommissioner/profiles/generic.py +5 -4
  108. rucio/daemons/rsedecommissioner/profiles/types.py +7 -6
  109. rucio/daemons/rsedecommissioner/rse_decommissioner.py +1 -1
  110. rucio/daemons/storage/consistency/actions.py +8 -6
  111. rucio/daemons/tracer/kronos.py +4 -4
  112. rucio/db/sqla/constants.py +5 -0
  113. rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +4 -4
  114. rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
  115. rucio/db/sqla/models.py +157 -154
  116. rucio/db/sqla/session.py +58 -27
  117. rucio/db/sqla/types.py +2 -2
  118. rucio/db/sqla/util.py +2 -2
  119. rucio/gateway/account.py +18 -12
  120. rucio/gateway/account_limit.py +137 -60
  121. rucio/gateway/authentication.py +18 -12
  122. rucio/gateway/config.py +30 -20
  123. rucio/gateway/credential.py +9 -10
  124. rucio/gateway/did.py +70 -53
  125. rucio/gateway/dirac.py +6 -4
  126. rucio/gateway/exporter.py +3 -2
  127. rucio/gateway/heartbeat.py +6 -4
  128. rucio/gateway/identity.py +36 -51
  129. rucio/gateway/importer.py +3 -2
  130. rucio/gateway/lifetime_exception.py +3 -2
  131. rucio/gateway/meta_conventions.py +17 -6
  132. rucio/gateway/permission.py +4 -1
  133. rucio/gateway/quarantined_replica.py +3 -2
  134. rucio/gateway/replica.py +31 -22
  135. rucio/gateway/request.py +27 -18
  136. rucio/gateway/rse.py +69 -37
  137. rucio/gateway/rule.py +46 -26
  138. rucio/gateway/scope.py +3 -2
  139. rucio/gateway/subscription.py +14 -11
  140. rucio/gateway/vo.py +12 -8
  141. rucio/rse/__init__.py +3 -3
  142. rucio/rse/protocols/bittorrent.py +11 -1
  143. rucio/rse/protocols/cache.py +0 -11
  144. rucio/rse/protocols/dummy.py +0 -11
  145. rucio/rse/protocols/gfal.py +14 -9
  146. rucio/rse/protocols/globus.py +1 -1
  147. rucio/rse/protocols/http_cache.py +1 -1
  148. rucio/rse/protocols/posix.py +2 -2
  149. rucio/rse/protocols/protocol.py +84 -317
  150. rucio/rse/protocols/rclone.py +2 -1
  151. rucio/rse/protocols/rfio.py +10 -1
  152. rucio/rse/protocols/ssh.py +2 -1
  153. rucio/rse/protocols/storm.py +2 -13
  154. rucio/rse/protocols/webdav.py +74 -30
  155. rucio/rse/protocols/xrootd.py +2 -1
  156. rucio/rse/rsemanager.py +170 -53
  157. rucio/rse/translation.py +260 -0
  158. rucio/tests/common.py +23 -13
  159. rucio/tests/common_server.py +26 -9
  160. rucio/transfertool/bittorrent.py +15 -14
  161. rucio/transfertool/bittorrent_driver.py +5 -7
  162. rucio/transfertool/bittorrent_driver_qbittorrent.py +9 -8
  163. rucio/transfertool/fts3.py +20 -16
  164. rucio/transfertool/mock.py +2 -3
  165. rucio/vcsversion.py +4 -4
  166. rucio/version.py +7 -0
  167. rucio/web/rest/flaskapi/v1/accounts.py +17 -3
  168. rucio/web/rest/flaskapi/v1/auth.py +5 -5
  169. rucio/web/rest/flaskapi/v1/credentials.py +3 -2
  170. rucio/web/rest/flaskapi/v1/dids.py +21 -15
  171. rucio/web/rest/flaskapi/v1/identities.py +33 -9
  172. rucio/web/rest/flaskapi/v1/redirect.py +5 -4
  173. rucio/web/rest/flaskapi/v1/replicas.py +12 -8
  174. rucio/web/rest/flaskapi/v1/rses.py +15 -4
  175. rucio/web/rest/flaskapi/v1/traces.py +56 -19
  176. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic.ini.template +1 -1
  177. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic_offline.ini.template +1 -1
  178. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +3 -2
  179. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.template +3 -19
  180. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +1 -18
  181. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/requirements.server.txt +97 -68
  182. rucio-37.0.0.data/scripts/rucio +133 -0
  183. rucio-37.0.0.data/scripts/rucio-admin +97 -0
  184. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-atropos +2 -2
  185. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-auditor +2 -1
  186. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-automatix +2 -2
  187. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-client +17 -10
  188. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-receiver +1 -0
  189. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-kronos +1 -0
  190. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos +2 -2
  191. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos-temporary-expiration +2 -2
  192. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-necromancer +2 -2
  193. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-reaper +6 -6
  194. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-transmogrifier +2 -2
  195. rucio-37.0.0.dist-info/METADATA +92 -0
  196. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/RECORD +237 -243
  197. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/licenses/AUTHORS.rst +3 -0
  198. rucio/common/schema/atlas.py +0 -413
  199. rucio/common/schema/belleii.py +0 -408
  200. rucio/common/schema/domatpc.py +0 -401
  201. rucio/common/schema/escape.py +0 -426
  202. rucio/common/schema/icecube.py +0 -406
  203. rucio/core/permission/atlas.py +0 -1348
  204. rucio/core/permission/belleii.py +0 -1077
  205. rucio/core/permission/escape.py +0 -1078
  206. rucio/daemons/c3po/algorithms/__init__.py +0 -13
  207. rucio/daemons/c3po/algorithms/simple.py +0 -134
  208. rucio/daemons/c3po/algorithms/t2_free_space.py +0 -128
  209. rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +0 -130
  210. rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +0 -294
  211. rucio/daemons/c3po/c3po.py +0 -371
  212. rucio/daemons/c3po/collectors/agis.py +0 -108
  213. rucio/daemons/c3po/collectors/free_space.py +0 -81
  214. rucio/daemons/c3po/collectors/jedi_did.py +0 -57
  215. rucio/daemons/c3po/collectors/mock_did.py +0 -51
  216. rucio/daemons/c3po/collectors/network_metrics.py +0 -71
  217. rucio/daemons/c3po/collectors/workload.py +0 -112
  218. rucio/daemons/c3po/utils/__init__.py +0 -13
  219. rucio/daemons/c3po/utils/dataset_cache.py +0 -50
  220. rucio/daemons/c3po/utils/expiring_dataset_cache.py +0 -56
  221. rucio/daemons/c3po/utils/expiring_list.py +0 -62
  222. rucio/daemons/c3po/utils/popularity.py +0 -85
  223. rucio/daemons/c3po/utils/timeseries.py +0 -89
  224. rucio/rse/protocols/gsiftp.py +0 -92
  225. rucio-35.7.0.data/scripts/rucio-c3po +0 -85
  226. rucio-35.7.0.dist-info/METADATA +0 -72
  227. /rucio/{daemons/c3po → cli/bin_legacy}/__init__.py +0 -0
  228. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
  229. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
  230. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
  231. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
  232. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
  233. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
  234. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
  235. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
  236. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
  237. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/bootstrap.py +0 -0
  238. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
  239. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/reset_database.py +0 -0
  240. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-account +0 -0
  241. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-collection-replica +0 -0
  242. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-rse +0 -0
  243. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-bb8 +0 -0
  244. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-consumer +0 -0
  245. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-finisher +0 -0
  246. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-poller +0 -0
  247. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-preparer +0 -0
  248. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-stager +0 -0
  249. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-submitter +0 -0
  250. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-throttler +0 -0
  251. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dark-reaper +0 -0
  252. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dumper +0 -0
  253. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-follower +0 -0
  254. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-hermes +0 -0
  255. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-cleaner +0 -0
  256. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-evaluator +0 -0
  257. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-injector +0 -0
  258. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-repairer +0 -0
  259. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-oauth-manager +0 -0
  260. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-replica-recoverer +0 -0
  261. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-rse-decommissioner +0 -0
  262. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-storage-consistency-actions +0 -0
  263. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-undertaker +0 -0
  264. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/WHEEL +0 -0
  265. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/licenses/LICENSE +0 -0
  266. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/top_level.txt +0 -0
@@ -170,8 +170,9 @@ def get_auth_token_user_pass(
170
170
  """
171
171
 
172
172
  kwargs = {'account': account, 'username': username, 'password': password}
173
- if not permission.has_permission(issuer=account, vo=vo, action='get_auth_token_user_pass', kwargs=kwargs, session=session):
174
- raise exception.AccessDenied('User with identity %s can not log to account %s' % (username, account))
173
+ auth_result = permission.has_permission(issuer=account, vo=vo, action='get_auth_token_user_pass', kwargs=kwargs, session=session)
174
+ if not auth_result.allowed:
175
+ raise exception.AccessDenied('User with identity %s can not log to account %s. %s' % (username, account, auth_result.message))
175
176
 
176
177
  internal_account = InternalAccount(account, vo=vo)
177
178
 
@@ -204,8 +205,9 @@ def get_auth_token_gss(
204
205
  """
205
206
 
206
207
  kwargs = {'account': account, 'gsscred': gsscred}
207
- if not permission.has_permission(issuer=account, vo=vo, action='get_auth_token_gss', kwargs=kwargs, session=session):
208
- raise exception.AccessDenied('User with identity %s can not log to account %s' % (gsscred, account))
208
+ auth_result = permission.has_permission(issuer=account, vo=vo, action='get_auth_token_gss', kwargs=kwargs, session=session)
209
+ if not auth_result.allowed:
210
+ raise exception.AccessDenied('User with identity %s can not log to account %s. %s' % (gsscred, account, auth_result.message))
209
211
 
210
212
  internal_account = InternalAccount(account, vo=vo)
211
213
 
@@ -241,8 +243,9 @@ def get_auth_token_x509(
241
243
  account = identity.get_default_account(dn, IdentityType.X509).external
242
244
 
243
245
  kwargs = {'account': account, 'dn': dn}
244
- if not permission.has_permission(issuer=account, vo=vo, action='get_auth_token_x509', kwargs=kwargs, session=session):
245
- raise exception.AccessDenied('User with identity %s can not log to account %s' % (dn, account))
246
+ auth_result = permission.has_permission(issuer=account, vo=vo, action='get_auth_token_x509', kwargs=kwargs, session=session)
247
+ if not auth_result.allowed:
248
+ raise exception.AccessDenied('User with identity %s can not log to account %s. %s' % (dn, account, auth_result.message))
246
249
 
247
250
  internal_account = InternalAccount(account, vo=vo)
248
251
 
@@ -275,8 +278,9 @@ def get_auth_token_ssh(
275
278
  """
276
279
 
277
280
  kwargs = {'account': account, 'signature': signature}
278
- if not permission.has_permission(issuer=account, vo=vo, action='get_auth_token_ssh', kwargs=kwargs, session=session):
279
- raise exception.AccessDenied('User with provided signature can not log to account %s' % account)
281
+ auth_result = permission.has_permission(issuer=account, vo=vo, action='get_auth_token_ssh', kwargs=kwargs, session=session)
282
+ if not auth_result.allowed:
283
+ raise exception.AccessDenied('User with provided signature can not log to account %s. %s' % (account, auth_result.message))
280
284
 
281
285
  internal_account = InternalAccount(account, vo=vo)
282
286
 
@@ -307,8 +311,9 @@ def get_ssh_challenge_token(
307
311
  """
308
312
 
309
313
  kwargs = {'account': account}
310
- if not permission.has_permission(issuer=account, vo=vo, action='get_auth_token_ssh', kwargs=kwargs, session=session):
311
- raise exception.AccessDenied('User can not get challenge token for account %s' % account)
314
+ auth_result = permission.has_permission(issuer=account, vo=vo, action='get_auth_token_ssh', kwargs=kwargs, session=session)
315
+ if not auth_result.allowed:
316
+ raise exception.AccessDenied('User can not get challenge token for account %s. %s' % (account, auth_result.message))
312
317
 
313
318
  internal_account = InternalAccount(account, vo=vo)
314
319
 
@@ -340,8 +345,9 @@ def get_auth_token_saml(
340
345
  """
341
346
 
342
347
  kwargs = {'account': account, 'saml_nameid': saml_nameid}
343
- if not permission.has_permission(issuer=account, vo=vo, action='get_auth_token_saml', kwargs=kwargs, session=session):
344
- raise exception.AccessDenied('User with identity %s can not log to account %s' % (saml_nameid, account))
348
+ auth_result = permission.has_permission(issuer=account, vo=vo, action='get_auth_token_saml', kwargs=kwargs, session=session)
349
+ if not auth_result.allowed:
350
+ raise exception.AccessDenied('User with identity %s can not log to account %s. %s' % (saml_nameid, account, auth_result.message))
345
351
 
346
352
  internal_account = InternalAccount(account, vo=vo)
347
353
 
rucio/gateway/config.py CHANGED
@@ -43,8 +43,9 @@ def sections(issuer: Optional[str] = None, vo: str = 'def', *, session: "Session
43
43
  """
44
44
 
45
45
  kwargs = {'issuer': issuer}
46
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_sections', kwargs=kwargs, session=session):
47
- raise exception.AccessDenied('%s cannot retrieve sections' % issuer)
46
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_sections', kwargs=kwargs, session=session)
47
+ if not auth_result.allowed:
48
+ raise exception.AccessDenied('%s cannot retrieve sections. %s' % (issuer, auth_result.message))
48
49
  return config.sections(session=session)
49
50
 
50
51
 
@@ -60,8 +61,9 @@ def add_section(section: str, issuer: Optional[str] = None, vo: str = 'def', *,
60
61
  """
61
62
 
62
63
  kwargs = {'issuer': issuer, 'section': section}
63
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_add_section', kwargs=kwargs, session=session):
64
- raise exception.AccessDenied('%s cannot add section %s' % (issuer, section))
64
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_add_section', kwargs=kwargs, session=session)
65
+ if not auth_result.allowed:
66
+ raise exception.AccessDenied('%s cannot add section %s. %s' % (issuer, section, auth_result.message))
65
67
  return config.add_section(section, session=session)
66
68
 
67
69
 
@@ -78,8 +80,9 @@ def has_section(section: str, issuer: Optional[str] = None, vo: str = 'def', *,
78
80
  """
79
81
 
80
82
  kwargs = {'issuer': issuer, 'section': section}
81
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_has_section', kwargs=kwargs, session=session):
82
- raise exception.AccessDenied('%s cannot check existence of section %s' % (issuer, section))
83
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_has_section', kwargs=kwargs, session=session)
84
+ if not auth_result.allowed:
85
+ raise exception.AccessDenied('%s cannot check existence of section %s. %s' % (issuer, section, auth_result.message))
83
86
  return config.has_section(section, session=session)
84
87
 
85
88
 
@@ -96,8 +99,9 @@ def options(section: str, issuer: Optional[str] = None, vo: str = 'def', *, sess
96
99
  """
97
100
 
98
101
  kwargs = {'issuer': issuer, 'section': section}
99
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_options', kwargs=kwargs, session=session):
100
- raise exception.AccessDenied('%s cannot retrieve options from section %s' % (issuer, section))
102
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_options', kwargs=kwargs, session=session)
103
+ if auth_result.allowed:
104
+ raise exception.AccessDenied('%s cannot retrieve options from section %s. %s' % (issuer, section, auth_result.message))
101
105
  return config.options(section, session=session)
102
106
 
103
107
 
@@ -115,8 +119,9 @@ def has_option(section: str, option: str, issuer: Optional[str] = None, vo: str
115
119
  """
116
120
 
117
121
  kwargs = {'issuer': issuer, 'section': section, 'option': option}
118
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_has_option', kwargs=kwargs, session=session):
119
- raise exception.AccessDenied('%s cannot check existence of option %s from section %s' % (issuer, option, section))
122
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_has_option', kwargs=kwargs, session=session)
123
+ if not auth_result.allowed:
124
+ raise exception.AccessDenied('%s cannot check existence of option %s from section %s. %s' % (issuer, option, section, auth_result.message))
120
125
  return config.has_option(section, option, session=session)
121
126
 
122
127
 
@@ -137,8 +142,9 @@ def get(section: str, option: str, issuer: Optional[str] = None, vo: str = 'def'
137
142
  """
138
143
 
139
144
  kwargs = {'issuer': issuer, 'section': section, 'option': option}
140
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_get', kwargs=kwargs, session=session):
141
- raise exception.AccessDenied('%s cannot retrieve option %s from section %s' % (issuer, option, section))
145
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_get', kwargs=kwargs, session=session)
146
+ if not auth_result.allowed:
147
+ raise exception.AccessDenied('%s cannot retrieve option %s from section %s. %s' % (issuer, option, section, auth_result.message))
142
148
  return config.get(section, option, session=session, convert_type_fnc=convert_to_any_type)
143
149
 
144
150
 
@@ -156,8 +162,9 @@ def items(section: str, issuer: Optional[str] = None, vo: str = 'def', *, sessio
156
162
  """
157
163
 
158
164
  kwargs = {'issuer': issuer, 'section': section}
159
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_items', kwargs=kwargs, session=session):
160
- raise exception.AccessDenied('%s cannot retrieve options and values from section %s' % (issuer, section))
165
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_items', kwargs=kwargs, session=session)
166
+ if not auth_result.allowed:
167
+ raise exception.AccessDenied('%s cannot retrieve options and values from section %s. %s' % (issuer, section, auth_result.message))
161
168
  return config.items(section, session=session, convert_type_fnc=convert_to_any_type)
162
169
 
163
170
 
@@ -175,8 +182,9 @@ def set(section: str, option: str, value: Any, issuer: Optional[str] = None, vo:
175
182
  """
176
183
 
177
184
  kwargs = {'issuer': issuer, 'section': section, 'option': option, 'value': value}
178
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_set', kwargs=kwargs, session=session):
179
- raise exception.AccessDenied('%s cannot set option %s to %s in section %s' % (issuer, option, value, section))
185
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_set', kwargs=kwargs, session=session)
186
+ if not auth_result.allowed:
187
+ raise exception.AccessDenied('%s cannot set option %s to %s in section %s. %s' % (issuer, option, value, section, auth_result.message))
180
188
  return config.set(section, option, value, session=session)
181
189
 
182
190
 
@@ -193,8 +201,9 @@ def remove_section(section: str, issuer: Optional[str] = None, vo: str = 'def',
193
201
  """
194
202
 
195
203
  kwargs = {'issuer': issuer, 'section': section}
196
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_remove_section', kwargs=kwargs, session=session):
197
- raise exception.AccessDenied('%s cannot remove section %s' % (issuer, section))
204
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_remove_section', kwargs=kwargs, session=session)
205
+ if not auth_result.allowed:
206
+ raise exception.AccessDenied('%s cannot remove section %s. %s' % (issuer, section, auth_result.message))
198
207
  return config.remove_section(section, session=session)
199
208
 
200
209
 
@@ -212,6 +221,7 @@ def remove_option(section: str, option: str, issuer: Optional[str] = None, vo: s
212
221
  """
213
222
 
214
223
  kwargs = {'issuer': issuer, 'section': section, 'option': option}
215
- if not permission.has_permission(issuer=issuer, vo=vo, action='config_remove_option', kwargs=kwargs, session=session):
216
- raise exception.AccessDenied('%s cannot remove option %s from section %s' % (issuer, option, section))
224
+ auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_remove_option', kwargs=kwargs, session=session)
225
+ if not auth_result.allowed:
226
+ raise exception.AccessDenied('%s cannot remove option %s from section %s. %s' % (issuer, option, section, auth_result.message))
217
227
  return config.remove_option(section, option, session=session)
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import TYPE_CHECKING, Literal
15
+ from typing import TYPE_CHECKING
16
16
 
17
17
  from rucio.common import exception
18
18
  from rucio.core import credential
@@ -23,6 +23,8 @@ from rucio.gateway import permission
23
23
  if TYPE_CHECKING:
24
24
  from sqlalchemy.orm import Session
25
25
 
26
+ from rucio.common.constants import RSE_BASE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL, SUPPORTED_SIGN_URL_SERVICES_LITERAL
27
+
26
28
 
27
29
  @read_session
28
30
  def get_signed_url(
@@ -30,8 +32,8 @@ def get_signed_url(
30
32
  appid: str,
31
33
  ip: str,
32
34
  rse: str,
33
- service: Literal['gsc', 's3', 'swift'],
34
- operation: Literal['read', 'write', 'delete'],
35
+ service: 'SUPPORTED_SIGN_URL_SERVICES_LITERAL',
36
+ operation: 'RSE_BASE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL',
35
37
  url: str,
36
38
  lifetime: int,
37
39
  vo: str = 'def',
@@ -57,13 +59,10 @@ def get_signed_url(
57
59
  """
58
60
 
59
61
  kwargs = {'account': account}
60
- if not permission.has_permission(issuer=account, vo=vo, action='get_signed_url', kwargs=kwargs, session=session):
61
- raise exception.AccessDenied('Account %s can not get signed URL for rse=%s, service=%s, operation=%s, url=%s, lifetime=%s' % (account,
62
- rse,
63
- service,
64
- operation,
65
- url,
66
- lifetime))
62
+ auth_result = permission.has_permission(issuer=account, vo=vo, action='get_signed_url', kwargs=kwargs, session=session)
63
+ if not auth_result.allowed:
64
+ raise exception.AccessDenied('Account %s can not get signed URL for rse=%s, service=%s, operation=%s, url=%s, lifetime=%s. %s' %
65
+ (account, rse, service, operation, url, lifetime, auth_result.message))
67
66
 
68
67
  # look up RSE ID for name
69
68
  rse_id = get_rse_id(rse, vo=vo, session=session)
rucio/gateway/did.py CHANGED
@@ -12,7 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from collections.abc import Iterable, Iterator, Mapping, Sequence
16
15
  from copy import deepcopy
17
16
  from typing import TYPE_CHECKING, Any, Optional
18
17
 
@@ -29,13 +28,15 @@ from rucio.db.sqla.constants import DIDType
29
28
  from rucio.db.sqla.session import read_session, stream_session, transactional_session
30
29
 
31
30
  if TYPE_CHECKING:
31
+ from collections.abc import Iterable, Iterator, Mapping, Sequence
32
+
32
33
  from sqlalchemy.orm import Session
33
34
 
34
35
 
35
36
  @stream_session
36
37
  def list_dids(
37
38
  scope: str,
38
- filters: Mapping[Any, Any],
39
+ filters: 'Mapping[Any, Any]',
39
40
  did_type: str = 'collection',
40
41
  ignore_case: bool = False,
41
42
  limit: Optional[int] = None,
@@ -45,7 +46,7 @@ def list_dids(
45
46
  vo: str = 'def',
46
47
  *,
47
48
  session: "Session"
48
- ) -> Iterator[dict[str, Any]]:
49
+ ) -> 'Iterator[dict[str, Any]]':
49
50
  """
50
51
  List dids in a scope.
51
52
 
@@ -85,9 +86,9 @@ def add_did(
85
86
  account: Optional[str] = None,
86
87
  statuses: Optional[dict[str, str]] = None,
87
88
  meta: Optional[dict[str, str]] = None,
88
- rules: Optional[Sequence[dict[str, Any]]] = None,
89
+ rules: Optional['Sequence[dict[str, Any]]'] = None,
89
90
  lifetime: Optional[str] = None,
90
- dids: Optional[Sequence[dict[str, Any]]] = None,
91
+ dids: Optional['Sequence[dict[str, Any]]'] = None,
91
92
  rse: Optional[str] = None,
92
93
  vo: str = 'def',
93
94
  *,
@@ -119,8 +120,9 @@ def add_did(
119
120
  validate_schema(name='dids', obj=dids, vo=vo)
120
121
  validate_schema(name='rse', obj=rse, vo=vo)
121
122
  kwargs = {'scope': scope, 'name': name, 'type': did_type, 'issuer': issuer, 'account': account, 'statuses': statuses, 'meta': meta, 'rules': rules, 'lifetime': lifetime}
122
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='add_did', kwargs=kwargs, session=session):
123
- raise AccessDenied('Account %s can not add data identifier to scope %s' % (issuer, scope))
123
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='add_did', kwargs=kwargs, session=session)
124
+ if not auth_result.allowed:
125
+ raise AccessDenied('Account %s can not add data identifier to scope %s. %s' % (issuer, scope, auth_result.message))
124
126
 
125
127
  owner_account = None if account is None else InternalAccount(account, vo=vo)
126
128
  issuer_account = InternalAccount(issuer, vo=vo)
@@ -156,7 +158,7 @@ def add_did(
156
158
 
157
159
  @transactional_session
158
160
  def add_dids(
159
- dids: Sequence[dict[str, Any]],
161
+ dids: 'Sequence[dict[str, Any]]',
160
162
  issuer: str,
161
163
  vo: str = 'def',
162
164
  *,
@@ -178,8 +180,9 @@ def add_dids(
178
180
  d['rse_id'] = rse_id
179
181
 
180
182
  kwargs = {'issuer': issuer, 'dids': dids}
181
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='add_dids', kwargs=kwargs, session=session):
182
- raise AccessDenied('Account %s can not bulk add data identifier' % (issuer))
183
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='add_dids', kwargs=kwargs, session=session)
184
+ if not auth_result.allowed:
185
+ raise AccessDenied('Account %s can not bulk add data identifier. %s' % (issuer, auth_result.message))
183
186
 
184
187
  issuer_account = InternalAccount(issuer, vo=vo)
185
188
  for d in dids:
@@ -219,8 +222,9 @@ def attach_dids(
219
222
  attachment['rse_id'] = rse_id
220
223
 
221
224
  kwargs = {'scope': scope, 'name': name, 'attachment': attachment}
222
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='attach_dids', kwargs=kwargs, session=session):
223
- raise AccessDenied('Account %s can not add data identifiers to %s:%s' % (issuer, scope, name))
225
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='attach_dids', kwargs=kwargs, session=session)
226
+ if not auth_result.allowed:
227
+ raise AccessDenied('Account %s can not add data identifiers to %s:%s. %s' % (issuer, scope, name, auth_result.message))
224
228
 
225
229
  internal_scope = InternalScope(scope, vo=vo)
226
230
  issuer_account = InternalAccount(issuer, vo=vo)
@@ -243,7 +247,7 @@ def attach_dids(
243
247
 
244
248
  @transactional_session
245
249
  def attach_dids_to_dids(
246
- attachments: Sequence[dict[str, Any]],
250
+ attachments: 'Sequence[dict[str, Any]]',
247
251
  issuer: str,
248
252
  ignore_duplicate: bool = False,
249
253
  vo: str = 'def',
@@ -268,8 +272,9 @@ def attach_dids_to_dids(
268
272
  rse_id = get_rse_id(rse=a['rse'], vo=vo, session=session)
269
273
  a['rse_id'] = rse_id
270
274
 
271
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='attach_dids_to_dids', kwargs={'attachments': attachments}, session=session):
272
- raise AccessDenied('Account %s can not add data identifiers' % (issuer))
275
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='attach_dids_to_dids', kwargs={'attachments': attachments}, session=session)
276
+ if not auth_result.allowed:
277
+ raise AccessDenied('Account %s can not add data identifiers. %s' % (issuer, auth_result.message))
273
278
 
274
279
  issuer_account = InternalAccount(issuer, vo=vo)
275
280
  for attachment in attachments:
@@ -287,7 +292,7 @@ def attach_dids_to_dids(
287
292
  def detach_dids(
288
293
  scope: str,
289
294
  name: str,
290
- dids: Sequence[dict[str, Any]],
295
+ dids: 'Sequence[dict[str, Any]]',
291
296
  issuer: str,
292
297
  vo: str = 'def',
293
298
  *,
@@ -304,8 +309,9 @@ def detach_dids(
304
309
  :param session: The database session in use.
305
310
  """
306
311
  kwargs = {'scope': scope, 'name': name, 'dids': dids, 'issuer': issuer}
307
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='detach_dids', kwargs=kwargs, session=session):
308
- raise AccessDenied('Account %s can not detach data identifiers from %s:%s' % (issuer, scope, name))
312
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='detach_dids', kwargs=kwargs, session=session)
313
+ if not auth_result.allowed:
314
+ raise AccessDenied('Account %s can not detach data identifiers from %s:%s. %s' % (issuer, scope, name, auth_result.message))
309
315
 
310
316
  internal_scope = InternalScope(scope, vo=vo)
311
317
  for d in dids:
@@ -323,7 +329,7 @@ def list_new_dids(
323
329
  vo: str = 'def',
324
330
  *,
325
331
  session: "Session"
326
- ) -> Iterator[dict[str, Any]]:
332
+ ) -> 'Iterator[dict[str, Any]]':
327
333
  """
328
334
  List recent identifiers.
329
335
 
@@ -342,7 +348,7 @@ def list_new_dids(
342
348
 
343
349
  @transactional_session
344
350
  def set_new_dids(
345
- dids: Sequence[dict[str, Any]],
351
+ dids: 'Sequence[dict[str, Any]]',
346
352
  new_flag: bool = True,
347
353
  vo: str = 'def',
348
354
  *,
@@ -370,7 +376,7 @@ def list_content(
370
376
  vo: str = 'def',
371
377
  *,
372
378
  session: "Session"
373
- ) -> Iterator[dict[str, Any]]:
379
+ ) -> 'Iterator[dict[str, Any]]':
374
380
  """
375
381
  List data identifier contents.
376
382
 
@@ -394,7 +400,7 @@ def list_content_history(
394
400
  vo='def',
395
401
  *,
396
402
  session: "Session"
397
- ) -> Iterator[dict[str, Any]]:
403
+ ) -> 'Iterator[dict[str, Any]]':
398
404
  """
399
405
  List data identifier contents history.
400
406
 
@@ -414,12 +420,12 @@ def list_content_history(
414
420
 
415
421
  @stream_session
416
422
  def bulk_list_files(
417
- dids: Iterable[dict[str, Any]],
423
+ dids: 'Iterable[dict[str, Any]]',
418
424
  long: bool = False,
419
425
  vo: str = 'def',
420
426
  *,
421
427
  session: "Session"
422
- ) -> Iterator[dict[str, Any]]:
428
+ ) -> 'Iterator[dict[str, Any]]':
423
429
  """
424
430
  List file contents of a list of data identifiers.
425
431
 
@@ -444,7 +450,7 @@ def list_files(
444
450
  vo: str = 'def',
445
451
  *,
446
452
  session: "Session"
447
- ) -> Iterator[dict[str, Any]]:
453
+ ) -> 'Iterator[dict[str, Any]]':
448
454
  """
449
455
  List data identifier file contents.
450
456
 
@@ -471,7 +477,7 @@ def scope_list(
471
477
  vo: str = 'def',
472
478
  *,
473
479
  session: "Session"
474
- ) -> Iterator[dict[str, Any]]:
480
+ ) -> 'Iterator[dict[str, Any]]':
475
481
  """
476
482
  List data identifiers in a scope.
477
483
 
@@ -544,8 +550,9 @@ def set_metadata(
544
550
  if key in RESERVED_KEYS:
545
551
  raise AccessDenied('Account %s can not change this metadata value to data identifier %s:%s' % (issuer, scope, name))
546
552
 
547
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_metadata', kwargs=kwargs, session=session):
548
- raise AccessDenied('Account %s can not add metadata to data identifier %s:%s' % (issuer, scope, name))
553
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_metadata', kwargs=kwargs, session=session)
554
+ if not auth_result.allowed:
555
+ raise AccessDenied('Account %s can not add metadata to data identifier %s:%s. %s' % (issuer, scope, name, auth_result.message))
549
556
 
550
557
  internal_scope = InternalScope(scope, vo=vo)
551
558
  return did.set_metadata(scope=internal_scope, name=name, key=key, value=value, recursive=recursive, session=session)
@@ -579,8 +586,9 @@ def set_metadata_bulk(
579
586
  if key in RESERVED_KEYS:
580
587
  raise AccessDenied('Account %s can not change the value of the metadata key %s to data identifier %s:%s' % (issuer, key, scope, name))
581
588
 
582
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_metadata_bulk', kwargs=kwargs, session=session):
583
- raise AccessDenied('Account %s can not add metadata to data identifier %s:%s' % (issuer, scope, name))
589
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_metadata_bulk', kwargs=kwargs, session=session)
590
+ if not auth_result.allowed:
591
+ raise AccessDenied('Account %s can not add metadata to data identifier %s:%s. %s' % (issuer, scope, name, auth_result.message))
584
592
 
585
593
  internal_scope = InternalScope(scope, vo=vo)
586
594
  return did.set_metadata_bulk(scope=internal_scope, name=name, meta=meta, recursive=recursive, session=session)
@@ -588,7 +596,7 @@ def set_metadata_bulk(
588
596
 
589
597
  @transactional_session
590
598
  def set_dids_metadata_bulk(
591
- dids: Iterable[dict[str, Any]],
599
+ dids: 'Iterable[dict[str, Any]]',
592
600
  issuer: str,
593
601
  recursive: bool = False,
594
602
  vo: str = 'def',
@@ -607,8 +615,9 @@ def set_dids_metadata_bulk(
607
615
 
608
616
  for entry in dids:
609
617
  kwargs = {'scope': entry['scope'], 'name': entry['name'], 'meta': entry['meta'], 'issuer': issuer}
610
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_metadata_bulk', kwargs=kwargs, session=session):
611
- raise AccessDenied('Account %s can not add metadata to data identifier %s:%s' % (issuer, entry['scope'], entry['name']))
618
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_metadata_bulk', kwargs=kwargs, session=session)
619
+ if not auth_result.allowed:
620
+ raise AccessDenied('Account %s can not add metadata to data identifier %s:%s. %s' % (issuer, entry['scope'], entry['name'], auth_result.message))
612
621
  entry['scope'] = InternalScope(entry['scope'], vo=vo)
613
622
  meta = entry['meta']
614
623
  for key in meta:
@@ -633,6 +642,7 @@ def get_metadata(
633
642
  :param scope: The scope name.
634
643
  :param name: The data identifier name.
635
644
  :param vo: The VO to act on.
645
+ :param plugin: The metadata plugin to query, 'ALL' for all available plugins
636
646
  :param session: The database session in use.
637
647
  """
638
648
 
@@ -644,16 +654,18 @@ def get_metadata(
644
654
 
645
655
  @stream_session
646
656
  def get_metadata_bulk(
647
- dids: Iterable[dict[str, Any]],
657
+ dids: 'Iterable[dict[str, Any]]',
648
658
  inherit: bool = False,
659
+ plugin: str = 'DID_COLUMN',
649
660
  vo: str = 'def',
650
661
  *,
651
662
  session: "Session"
652
- ) -> Iterator[dict[str, Any]]:
663
+ ) -> 'Iterator[dict[str, Any]]':
653
664
  """
654
665
  Get metadata for a list of dids
655
666
  :param dids: A list of dids.
656
667
  :param inherit: A boolean. If set to true, the metadata of the parent are concatenated.
668
+ :param plugin: The metadata plugin to query, 'ALL' for all available plugins
657
669
  :param vo: The VO to act on.
658
670
  :param session: The database session in use.
659
671
  """
@@ -661,7 +673,7 @@ def get_metadata_bulk(
661
673
  validate_schema(name='dids', obj=dids, vo=vo)
662
674
  for entry in dids:
663
675
  entry['scope'] = InternalScope(entry['scope'], vo=vo)
664
- meta = did.get_metadata_bulk(dids, inherit=inherit, session=session)
676
+ meta = did.get_metadata_bulk(dids, inherit=inherit, plugin=plugin, session=session)
665
677
  for met in meta:
666
678
  yield gateway_update_return_dict(met, session=session)
667
679
 
@@ -710,8 +722,9 @@ def set_status(
710
722
  :param session: The database session in use.
711
723
  """
712
724
 
713
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_status', kwargs={'scope': scope, 'name': name, 'issuer': issuer}, session=session):
714
- raise AccessDenied('Account %s can not set status on data identifier %s:%s' % (issuer, scope, name))
725
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_status', kwargs={'scope': scope, 'name': name, 'issuer': issuer}, session=session)
726
+ if not auth_result.allowed:
727
+ raise AccessDenied('Account %s can not set status on data identifier %s:%s. %s' % (issuer, scope, name, auth_result.message))
715
728
 
716
729
  internal_scope = InternalScope(scope, vo=vo)
717
730
 
@@ -724,7 +737,7 @@ def get_dataset_by_guid(
724
737
  vo: str = 'def',
725
738
  *,
726
739
  session: "Session"
727
- ) -> Iterator[dict[str, Any]]:
740
+ ) -> 'Iterator[dict[str, Any]]':
728
741
  """
729
742
  Get the parent datasets for a given GUID.
730
743
  :param guid: The GUID.
@@ -748,7 +761,7 @@ def list_parent_dids(
748
761
  vo: str = 'def',
749
762
  *,
750
763
  session: "Session"
751
- ) -> Iterator[dict[str, Any]]:
764
+ ) -> 'Iterator[dict[str, Any]]':
752
765
  """
753
766
  List parent datasets and containers of a did.
754
767
 
@@ -792,8 +805,9 @@ def create_did_sample(
792
805
  :param session: The database session in use.
793
806
  """
794
807
  kwargs = {'issuer': issuer, 'scope': output_scope}
795
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='create_did_sample', kwargs=kwargs, session=session):
796
- raise AccessDenied('Account %s can not bulk add data identifier' % (issuer))
808
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='create_did_sample', kwargs=kwargs, session=session)
809
+ if not auth_result.allowed:
810
+ raise AccessDenied('Account %s can not bulk add data identifier. %s' % (issuer, auth_result.message))
797
811
 
798
812
  input_internal_scope = InternalScope(input_scope, vo=vo)
799
813
  output_internal_scope = InternalScope(output_scope, vo=vo)
@@ -806,7 +820,7 @@ def create_did_sample(
806
820
 
807
821
  @transactional_session
808
822
  def resurrect(
809
- dids: Iterable[dict[str, Any]],
823
+ dids: 'Iterable[dict[str, Any]]',
810
824
  issuer: str,
811
825
  vo: str = 'def',
812
826
  *,
@@ -821,8 +835,9 @@ def resurrect(
821
835
  :param session: The database session in use.
822
836
  """
823
837
  kwargs = {'issuer': issuer}
824
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='resurrect', kwargs=kwargs, session=session):
825
- raise AccessDenied('Account %s can not resurrect data identifiers' % (issuer))
838
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='resurrect', kwargs=kwargs, session=session)
839
+ if not auth_result.allowed:
840
+ raise AccessDenied('Account %s can not resurrect data identifiers. %s' % (issuer, auth_result.message))
826
841
  validate_schema(name='dids', obj=dids, vo=vo)
827
842
 
828
843
  for d in dids:
@@ -838,7 +853,7 @@ def list_archive_content(
838
853
  vo: str = 'def',
839
854
  *,
840
855
  session: "Session"
841
- ) -> Iterator[dict[str, Any]]:
856
+ ) -> 'Iterator[dict[str, Any]]':
842
857
  """
843
858
  List archive contents.
844
859
 
@@ -879,7 +894,7 @@ def add_did_to_followed(
879
894
 
880
895
  @transactional_session
881
896
  def add_dids_to_followed(
882
- dids: Iterable[Mapping[str, Any]],
897
+ dids: 'Iterable[Mapping[str, Any]]',
883
898
  account: str,
884
899
  *,
885
900
  session: "Session",
@@ -903,7 +918,7 @@ def get_users_following_did(
903
918
  *,
904
919
  session: "Session",
905
920
  vo: str = 'def'
906
- ) -> Iterator[dict[str, str]]:
921
+ ) -> 'Iterator[dict[str, str]]':
907
922
  """
908
923
  Return list of users following a did
909
924
 
@@ -938,8 +953,9 @@ def remove_did_from_followed(
938
953
  :param issuer: The issuer account
939
954
  """
940
955
  kwargs = {'scope': scope, 'issuer': issuer}
941
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='remove_did_from_followed', kwargs=kwargs, session=session):
942
- raise AccessDenied('Account %s can not remove data identifiers from followed table' % (issuer))
956
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='remove_did_from_followed', kwargs=kwargs, session=session)
957
+ if not auth_result.allowed:
958
+ raise AccessDenied('Account %s can not remove data identifiers from followed table. %s' % (issuer, auth_result.message))
943
959
 
944
960
  internal_scope = InternalScope(scope, vo=vo)
945
961
  internal_account = InternalAccount(account, vo=vo)
@@ -948,7 +964,7 @@ def remove_did_from_followed(
948
964
 
949
965
  @transactional_session
950
966
  def remove_dids_from_followed(
951
- dids: Iterable[Mapping[str, Any]],
967
+ dids: 'Iterable[Mapping[str, Any]]',
952
968
  account: str,
953
969
  issuer: str,
954
970
  *,
@@ -963,8 +979,9 @@ def remove_dids_from_followed(
963
979
  :param session: The database session in use.
964
980
  """
965
981
  kwargs = {'dids': dids, 'issuer': issuer}
966
- if not rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='remove_dids_from_followed', kwargs=kwargs, session=session):
967
- raise AccessDenied('Account %s can not bulk remove data identifiers from followed table' % (issuer))
982
+ auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='remove_dids_from_followed', kwargs=kwargs, session=session)
983
+ if not auth_result.allowed:
984
+ raise AccessDenied('Account %s can not bulk remove data identifiers from followed table. %s' % (issuer, auth_result.message))
968
985
 
969
986
  internal_account = InternalAccount(account, vo=vo)
970
987
  return did.remove_dids_from_followed(dids=dids, account=internal_account, session=session)
rucio/gateway/dirac.py CHANGED
@@ -68,14 +68,16 @@ def add_files(
68
68
  for rse in rses:
69
69
  rse_id = rses[rse]
70
70
  kwargs = {'rse': rse, 'rse_id': rse_id}
71
- if not has_permission(issuer=issuer, action='add_replicas', kwargs=kwargs, vo=vo, session=session):
72
- raise AccessDenied('Account %s can not add file replicas on %s for VO %s' % (issuer, rse, vo))
71
+ auth_result = has_permission(issuer=issuer, action='add_replicas', kwargs=kwargs, vo=vo, session=session)
72
+ if not auth_result.allowed:
73
+ raise AccessDenied('Account %s can not add file replicas on %s for VO %s. %s' % (issuer, rse, vo, auth_result.message))
73
74
  if not has_permission(issuer=issuer, action='skip_availability_check', kwargs=kwargs, vo=vo, session=session):
74
75
  ignore_availability = False
75
76
 
76
77
  # Check if the issuer can add the files
77
78
  kwargs = {'issuer': issuer, 'dids': dids}
78
- if not has_permission(issuer=issuer, action='add_dids', kwargs=kwargs, vo=vo, session=session):
79
- raise AccessDenied('Account %s can not bulk add data identifier for VO %s' % (issuer, vo))
79
+ auth_result = has_permission(issuer=issuer, action='add_dids', kwargs=kwargs, vo=vo, session=session)
80
+ if not auth_result.allowed:
81
+ raise AccessDenied('Account %s can not bulk add data identifier for VO %s. %s' % (issuer, vo, auth_result.message))
80
82
 
81
83
  dirac.add_files(lfns=lfns, account=issuer, ignore_availability=ignore_availability, parents_metadata=parents_metadata, vo=vo, session=session)