|
27 | 27 | import uuid |
28 | 28 | from functools import wraps |
29 | 29 |
|
| 30 | +import requests |
30 | 31 | from flask import current_app, request |
31 | 32 | from flask_login import current_user |
32 | 33 | from invenio_access.models import ActionRoles, ActionUsers |
|
49 | 50 | from sqlalchemy.orm.exc import NoResultFound |
50 | 51 | from werkzeug.local import LocalProxy |
51 | 52 |
|
52 | | -from cap.modules.deposit.errors import DisconnectWebhookError, FileUploadError |
| 53 | +from cap.modules.auth.ext import _fetch_token |
| 54 | +from cap.modules.deposit.errors import AuthorizationError, \ |
| 55 | + DisconnectWebhookError, FileUploadError |
53 | 56 | from cap.modules.deposit.validators import NoRequiredValidator |
54 | 57 | from cap.modules.experiments.permissions import exp_need_factory |
55 | 58 | from cap.modules.mail.utils import post_action_notifications |
|
75 | 78 | UpdateDepositPermission) |
76 | 79 |
|
77 | 80 | from .review import Reviewable |
| 81 | +from .tasks import upload_to_zenodo |
78 | 82 |
|
79 | 83 | _datastore = LocalProxy(lambda: current_app.extensions['security'].datastore) |
80 | 84 |
|
@@ -254,53 +258,109 @@ def upload(self, pid, *args, **kwargs): |
254 | 258 | _, rec = request.view_args.get('pid_value').data |
255 | 259 | record_uuid = str(rec.id) |
256 | 260 | data = request.get_json() |
257 | | - webhook = data.get('webhook', False) |
258 | | - event_type = data.get('event_type', 'release') |
259 | | - |
260 | | - try: |
261 | | - url = data['url'] |
262 | | - except KeyError: |
263 | | - raise FileUploadError('Missing url parameter.') |
| 261 | + target = data.get('target') |
| 262 | + |
| 263 | + if target == 'zenodo': |
| 264 | + # check for token |
| 265 | + token = _fetch_token('zenodo') |
| 266 | + if not token: |
| 267 | + raise FileUploadError( |
| 268 | + 'Token not found, please connect your Zenodo ' |
| 269 | + 'account before creating a deposit.') |
| 270 | + |
| 271 | + files = data.get('files') |
| 272 | + bucket = data.get('bucket') |
| 273 | + if files and bucket: |
| 274 | + # first create a deposit, and check if token is expired |
| 275 | + deposit = requests.post( |
| 276 | + url=f'{current_app.config.get("ZENODO_SERVER_URL")}' |
| 277 | + f'/deposit/depositions', |
| 278 | + params=dict(access_token=token), |
| 279 | + json={}, |
| 280 | + headers={'Content-Type': 'application/json'} |
| 281 | + ) |
| 282 | + if not deposit.ok: |
| 283 | + if deposit.status_code == 401: |
| 284 | + raise AuthorizationError( |
| 285 | + 'Authorization to Zenodo failed. ' |
| 286 | + 'Please reconnect.') |
| 287 | + raise FileUploadError( |
| 288 | + 'Something went wrong, ' |
| 289 | + 'Zenodo deposit not created.') |
| 290 | + |
| 291 | + dep_data = deposit.json() |
| 292 | + zenodo_bucket_url = dep_data['links']['bucket'] |
| 293 | + zenodo_depid = dep_data['id'] |
| 294 | + |
| 295 | + # TODO: fix with serializers |
| 296 | + zenodo_deposit = { |
| 297 | + 'id': zenodo_depid, |
| 298 | + 'links': { |
| 299 | + 'self': dep_data['links']['self'], |
| 300 | + 'bucket': zenodo_bucket_url, |
| 301 | + 'html': dep_data['links']['html'], |
| 302 | + 'publish': dep_data['links']['publish'], |
| 303 | + }, |
| 304 | + 'files': [] |
| 305 | + } |
| 306 | + self.setdefault('_zenodo', []).append(zenodo_deposit) |
| 307 | + self.commit() |
| 308 | + |
| 309 | + # upload files to zenodo deposit |
| 310 | + upload_to_zenodo.delay( |
| 311 | + record_uuid, files, bucket, token, zenodo_depid, zenodo_bucket_url) # noqa |
| 312 | + else: |
| 313 | + raise FileUploadError( |
| 314 | + 'You cannot create an empty Zenodo deposit. ' |
| 315 | + 'Please add some files.') |
| 316 | + else: |
| 317 | + webhook = data.get('webhook', False) |
| 318 | + event_type = data.get('event_type', 'release') |
264 | 319 |
|
265 | | - try: |
266 | | - host, owner, repo, branch, filepath = parse_git_url(url) |
267 | | - api = create_git_api(host, owner, repo, branch, |
268 | | - current_user.id) |
| 320 | + try: |
| 321 | + url = data['url'] |
| 322 | + except KeyError: |
| 323 | + raise FileUploadError('Missing url parameter.') |
269 | 324 |
|
270 | | - if filepath: |
271 | | - if webhook: |
272 | | - raise FileUploadError( |
273 | | - 'You cannot create a webhook on a file') |
| 325 | + try: |
| 326 | + host, owner, repo, branch, filepath = parse_git_url(url) # noqa |
| 327 | + api = create_git_api(host, owner, repo, branch, |
| 328 | + current_user.id) |
274 | 329 |
|
275 | | - download_repo_file( |
276 | | - record_uuid, |
277 | | - f'repositories/{host}/{owner}/{repo}/{api.branch or api.sha}/{filepath}', # noqa |
278 | | - *api.get_file_download(filepath), |
279 | | - api.auth_headers, |
280 | | - ) |
281 | | - elif webhook: |
282 | | - if event_type == 'release': |
283 | | - if branch: |
| 330 | + if filepath: |
| 331 | + if webhook: |
284 | 332 | raise FileUploadError( |
285 | | - 'You cannot create a release webhook' |
286 | | - ' for a specific branch or sha.') |
287 | | - |
288 | | - if event_type == 'push' and \ |
289 | | - api.branch is None and api.sha: |
290 | | - raise FileUploadError( |
291 | | - 'You cannot create a push webhook' |
292 | | - ' for a specific sha.') |
| 333 | + 'You cannot create a webhook on a file') |
| 334 | + |
| 335 | + download_repo_file( |
| 336 | + record_uuid, |
| 337 | + f'repositories/{host}/{owner}/{repo}/{api.branch or api.sha}/{filepath}', # noqa |
| 338 | + *api.get_file_download(filepath), |
| 339 | + api.auth_headers, |
| 340 | + ) |
| 341 | + elif webhook: |
| 342 | + if event_type == 'release': |
| 343 | + if branch: |
| 344 | + raise FileUploadError( |
| 345 | + 'You cannot create a release webhook' |
| 346 | + ' for a specific branch or sha.') |
| 347 | + |
| 348 | + if event_type == 'push' and \ |
| 349 | + api.branch is None and api.sha: |
| 350 | + raise FileUploadError( |
| 351 | + 'You cannot create a push webhook' |
| 352 | + ' for a specific sha.') |
293 | 353 |
|
294 | | - create_webhook(record_uuid, api, event_type) |
295 | | - else: |
296 | | - download_repo.delay( |
297 | | - record_uuid, |
298 | | - f'repositories/{host}/{owner}/{repo}/{api.branch or api.sha}.tar.gz', # noqa |
299 | | - api.get_repo_download(), |
300 | | - api.auth_headers) |
| 354 | + create_webhook(record_uuid, api, event_type) |
| 355 | + else: |
| 356 | + download_repo.delay( |
| 357 | + record_uuid, |
| 358 | + f'repositories/{host}/{owner}/{repo}/{api.branch or api.sha}.tar.gz', # noqa |
| 359 | + api.get_repo_download(), |
| 360 | + api.auth_headers) |
301 | 361 |
|
302 | | - except GitError as e: |
303 | | - raise FileUploadError(str(e)) |
| 362 | + except GitError as e: |
| 363 | + raise FileUploadError(str(e)) |
304 | 364 |
|
305 | 365 | return self |
306 | 366 |
|
@@ -584,16 +644,15 @@ def validate(self, **kwargs): |
584 | 644 |
|
585 | 645 | validator = NoRequiredValidator(schema, resolver=resolver) |
586 | 646 |
|
587 | | - result = {} |
588 | | - result['errors'] = [ |
| 647 | + errors = [ |
589 | 648 | FieldError( |
590 | 649 | list(error.path)+error.validator_value, |
591 | 650 | str(error.message)) |
592 | 651 | for error in validator.iter_errors(self) |
593 | 652 | ] |
594 | 653 |
|
595 | | - if result['errors']: |
596 | | - raise DepositValidationError(None, errors=result['errors']) |
| 654 | + if errors: |
| 655 | + raise DepositValidationError(None, errors=errors) |
597 | 656 | except RefResolutionError: |
598 | 657 | raise DepositValidationError('Schema {} not found.'.format( |
599 | 658 | self['$schema'])) |
|
0 commit comments