|
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