Skip to content

Commit 0a28484

Browse files
committed
Updated auth token validation to use py sdk, TTL will be used by both private and token urls, minor refactoring
1 parent 39f6063 commit 0a28484

1 file changed

Lines changed: 19 additions & 35 deletions

File tree

cloudinary_cli/modules/clone.py

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
help="Webhook notification URL.")
4545
@option("-t", "--ttl", type=int, default=3600,
4646
help=("URL expiration duration in seconds. Only relevant if cloning "
47-
"restricted assets without providing an auth_key in which case "
47+
"restricted assets. If you do not provide an auth_key, "
4848
"a private download URL is generated which may incur additional "
4949
"bandwidth costs."))
5050
def clone(target, force, overwrite, concurrent_workers, fields,
@@ -64,16 +64,21 @@ def clone(target, force, overwrite, concurrent_workers, fields,
6464
"as source environment.")
6565
return False
6666

67-
source_config = config_to_dict(cloudinary.config())
68-
auth_token = source_config.get("auth_token")
69-
if auth_token and not validate_authtoken(auth_token):
67+
auth_token = cloudinary.config().auth_token
68+
if auth_token:
7069
# It is important to validate auth_token if provided as this prevents
7170
# customer from having to re-run the command as well as
7271
# saving Admin API calls and time.
73-
return False
72+
try:
73+
cloudinary.utils.generate_auth_token(acl="/image/*")
74+
except Exception as e:
75+
logger.error(f"{e} - auth_token validation failed. "
76+
"Please double-check your auth_token parameters.")
77+
return False
7478

7579
source_assets = search_assets(force, search_exp)
7680
if not source_assets:
81+
# End command if search_exp contains unsupported type(s)
7782
return False
7883

7984
upload_list = []
@@ -85,44 +90,21 @@ def clone(target, force, overwrite, concurrent_workers, fields,
8590
updated_options.update(config_to_dict(target_config))
8691
upload_list.append((asset_url, {**updated_options}))
8792

93+
source_cloud_name = cloudinary.config().cloud_name
8894
if not upload_list:
89-
logger.error(style(f'No assets found in {cloudinary.config().cloud_name}', fg="red"))
95+
logger.error(style('No asset(s) found in '
96+
f'{source_cloud_name}', fg="red"))
9097
return False
9198

92-
logger.info(style(f'Copying {len(upload_list)} asset(s) from {cloudinary.config().cloud_name} to {target_config.cloud_name}', fg="blue"))
99+
logger.info(style(f'Copying {len(upload_list)} asset(s) from '
100+
f'{source_cloud_name} to '
101+
f'{target_config.cloud_name}', fg="blue"))
93102

94103
run_tasks_concurrently(upload_file, upload_list, concurrent_workers)
95104

96105
return True
97106

98107

99-
def validate_authtoken(auth_token):
100-
duration = auth_token.get('duration')
101-
if not duration:
102-
logger.error("Duration is required when using auth_token. Include "
103-
"`auth_token[duration]=<duration>` in your config.")
104-
return False
105-
try:
106-
duration = int(duration)
107-
if duration < 0:
108-
logger.error("Duration cannot be negative.")
109-
return False
110-
except (ValueError, TypeError):
111-
logger.error("Duration must be an integer.")
112-
return False
113-
key = auth_token.get('key')
114-
if not key:
115-
logger.error("No auth_token key found. Include "
116-
"`auth_token[key]=<key>` in your config.")
117-
return False
118-
try:
119-
_digest("", key)
120-
except Exception as e:
121-
logger.error(f"Auth token invalid: {e}.")
122-
return False
123-
return True
124-
125-
126108
def search_assets(force, search_exp):
127109
# Prevent other unsupported types to prevent
128110
# avoidable errors during the upload process
@@ -143,7 +125,7 @@ def search_assets(force, search_exp):
143125
search_exp += " AND (type:upload OR type:private OR type:authenticated)"
144126
else:
145127
search_exp = "type:upload OR type:private OR type:authenticated"
146-
print(search_exp)
128+
147129
search = cloudinary.search.Search().expression(search_exp)
148130
search.fields(['tags', 'context', 'access_control',
149131
'secure_url', 'display_name', 'format'])
@@ -172,12 +154,14 @@ def process_metadata(res, overwrite, async_, notification_url,
172154
# Generate a time-limited URL for restricted assets
173155
# Use private url if no auth_token provided
174156
if auth_token:
157+
# Don't add format if asset is raw
175158
pub_id_format = (pub_id if reso_type == "raw"
176159
else f"{pub_id}.{file_format}")
177160
asset_url = cloudinary.utils.cloudinary_url(
178161
pub_id_format,
179162
type=del_type,
180163
resource_type=reso_type,
164+
auth_token={"duration": ttl},
181165
secure=True,
182166
sign_url=True)
183167
else:

0 commit comments

Comments
 (0)