rucio 38.2.0__py3-none-any.whl → 38.4.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.
- rucio/cli/bin_legacy/rucio.py +26 -23
- rucio/cli/command.py +36 -26
- rucio/cli/config.py +22 -7
- rucio/cli/did.py +2 -2
- rucio/cli/download.py +1 -1
- rucio/cli/opendata.py +78 -10
- rucio/cli/utils.py +13 -1
- rucio/client/accountclient.py +20 -19
- rucio/client/accountlimitclient.py +5 -4
- rucio/client/baseclient.py +25 -25
- rucio/client/configclient.py +29 -5
- rucio/client/credentialclient.py +2 -1
- rucio/client/didclient.py +33 -32
- rucio/client/diracclient.py +2 -1
- rucio/client/exportclient.py +2 -1
- rucio/client/importclient.py +2 -1
- rucio/client/lifetimeclient.py +3 -2
- rucio/client/lockclient.py +4 -3
- rucio/client/metaconventionsclient.py +5 -4
- rucio/client/opendataclient.py +8 -7
- rucio/client/pingclient.py +2 -1
- rucio/client/replicaclient.py +27 -26
- rucio/client/requestclient.py +8 -8
- rucio/client/richclient.py +6 -0
- rucio/client/rseclient.py +31 -28
- rucio/client/ruleclient.py +13 -12
- rucio/client/scopeclient.py +4 -3
- rucio/client/subscriptionclient.py +6 -5
- rucio/common/constants.py +23 -0
- rucio/common/exception.py +30 -0
- rucio/common/plugins.py +33 -15
- rucio/common/utils.py +3 -3
- rucio/core/config.py +8 -6
- rucio/core/credential.py +19 -26
- rucio/core/did.py +1 -1
- rucio/core/did_meta_plugins/did_column_meta.py +226 -69
- rucio/core/opendata.py +150 -8
- rucio/core/replica.py +3 -4
- rucio/core/request.py +1 -1
- rucio/core/rule.py +6 -3
- rucio/core/rule_grouping.py +5 -5
- rucio/gateway/account.py +8 -7
- rucio/gateway/config.py +2 -37
- rucio/gateway/opendata.py +2 -2
- rucio/gateway/request.py +2 -117
- rucio/gateway/rule.py +2 -2
- rucio/rse/protocols/webdav.py +5 -2
- rucio/rse/translation.py +3 -3
- rucio/transfertool/fts3.py +0 -19
- rucio/transfertool/fts3_plugins.py +3 -3
- rucio/vcsversion.py +3 -3
- rucio/web/rest/flaskapi/v1/accountlimits.py +4 -3
- rucio/web/rest/flaskapi/v1/accounts.py +26 -25
- rucio/web/rest/flaskapi/v1/archives.py +2 -2
- rucio/web/rest/flaskapi/v1/auth.py +15 -14
- rucio/web/rest/flaskapi/v1/common.py +4 -4
- rucio/web/rest/flaskapi/v1/config.py +57 -17
- rucio/web/rest/flaskapi/v1/credentials.py +3 -3
- rucio/web/rest/flaskapi/v1/dids.py +25 -24
- rucio/web/rest/flaskapi/v1/dirac.py +3 -2
- rucio/web/rest/flaskapi/v1/export.py +4 -2
- rucio/web/rest/flaskapi/v1/heartbeats.py +2 -1
- rucio/web/rest/flaskapi/v1/identities.py +5 -4
- rucio/web/rest/flaskapi/v1/import.py +3 -2
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +3 -2
- rucio/web/rest/flaskapi/v1/locks.py +4 -3
- rucio/web/rest/flaskapi/v1/meta_conventions.py +4 -3
- rucio/web/rest/flaskapi/v1/metrics.py +2 -1
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +2 -1
- rucio/web/rest/flaskapi/v1/opendata.py +7 -6
- rucio/web/rest/flaskapi/v1/opendata_public.py +6 -5
- rucio/web/rest/flaskapi/v1/ping.py +3 -2
- rucio/web/rest/flaskapi/v1/redirect.py +4 -3
- rucio/web/rest/flaskapi/v1/replicas.py +31 -31
- rucio/web/rest/flaskapi/v1/requests.py +7 -7
- rucio/web/rest/flaskapi/v1/rses.py +23 -16
- rucio/web/rest/flaskapi/v1/rules.py +9 -8
- rucio/web/rest/flaskapi/v1/scopes.py +4 -3
- rucio/web/rest/flaskapi/v1/subscriptions.py +9 -8
- rucio/web/rest/flaskapi/v1/traces.py +2 -1
- rucio/web/rest/flaskapi/v1/vos.py +4 -3
- {rucio-38.2.0.dist-info → rucio-38.4.0.dist-info}/METADATA +1 -1
- {rucio-38.2.0.dist-info → rucio-38.4.0.dist-info}/RECORD +142 -142
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/alembic.ini.template +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/requirements.server.txt +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/tools/bootstrap.py +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/data/rucio/tools/reset_database.py +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-abacus-account +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-abacus-collection-replica +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-abacus-rse +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-admin +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-atropos +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-auditor +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-automatix +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-bb8 +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-cache-client +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-cache-consumer +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-conveyor-finisher +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-conveyor-poller +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-conveyor-preparer +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-conveyor-receiver +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-conveyor-stager +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-conveyor-submitter +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-conveyor-throttler +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-dark-reaper +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-dumper +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-follower +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-hermes +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-judge-cleaner +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-judge-evaluator +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-judge-injector +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-judge-repairer +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-kronos +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-minos +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-minos-temporary-expiration +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-necromancer +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-oauth-manager +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-reaper +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-replica-recoverer +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-rse-decommissioner +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-storage-consistency-actions +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-transmogrifier +0 -0
- {rucio-38.2.0.data → rucio-38.4.0.data}/scripts/rucio-undertaker +0 -0
- {rucio-38.2.0.dist-info → rucio-38.4.0.dist-info}/WHEEL +0 -0
- {rucio-38.2.0.dist-info → rucio-38.4.0.dist-info}/licenses/AUTHORS.rst +0 -0
- {rucio-38.2.0.dist-info → rucio-38.4.0.dist-info}/licenses/LICENSE +0 -0
- {rucio-38.2.0.dist-info → rucio-38.4.0.dist-info}/top_level.txt +0 -0
rucio/gateway/rule.py
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
from typing import TYPE_CHECKING, Any, Literal, Optional
|
|
16
16
|
|
|
17
17
|
from rucio.common.config import config_get_bool
|
|
18
|
-
from rucio.common.constants import DEFAULT_VO
|
|
18
|
+
from rucio.common.constants import DEFAULT_ACTIVITY, DEFAULT_VO
|
|
19
19
|
from rucio.common.exception import AccessDenied
|
|
20
20
|
from rucio.common.schema import validate_schema
|
|
21
21
|
from rucio.common.types import InternalAccount, InternalScope
|
|
@@ -97,7 +97,7 @@ def add_replication_rule(
|
|
|
97
97
|
account = issuer
|
|
98
98
|
|
|
99
99
|
if activity is None:
|
|
100
|
-
activity =
|
|
100
|
+
activity = DEFAULT_ACTIVITY
|
|
101
101
|
|
|
102
102
|
kwargs = {'dids': dids, 'copies': copies, 'rse_expression': rse_expression, 'weight': weight, 'lifetime': lifetime,
|
|
103
103
|
'grouping': grouping, 'account': account, 'locked': locked, 'subscription_id': subscription_id,
|
rucio/rse/protocols/webdav.py
CHANGED
|
@@ -25,6 +25,7 @@ from requests.adapters import HTTPAdapter
|
|
|
25
25
|
from urllib3.poolmanager import PoolManager
|
|
26
26
|
|
|
27
27
|
from rucio.common import exception
|
|
28
|
+
from rucio.common.constants import HTTPMethod
|
|
28
29
|
from rucio.rse.protocols import protocol
|
|
29
30
|
|
|
30
31
|
|
|
@@ -259,9 +260,11 @@ class Default(protocol.RSEProtocol):
|
|
|
259
260
|
try:
|
|
260
261
|
# use GET instead of HEAD for presigned urls
|
|
261
262
|
if not using_presigned_urls:
|
|
262
|
-
result = self.session.request(
|
|
263
|
+
result = self.session.request(HTTPMethod.HEAD.value, path, verify=False, timeout=self.timeout,
|
|
264
|
+
cert=self.cert)
|
|
263
265
|
else:
|
|
264
|
-
result = self.session.request(
|
|
266
|
+
result = self.session.request(HTTPMethod.GET.value, path, verify=False, timeout=self.timeout,
|
|
267
|
+
cert=self.cert)
|
|
265
268
|
if result.status_code == 200:
|
|
266
269
|
return True
|
|
267
270
|
elif result.status_code in [401, ]:
|
rucio/rse/translation.py
CHANGED
|
@@ -18,7 +18,7 @@ from configparser import NoOptionError, NoSectionError
|
|
|
18
18
|
from typing import TYPE_CHECKING, Any, Optional
|
|
19
19
|
|
|
20
20
|
from rucio.common import config
|
|
21
|
-
from rucio.common.constants import DEFAULT_VO, RseAttr
|
|
21
|
+
from rucio.common.constants import DEFAULT_VO, POLICY_ALGORITHM_TYPES_LITERAL, RseAttr
|
|
22
22
|
from rucio.common.exception import ConfigNotFound
|
|
23
23
|
from rucio.common.plugins import PolicyPackageAlgorithms
|
|
24
24
|
|
|
@@ -33,7 +33,7 @@ class RSEDeterministicScopeTranslation(PolicyPackageAlgorithms):
|
|
|
33
33
|
Translates a pfn dictionary into a scope and name
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
|
-
_algorithm_type = "pfn2lfn"
|
|
36
|
+
_algorithm_type: POLICY_ALGORITHM_TYPES_LITERAL = "pfn2lfn"
|
|
37
37
|
|
|
38
38
|
def __init__(self, vo: str = DEFAULT_VO):
|
|
39
39
|
super().__init__()
|
|
@@ -111,7 +111,7 @@ class RSEDeterministicTranslation(PolicyPackageAlgorithms):
|
|
|
111
111
|
"""
|
|
112
112
|
|
|
113
113
|
_DEFAULT_LFN2PFN = "hash"
|
|
114
|
-
_algorithm_type = "lfn2pfn"
|
|
114
|
+
_algorithm_type: POLICY_ALGORITHM_TYPES_LITERAL = "lfn2pfn"
|
|
115
115
|
|
|
116
116
|
def __init__(
|
|
117
117
|
self,
|
rucio/transfertool/fts3.py
CHANGED
|
@@ -76,7 +76,6 @@ BULK_QUERY_COUNTER = METRICS.counter(name='{host}.bulk_query.{state}',
|
|
|
76
76
|
QUERY_DETAILS_COUNTER = METRICS.counter(name='{host}.query_details.{state}',
|
|
77
77
|
documentation='Number of detailed status queries', labelnames=('state', 'host'))
|
|
78
78
|
|
|
79
|
-
REWRITE_HTTPS_TO_DAVS = config_get_bool('transfers', 'rewrite_https_to_davs', default=False)
|
|
80
79
|
VO_CERTS_PATH = config_get('conveyor', 'vo_certs_path', False, None)
|
|
81
80
|
|
|
82
81
|
# https://fts3-docs.web.cern.ch/fts3-docs/docs/state_machine.html
|
|
@@ -1073,24 +1072,6 @@ class FTS3Transfertool(Transfertool):
|
|
|
1073
1072
|
if not transfer_file['sources'] or transfer_file['sources'] == []:
|
|
1074
1073
|
raise Exception('No sources defined')
|
|
1075
1074
|
|
|
1076
|
-
# TODO: remove the following logic in rucio 1.31
|
|
1077
|
-
if REWRITE_HTTPS_TO_DAVS:
|
|
1078
|
-
new_src_urls = []
|
|
1079
|
-
new_dst_urls = []
|
|
1080
|
-
for url in transfer_file['sources']:
|
|
1081
|
-
if url.startswith('https'):
|
|
1082
|
-
new_src_urls.append(':'.join(['davs'] + url.split(':')[1:]))
|
|
1083
|
-
else:
|
|
1084
|
-
new_src_urls.append(url)
|
|
1085
|
-
for url in transfer_file['destinations']:
|
|
1086
|
-
if url.startswith('https'):
|
|
1087
|
-
new_dst_urls.append(':'.join(['davs'] + url.split(':')[1:]))
|
|
1088
|
-
else:
|
|
1089
|
-
new_dst_urls.append(url)
|
|
1090
|
-
|
|
1091
|
-
transfer_file['sources'] = new_src_urls
|
|
1092
|
-
transfer_file['destinations'] = new_dst_urls
|
|
1093
|
-
|
|
1094
1075
|
transfer_id = None
|
|
1095
1076
|
expected_transfer_id = None
|
|
1096
1077
|
if self.deterministic_id:
|
|
@@ -17,7 +17,7 @@ import sys
|
|
|
17
17
|
from typing import TYPE_CHECKING, Any, Optional, TypeVar
|
|
18
18
|
|
|
19
19
|
from rucio.common.config import config_get_int
|
|
20
|
-
from rucio.common.constants import DEFAULT_VO
|
|
20
|
+
from rucio.common.constants import DEFAULT_VO, POLICY_ALGORITHM_TYPES_LITERAL
|
|
21
21
|
from rucio.common.exception import InvalidRequest
|
|
22
22
|
from rucio.common.plugins import PolicyPackageAlgorithms
|
|
23
23
|
|
|
@@ -33,8 +33,8 @@ class FTS3TapeMetadataPlugin(PolicyPackageAlgorithms):
|
|
|
33
33
|
Plugins are registered during initialization and called during a transfer with FTS3
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
|
-
ALGORITHM_NAME = "fts3_tape_metadata_plugins"
|
|
37
|
-
_INIT_FUNC_NAME = "fts3_plugins_init"
|
|
36
|
+
ALGORITHM_NAME: POLICY_ALGORITHM_TYPES_LITERAL = "fts3_tape_metadata_plugins"
|
|
37
|
+
_INIT_FUNC_NAME: POLICY_ALGORITHM_TYPES_LITERAL = "fts3_plugins_init"
|
|
38
38
|
DEFAULT = "def"
|
|
39
39
|
|
|
40
40
|
def __init__(self, policy_algorithm: str) -> None:
|
rucio/vcsversion.py
CHANGED
|
@@ -4,8 +4,8 @@ This file is automatically generated; Do not edit it. :)
|
|
|
4
4
|
'''
|
|
5
5
|
VERSION_INFO = {
|
|
6
6
|
'final': True,
|
|
7
|
-
'version': '38.
|
|
7
|
+
'version': '38.4.0',
|
|
8
8
|
'branch_nick': 'release-38-LTS',
|
|
9
|
-
'revision_id': '
|
|
10
|
-
'revno':
|
|
9
|
+
'revision_id': '945ab71be90243fe96148bb3bd13c1c3ae410765',
|
|
10
|
+
'revno': 14030
|
|
11
11
|
}
|
|
@@ -16,6 +16,7 @@ from typing import TYPE_CHECKING
|
|
|
16
16
|
|
|
17
17
|
from flask import Flask, request
|
|
18
18
|
|
|
19
|
+
from rucio.common.constants import HTTPMethod
|
|
19
20
|
from rucio.common.exception import AccessDenied, AccountNotFound, RSENotFound
|
|
20
21
|
from rucio.gateway.account_limit import delete_global_account_limit, delete_local_account_limit, set_global_account_limit, set_local_account_limit
|
|
21
22
|
from rucio.web.rest.flaskapi.authenticated_bp import AuthenticatedBlueprint
|
|
@@ -219,11 +220,11 @@ def blueprint(with_doc: bool = False) -> AuthenticatedBlueprint:
|
|
|
219
220
|
bp = AuthenticatedBlueprint('accountlimits', __name__, url_prefix='/accountlimits')
|
|
220
221
|
|
|
221
222
|
local_account_limit_view = LocalAccountLimit.as_view('local_account_limit')
|
|
222
|
-
bp.add_url_rule('/local/<account>/<rse>', view_func=local_account_limit_view, methods=[
|
|
223
|
+
bp.add_url_rule('/local/<account>/<rse>', view_func=local_account_limit_view, methods=[HTTPMethod.POST.value, HTTPMethod.DELETE.value])
|
|
223
224
|
if not with_doc:
|
|
224
|
-
bp.add_url_rule('/<account>/<rse>', view_func=local_account_limit_view, methods=[
|
|
225
|
+
bp.add_url_rule('/<account>/<rse>', view_func=local_account_limit_view, methods=[HTTPMethod.POST.value, HTTPMethod.DELETE.value])
|
|
225
226
|
global_account_limit_view = GlobalAccountLimit.as_view('global_account_limit')
|
|
226
|
-
bp.add_url_rule('/global/<account>/<rse_expression>', view_func=global_account_limit_view, methods=[
|
|
227
|
+
bp.add_url_rule('/global/<account>/<rse_expression>', view_func=global_account_limit_view, methods=[HTTPMethod.POST.value, HTTPMethod.DELETE.value])
|
|
227
228
|
|
|
228
229
|
bp.after_request(response_headers)
|
|
229
230
|
return bp
|
|
@@ -18,7 +18,8 @@ from typing import TYPE_CHECKING, Any, Literal, Optional, Union
|
|
|
18
18
|
|
|
19
19
|
from flask import Flask, Response, jsonify, redirect, request
|
|
20
20
|
|
|
21
|
-
from rucio.common.
|
|
21
|
+
from rucio.common.constants import HTTPMethod
|
|
22
|
+
from rucio.common.exception import AccessDenied, AccountNotFound, CounterNotFound, Duplicate, IdentityError, InvalidAccountType, InvalidObject, RSENotFound, RuleNotFound, ScopeNotFound
|
|
22
23
|
from rucio.common.utils import APIEncoder, render_json
|
|
23
24
|
from rucio.gateway.account import add_account, add_account_attribute, del_account, del_account_attribute, get_account_info, get_usage_history, list_account_attributes, list_accounts, list_identities, update_account
|
|
24
25
|
from rucio.gateway.account_limit import get_global_account_limit, get_global_account_usage, get_local_account_limit, get_local_account_usage
|
|
@@ -447,7 +448,7 @@ class AccountParameter(ErrorHandlingMethodView):
|
|
|
447
448
|
return generate_http_error_flask(409, error)
|
|
448
449
|
except AccessDenied as error:
|
|
449
450
|
return generate_http_error_flask(401, error)
|
|
450
|
-
except InvalidObject as error:
|
|
451
|
+
except (InvalidObject, InvalidAccountType) as error:
|
|
451
452
|
return generate_http_error_flask(400, error)
|
|
452
453
|
|
|
453
454
|
return 'Created', 201
|
|
@@ -1047,44 +1048,44 @@ def blueprint(with_doc: bool = False) -> AuthenticatedBlueprint:
|
|
|
1047
1048
|
bp = AuthenticatedBlueprint('accounts', __name__, url_prefix='/accounts')
|
|
1048
1049
|
|
|
1049
1050
|
attributes_view = Attributes.as_view('attributes')
|
|
1050
|
-
bp.add_url_rule('/<account>/attr/', view_func=attributes_view, methods=[
|
|
1051
|
-
bp.add_url_rule('/<account>/attr/<key>', view_func=attributes_view, methods=[
|
|
1051
|
+
bp.add_url_rule('/<account>/attr/', view_func=attributes_view, methods=[HTTPMethod.GET.value])
|
|
1052
|
+
bp.add_url_rule('/<account>/attr/<key>', view_func=attributes_view, methods=[HTTPMethod.POST.value, HTTPMethod.DELETE.value])
|
|
1052
1053
|
scopes_view = Scopes.as_view('scopes')
|
|
1053
|
-
bp.add_url_rule('/<account>/scopes/', view_func=scopes_view, methods=[
|
|
1054
|
-
bp.add_url_rule('/<account>/scopes/<scope>', view_func=scopes_view, methods=[
|
|
1054
|
+
bp.add_url_rule('/<account>/scopes/', view_func=scopes_view, methods=[HTTPMethod.GET.value])
|
|
1055
|
+
bp.add_url_rule('/<account>/scopes/<scope>', view_func=scopes_view, methods=[HTTPMethod.POST.value])
|
|
1055
1056
|
local_account_limits_view = LocalAccountLimits.as_view('local_account_limit')
|
|
1056
|
-
bp.add_url_rule('/<account>/limits/local', view_func=local_account_limits_view, methods=[
|
|
1057
|
-
bp.add_url_rule('/<account>/limits', view_func=local_account_limits_view, methods=[
|
|
1058
|
-
bp.add_url_rule('/<account>/limits/local/<rse>', view_func=local_account_limits_view, methods=[
|
|
1059
|
-
bp.add_url_rule('/<account>/limits/<rse>', view_func=local_account_limits_view, methods=[
|
|
1057
|
+
bp.add_url_rule('/<account>/limits/local', view_func=local_account_limits_view, methods=[HTTPMethod.GET.value])
|
|
1058
|
+
bp.add_url_rule('/<account>/limits', view_func=local_account_limits_view, methods=[HTTPMethod.GET.value])
|
|
1059
|
+
bp.add_url_rule('/<account>/limits/local/<rse>', view_func=local_account_limits_view, methods=[HTTPMethod.GET.value])
|
|
1060
|
+
bp.add_url_rule('/<account>/limits/<rse>', view_func=local_account_limits_view, methods=[HTTPMethod.GET.value])
|
|
1060
1061
|
global_account_limits_view = GlobalAccountLimits.as_view('global_account_limit')
|
|
1061
|
-
bp.add_url_rule('/<account>/limits/global', view_func=global_account_limits_view, methods=[
|
|
1062
|
-
bp.add_url_rule('/<account>/limits/global/<rse_expression>', view_func=global_account_limits_view, methods=[
|
|
1062
|
+
bp.add_url_rule('/<account>/limits/global', view_func=global_account_limits_view, methods=[HTTPMethod.GET.value])
|
|
1063
|
+
bp.add_url_rule('/<account>/limits/global/<rse_expression>', view_func=global_account_limits_view, methods=[HTTPMethod.GET.value])
|
|
1063
1064
|
identities_view = Identities.as_view('identities')
|
|
1064
|
-
bp.add_url_rule('/<account>/identities', view_func=identities_view, methods=[
|
|
1065
|
+
bp.add_url_rule('/<account>/identities', view_func=identities_view, methods=[HTTPMethod.GET.value, HTTPMethod.POST.value, HTTPMethod.DELETE.value])
|
|
1065
1066
|
rules_view = Rules.as_view('rules')
|
|
1066
|
-
bp.add_url_rule('/<account>/rules', view_func=rules_view, methods=[
|
|
1067
|
+
bp.add_url_rule('/<account>/rules', view_func=rules_view, methods=[HTTPMethod.GET.value])
|
|
1067
1068
|
usagehistory_view = UsageHistory.as_view('usagehistory')
|
|
1068
|
-
bp.add_url_rule('/<account>/usage/history/<rse>', view_func=usagehistory_view, methods=[
|
|
1069
|
+
bp.add_url_rule('/<account>/usage/history/<rse>', view_func=usagehistory_view, methods=[HTTPMethod.GET.value])
|
|
1069
1070
|
usage_view = LocalUsage.as_view('usage')
|
|
1070
|
-
bp.add_url_rule('/<account>/usage/local', view_func=usage_view, methods=[
|
|
1071
|
-
bp.add_url_rule('/<account>/usage', view_func=usage_view, methods=[
|
|
1071
|
+
bp.add_url_rule('/<account>/usage/local', view_func=usage_view, methods=[HTTPMethod.GET.value])
|
|
1072
|
+
bp.add_url_rule('/<account>/usage', view_func=usage_view, methods=[HTTPMethod.GET.value])
|
|
1072
1073
|
if not with_doc:
|
|
1073
1074
|
# for backwards-compatibility
|
|
1074
1075
|
# rule without trailing slash needs to be added before rule with trailing slash
|
|
1075
|
-
bp.add_url_rule('/<account>/usage/', view_func=usage_view, methods=[
|
|
1076
|
-
bp.add_url_rule('/<account>/usage/local/<rse>', view_func=usage_view, methods=[
|
|
1077
|
-
bp.add_url_rule('/<account>/usage/<rse>', view_func=usage_view, methods=[
|
|
1076
|
+
bp.add_url_rule('/<account>/usage/', view_func=usage_view, methods=[HTTPMethod.GET.value])
|
|
1077
|
+
bp.add_url_rule('/<account>/usage/local/<rse>', view_func=usage_view, methods=[HTTPMethod.GET.value])
|
|
1078
|
+
bp.add_url_rule('/<account>/usage/<rse>', view_func=usage_view, methods=[HTTPMethod.GET.value])
|
|
1078
1079
|
global_usage_view = GlobalUsage.as_view('global_usage')
|
|
1079
|
-
bp.add_url_rule('/<account>/usage/global', view_func=global_usage_view, methods=[
|
|
1080
|
-
bp.add_url_rule('/<account>/usage/global/<rse_expression>', view_func=global_usage_view, methods=[
|
|
1080
|
+
bp.add_url_rule('/<account>/usage/global', view_func=global_usage_view, methods=[HTTPMethod.GET.value])
|
|
1081
|
+
bp.add_url_rule('/<account>/usage/global/<rse_expression>', view_func=global_usage_view, methods=[HTTPMethod.GET.value])
|
|
1081
1082
|
account_parameter_view = AccountParameter.as_view('account_parameter')
|
|
1082
|
-
bp.add_url_rule('/<account>', view_func=account_parameter_view, methods=[
|
|
1083
|
+
bp.add_url_rule('/<account>', view_func=account_parameter_view, methods=[HTTPMethod.GET.value, HTTPMethod.PUT.value, HTTPMethod.POST.value, HTTPMethod.DELETE.value])
|
|
1083
1084
|
account_view = Account.as_view('account')
|
|
1084
1085
|
if not with_doc:
|
|
1085
1086
|
# rule without trailing slash needs to be added before rule with trailing slash
|
|
1086
|
-
bp.add_url_rule('', view_func=account_view, methods=[
|
|
1087
|
-
bp.add_url_rule('/', view_func=account_view, methods=[
|
|
1087
|
+
bp.add_url_rule('', view_func=account_view, methods=[HTTPMethod.GET.value])
|
|
1088
|
+
bp.add_url_rule('/', view_func=account_view, methods=[HTTPMethod.GET.value])
|
|
1088
1089
|
|
|
1089
1090
|
bp.after_request(response_headers)
|
|
1090
1091
|
return bp
|
|
@@ -17,7 +17,7 @@ from typing import TYPE_CHECKING
|
|
|
17
17
|
|
|
18
18
|
from flask import Flask, Response, request
|
|
19
19
|
|
|
20
|
-
from rucio.common.constants import DEFAULT_VO
|
|
20
|
+
from rucio.common.constants import DEFAULT_VO, HTTPMethod
|
|
21
21
|
from rucio.gateway.did import list_archive_content
|
|
22
22
|
from rucio.web.rest.flaskapi.authenticated_bp import AuthenticatedBlueprint
|
|
23
23
|
from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, check_accept_header_wrapper_flask, generate_http_error_flask, parse_scope_name, response_headers, try_stream
|
|
@@ -90,7 +90,7 @@ def blueprint() -> AuthenticatedBlueprint:
|
|
|
90
90
|
bp = AuthenticatedBlueprint('archives', __name__, url_prefix='/archives')
|
|
91
91
|
|
|
92
92
|
archive_view = Archive.as_view('archive')
|
|
93
|
-
bp.add_url_rule('/<path:scope_name>/files', view_func=archive_view, methods=[
|
|
93
|
+
bp.add_url_rule('/<path:scope_name>/files', view_func=archive_view, methods=[HTTPMethod.GET.value])
|
|
94
94
|
|
|
95
95
|
bp.after_request(response_headers)
|
|
96
96
|
return bp
|
|
@@ -23,6 +23,7 @@ from jinja2.exceptions import TemplateNotFound
|
|
|
23
23
|
from werkzeug.datastructures import Headers
|
|
24
24
|
|
|
25
25
|
from rucio.common.config import config_get
|
|
26
|
+
from rucio.common.constants import HTTPMethod
|
|
26
27
|
from rucio.common.exception import AccessDenied, CannotAuthenticate, CannotAuthorize, ConfigurationError, IdentityError, IdentityNotFound, InvalidRequest
|
|
27
28
|
from rucio.common.extra import import_extras
|
|
28
29
|
from rucio.common.utils import date_to_str
|
|
@@ -1632,31 +1633,31 @@ def blueprint() -> Blueprint:
|
|
|
1632
1633
|
bp = Blueprint('auth', __name__, url_prefix='/auth')
|
|
1633
1634
|
|
|
1634
1635
|
user_pass_view = UserPass.as_view('user_pass')
|
|
1635
|
-
bp.add_url_rule('/userpass', view_func=user_pass_view, methods=[
|
|
1636
|
+
bp.add_url_rule('/userpass', view_func=user_pass_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1636
1637
|
gss_view = GSS.as_view('gss')
|
|
1637
|
-
bp.add_url_rule('/gss', view_func=gss_view, methods=[
|
|
1638
|
+
bp.add_url_rule('/gss', view_func=gss_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1638
1639
|
x509_view = x509.as_view('x509')
|
|
1639
|
-
bp.add_url_rule('/x509', view_func=x509_view, methods=[
|
|
1640
|
-
bp.add_url_rule('/x509/webui', view_func=x509_view, methods=[
|
|
1641
|
-
bp.add_url_rule('/x509_proxy', view_func=x509_view, methods=[
|
|
1640
|
+
bp.add_url_rule('/x509', view_func=x509_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1641
|
+
bp.add_url_rule('/x509/webui', view_func=x509_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1642
|
+
bp.add_url_rule('/x509_proxy', view_func=x509_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1642
1643
|
ssh_view = SSH.as_view('ssh')
|
|
1643
|
-
bp.add_url_rule('/ssh', view_func=ssh_view, methods=[
|
|
1644
|
+
bp.add_url_rule('/ssh', view_func=ssh_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1644
1645
|
ssh_challenge_token_view = SSHChallengeToken.as_view('ssh_challenge_token')
|
|
1645
|
-
bp.add_url_rule('/ssh_challenge_token', view_func=ssh_challenge_token_view, methods=[
|
|
1646
|
+
bp.add_url_rule('/ssh_challenge_token', view_func=ssh_challenge_token_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1646
1647
|
saml_view = SAML.as_view('saml')
|
|
1647
|
-
bp.add_url_rule('/saml', view_func=saml_view, methods=[
|
|
1648
|
+
bp.add_url_rule('/saml', view_func=saml_view, methods=[HTTPMethod.GET.value, HTTPMethod.POST.value, HTTPMethod.OPTIONS.value])
|
|
1648
1649
|
validate_view = Validate.as_view('validate')
|
|
1649
|
-
bp.add_url_rule('/validate', view_func=validate_view, methods=[
|
|
1650
|
+
bp.add_url_rule('/validate', view_func=validate_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1650
1651
|
oidc_view = OIDC.as_view('oidc_view')
|
|
1651
|
-
bp.add_url_rule('/oidc', view_func=oidc_view, methods=[
|
|
1652
|
+
bp.add_url_rule('/oidc', view_func=oidc_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1652
1653
|
token_oidc_view = TokenOIDC.as_view('token_oidc_view')
|
|
1653
|
-
bp.add_url_rule('/oidc_token', view_func=token_oidc_view, methods=[
|
|
1654
|
+
bp.add_url_rule('/oidc_token', view_func=token_oidc_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1654
1655
|
code_oidc_view = CodeOIDC.as_view('code_oidc_view')
|
|
1655
|
-
bp.add_url_rule('/oidc_code', view_func=code_oidc_view, methods=[
|
|
1656
|
+
bp.add_url_rule('/oidc_code', view_func=code_oidc_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1656
1657
|
redirect_oidc_view = RedirectOIDC.as_view('redirect_oidc_view')
|
|
1657
|
-
bp.add_url_rule('/oidc_redirect', view_func=redirect_oidc_view, methods=[
|
|
1658
|
+
bp.add_url_rule('/oidc_redirect', view_func=redirect_oidc_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1658
1659
|
refresh_oidc_view = RefreshOIDC.as_view('refresh_oidc_view')
|
|
1659
|
-
bp.add_url_rule('/oidc_refresh', view_func=refresh_oidc_view, methods=[
|
|
1660
|
+
bp.add_url_rule('/oidc_refresh', view_func=refresh_oidc_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
1660
1661
|
|
|
1661
1662
|
return bp
|
|
1662
1663
|
|
|
@@ -31,7 +31,7 @@ from werkzeug.exceptions import HTTPException
|
|
|
31
31
|
from werkzeug.wrappers import Request, Response
|
|
32
32
|
|
|
33
33
|
from rucio.common import config
|
|
34
|
-
from rucio.common.constants import DEFAULT_VO
|
|
34
|
+
from rucio.common.constants import DEFAULT_VO, HTTPMethod
|
|
35
35
|
from rucio.common.exception import CannotAuthenticate, DatabaseException, IdentityError, RucioException, UnsupportedRequestedContentType
|
|
36
36
|
from rucio.common.schema import get_schema_value
|
|
37
37
|
from rucio.common.utils import generate_uuid, render_json
|
|
@@ -66,7 +66,7 @@ class CORSMiddleware:
|
|
|
66
66
|
def __call__(self, environ: 'WSGIEnvironment', start_response: 'StartResponse') -> 'Iterable[bytes]':
|
|
67
67
|
request: Request = Request(environ)
|
|
68
68
|
|
|
69
|
-
if request.environ.get('REQUEST_METHOD') ==
|
|
69
|
+
if request.environ.get('REQUEST_METHOD') == HTTPMethod.OPTIONS.value:
|
|
70
70
|
try:
|
|
71
71
|
webui_urls = config.config_get_list('webui', 'urls')
|
|
72
72
|
except (NoOptionError, NoSectionError, RuntimeError) as error:
|
|
@@ -145,7 +145,7 @@ class ErrorHandlingMethodView(MethodView):
|
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
def request_auth_env() -> Optional['ResponseReturnValue']:
|
|
148
|
-
if flask.request.environ.get('REQUEST_METHOD') ==
|
|
148
|
+
if flask.request.environ.get('REQUEST_METHOD') == HTTPMethod.OPTIONS.value:
|
|
149
149
|
return '', 200
|
|
150
150
|
|
|
151
151
|
auth_token = flask.request.headers.get('X-Rucio-Auth-Token', default=None)
|
|
@@ -176,7 +176,7 @@ def response_headers(response: ResponseTypeVar) -> ResponseTypeVar:
|
|
|
176
176
|
response.headers['Access-Control-Allow-Methods'] = '*'
|
|
177
177
|
response.headers['Access-Control-Allow-Credentials'] = 'true'
|
|
178
178
|
|
|
179
|
-
if flask.request.environ.get('REQUEST_METHOD') ==
|
|
179
|
+
if flask.request.environ.get('REQUEST_METHOD') == HTTPMethod.GET.value:
|
|
180
180
|
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
|
|
181
181
|
response.headers['Cache-Control'] = 'post-check=0, pre-check=0'
|
|
182
182
|
response.headers['Pragma'] = 'no-cache'
|
|
@@ -12,20 +12,26 @@
|
|
|
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
|
|
16
|
+
|
|
15
17
|
from flask import Flask, jsonify
|
|
16
18
|
from flask import request as request
|
|
17
19
|
|
|
20
|
+
from rucio.common.constants import HTTPMethod
|
|
18
21
|
from rucio.common.exception import AccessDenied, ConfigNotFound, ConfigurationError
|
|
19
22
|
from rucio.gateway import config
|
|
20
23
|
from rucio.web.rest.flaskapi.authenticated_bp import AuthenticatedBlueprint
|
|
21
24
|
from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, check_accept_header_wrapper_flask, generate_http_error_flask, json_parameters, response_headers
|
|
22
25
|
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from flask.typing import ResponseReturnValue
|
|
28
|
+
|
|
23
29
|
|
|
24
30
|
class Config(ErrorHandlingMethodView):
|
|
25
31
|
""" REST API for full configuration. """
|
|
26
32
|
|
|
27
33
|
@check_accept_header_wrapper_flask(['application/json'])
|
|
28
|
-
def get(self):
|
|
34
|
+
def get(self) -> 'ResponseReturnValue':
|
|
29
35
|
"""
|
|
30
36
|
---
|
|
31
37
|
summary: List
|
|
@@ -53,7 +59,7 @@ class Config(ErrorHandlingMethodView):
|
|
|
53
59
|
|
|
54
60
|
return jsonify(res), 200
|
|
55
61
|
|
|
56
|
-
def post(self):
|
|
62
|
+
def post(self) -> 'ResponseReturnValue':
|
|
57
63
|
"""
|
|
58
64
|
---
|
|
59
65
|
summary: Create
|
|
@@ -97,7 +103,7 @@ class Section(ErrorHandlingMethodView):
|
|
|
97
103
|
""" REST API for the sections in the configuration. """
|
|
98
104
|
|
|
99
105
|
@check_accept_header_wrapper_flask(['application/json'])
|
|
100
|
-
def get(self, section):
|
|
106
|
+
def get(self, section: str) -> 'ResponseReturnValue':
|
|
101
107
|
"""
|
|
102
108
|
---
|
|
103
109
|
summary: List Sections
|
|
@@ -136,25 +142,55 @@ class Section(ErrorHandlingMethodView):
|
|
|
136
142
|
406:
|
|
137
143
|
description: "Not acceptable"
|
|
138
144
|
"""
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
145
|
+
if config.has_section(section, issuer=request.environ['issuer'], vo=request.environ['vo']):
|
|
146
|
+
res = {}
|
|
147
|
+
for item in config.items(section, issuer=request.environ['issuer'], vo=request.environ['vo']):
|
|
148
|
+
res[item[0]] = item[1]
|
|
149
|
+
return jsonify(res), 200
|
|
142
150
|
|
|
143
|
-
|
|
151
|
+
else:
|
|
144
152
|
return generate_http_error_flask(
|
|
145
153
|
status_code=404,
|
|
146
154
|
exc=ConfigNotFound.__name__,
|
|
147
155
|
exc_msg=f"No configuration found for section '{section}'"
|
|
148
156
|
)
|
|
149
157
|
|
|
150
|
-
|
|
158
|
+
def delete(self, section: str) -> 'ResponseReturnValue':
|
|
159
|
+
"""
|
|
160
|
+
---
|
|
161
|
+
summary: Remove an existing section
|
|
162
|
+
tags:
|
|
163
|
+
- Config
|
|
164
|
+
parameters:
|
|
165
|
+
- name: section
|
|
166
|
+
in: path
|
|
167
|
+
description: "The section."
|
|
168
|
+
responses:
|
|
169
|
+
200:
|
|
170
|
+
description: "OK"
|
|
171
|
+
401:
|
|
172
|
+
description: "Invalid Auth Token"
|
|
173
|
+
404:
|
|
174
|
+
description: "Config not found"
|
|
175
|
+
406:
|
|
176
|
+
description: "Not acceptable"
|
|
177
|
+
"""
|
|
178
|
+
if config.has_section(section, issuer=request.environ['issuer'], vo=request.environ['vo']):
|
|
179
|
+
config.remove_section(section, issuer=request.environ['issuer'], vo=request.environ['vo'])
|
|
180
|
+
return '', 200
|
|
181
|
+
else:
|
|
182
|
+
return generate_http_error_flask(
|
|
183
|
+
status_code=404,
|
|
184
|
+
exc=ConfigNotFound.__name__,
|
|
185
|
+
exc_msg=f"No configuration found for section '{section}'"
|
|
186
|
+
)
|
|
151
187
|
|
|
152
188
|
|
|
153
189
|
class OptionGetDel(ErrorHandlingMethodView):
|
|
154
190
|
""" REST API for reading or deleting the options in the configuration. """
|
|
155
191
|
|
|
156
192
|
@check_accept_header_wrapper_flask(['application/json'])
|
|
157
|
-
def get(self, section, option):
|
|
193
|
+
def get(self, section: str, option: str) -> 'ResponseReturnValue':
|
|
158
194
|
"""
|
|
159
195
|
---
|
|
160
196
|
summary: Get option
|
|
@@ -197,7 +233,7 @@ class OptionGetDel(ErrorHandlingMethodView):
|
|
|
197
233
|
except ConfigNotFound as error:
|
|
198
234
|
return generate_http_error_flask(404, error, f"No configuration found for section '{section}' option '{option}'")
|
|
199
235
|
|
|
200
|
-
def delete(self, section, option):
|
|
236
|
+
def delete(self, section: str, option: str) -> 'ResponseReturnValue':
|
|
201
237
|
"""
|
|
202
238
|
---
|
|
203
239
|
summary: Delete option
|
|
@@ -223,14 +259,17 @@ class OptionGetDel(ErrorHandlingMethodView):
|
|
|
223
259
|
401:
|
|
224
260
|
description: "Invalid Auth Token"
|
|
225
261
|
"""
|
|
226
|
-
config.
|
|
227
|
-
|
|
262
|
+
if config.has_option(section, option, issuer=request.environ['issuer'], vo=request.environ['vo']):
|
|
263
|
+
config.remove_option(section=section, option=option, issuer=request.environ['issuer'], vo=request.environ['vo'])
|
|
264
|
+
return '', 200
|
|
265
|
+
else:
|
|
266
|
+
return generate_http_error_flask(404, ConfigNotFound.__name__, f"No configuration found for section '{section}' option '{option}'")
|
|
228
267
|
|
|
229
268
|
|
|
230
269
|
class OptionSet(ErrorHandlingMethodView):
|
|
231
270
|
""" REST API for setting the options in the configuration. """
|
|
232
271
|
|
|
233
|
-
def put(self, section, option, value):
|
|
272
|
+
def put(self, section: str, option: str, value: str) -> 'ResponseReturnValue':
|
|
234
273
|
"""
|
|
235
274
|
---
|
|
236
275
|
summary: Create value
|
|
@@ -285,13 +324,14 @@ def blueprint() -> AuthenticatedBlueprint:
|
|
|
285
324
|
bp = AuthenticatedBlueprint('config', __name__, url_prefix='/config')
|
|
286
325
|
|
|
287
326
|
option_set_view = OptionSet.as_view('option_set')
|
|
288
|
-
bp.add_url_rule('/<section>/<option>/<value>', view_func=option_set_view, methods=[
|
|
327
|
+
bp.add_url_rule('/<section>/<option>/<value>', view_func=option_set_view, methods=[HTTPMethod.PUT.value])
|
|
289
328
|
option_get_del_view = OptionGetDel.as_view('option_get_del')
|
|
290
|
-
bp.add_url_rule('/<section>/<option>', view_func=option_get_del_view, methods=[
|
|
329
|
+
bp.add_url_rule('/<section>/<option>', view_func=option_get_del_view, methods=[HTTPMethod.GET.value, HTTPMethod.DELETE.value])
|
|
291
330
|
section_view = Section.as_view('section')
|
|
292
|
-
|
|
331
|
+
|
|
332
|
+
bp.add_url_rule('/<section>', view_func=section_view, methods=[HTTPMethod.GET.value, HTTPMethod.DELETE.value])
|
|
293
333
|
config_view = Config.as_view('config')
|
|
294
|
-
bp.add_url_rule('', view_func=config_view, methods=[
|
|
334
|
+
bp.add_url_rule('', view_func=config_view, methods=[HTTPMethod.GET.value, HTTPMethod.POST.value])
|
|
295
335
|
|
|
296
336
|
bp.after_request(response_headers)
|
|
297
337
|
return bp
|
|
@@ -17,7 +17,7 @@ from typing import TYPE_CHECKING, cast
|
|
|
17
17
|
from flask import Flask, request
|
|
18
18
|
from werkzeug.datastructures import Headers
|
|
19
19
|
|
|
20
|
-
from rucio.common.constants import RSE_BASE_SUPPORTED_PROTOCOL_OPERATIONS, RSE_BASE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL, SUPPORTED_SIGN_URL_SERVICES, SUPPORTED_SIGN_URL_SERVICES_LITERAL
|
|
20
|
+
from rucio.common.constants import RSE_BASE_SUPPORTED_PROTOCOL_OPERATIONS, RSE_BASE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL, SUPPORTED_SIGN_URL_SERVICES, SUPPORTED_SIGN_URL_SERVICES_LITERAL, HTTPMethod
|
|
21
21
|
from rucio.common.exception import CannotAuthenticate
|
|
22
22
|
from rucio.gateway.credential import get_signed_url
|
|
23
23
|
from rucio.web.rest.flaskapi.authenticated_bp import AuthenticatedBlueprint
|
|
@@ -203,10 +203,10 @@ def blueprint(with_doc=False):
|
|
|
203
203
|
bp = AuthenticatedBlueprint('credentials', __name__, url_prefix='/credentials')
|
|
204
204
|
|
|
205
205
|
signurl_view = SignURL.as_view('signurl')
|
|
206
|
-
bp.add_url_rule('/signurl', view_func=signurl_view, methods=[
|
|
206
|
+
bp.add_url_rule('/signurl', view_func=signurl_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
207
207
|
if not with_doc:
|
|
208
208
|
# yes, /signur ~= '/signurl?$'
|
|
209
|
-
bp.add_url_rule('/signur', view_func=signurl_view, methods=[
|
|
209
|
+
bp.add_url_rule('/signur', view_func=signurl_view, methods=[HTTPMethod.GET.value, HTTPMethod.OPTIONS.value])
|
|
210
210
|
|
|
211
211
|
bp.after_request(response_headers)
|
|
212
212
|
|