-
Notifications
You must be signed in to change notification settings - Fork 336
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/files-on-anything' of https://github.com/Center…
…ForOpenScience/osf.io into feature/node-preprint
- Loading branch information
Showing
132 changed files
with
3,631 additions
and
644 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# -*- coding: utf-8 -*- | ||
import hmac | ||
import hashlib | ||
|
||
from rest_framework import permissions | ||
from rest_framework import exceptions | ||
|
||
from framework import sentry | ||
from website import settings | ||
|
||
|
||
class RequestComesFromMailgun(permissions.BasePermission): | ||
"""Verify that request comes from Mailgun. | ||
Adapted here from conferences/message.py | ||
Signature comparisons as recomended from mailgun docs: | ||
https://documentation.mailgun.com/en/latest/user_manual.html#webhooks | ||
""" | ||
def has_permission(self, request, view): | ||
if request.method != 'POST': | ||
raise exceptions.MethodNotAllowed(method=request.method) | ||
data = request.data | ||
if not data: | ||
raise exceptions.ParseError('Request body is empty') | ||
if not settings.MAILGUN_API_KEY: | ||
return False | ||
signature = hmac.new( | ||
key=settings.MAILGUN_API_KEY, | ||
msg='{}{}'.format( | ||
data['timestamp'], | ||
data['token'], | ||
), | ||
digestmod=hashlib.sha256, | ||
).hexdigest() | ||
if 'signature' not in data: | ||
error_message = 'Signature required in request body' | ||
sentry.log_message(error_message) | ||
raise exceptions.ParseError(error_message) | ||
if not hmac.compare_digest(unicode(signature), unicode(data['signature'])): | ||
raise exceptions.ParseError('Invalid signature') | ||
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from django.conf.urls import url | ||
|
||
from api.crossref import views | ||
|
||
app_name = 'osf' | ||
|
||
urlpatterns = [ | ||
url(r'^email/$', views.ParseCrossRefConfirmation.as_view(), name=views.ParseCrossRefConfirmation.view_name), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import logging | ||
|
||
import lxml.etree | ||
from django.http import HttpResponse | ||
from django.views.decorators.csrf import csrf_exempt | ||
from rest_framework.views import APIView | ||
|
||
from api.crossref.permissions import RequestComesFromMailgun | ||
from framework.auth.views import mails | ||
from osf.models import Preprint | ||
from website import settings | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class ParseCrossRefConfirmation(APIView): | ||
# This view goes under the _/ namespace | ||
view_name = 'parse_crossref_confirmation_email' | ||
view_category = 'identifiers' | ||
|
||
permission_classes = ( | ||
RequestComesFromMailgun, | ||
) | ||
|
||
@csrf_exempt | ||
def dispatch(self, request, *args, **kwargs): | ||
return super(ParseCrossRefConfirmation, self).dispatch(request, *args, **kwargs) | ||
|
||
def get_serializer_class(self): | ||
return None | ||
|
||
def post(self, request): | ||
crossref_email_content = lxml.etree.fromstring(str(request.POST['body-plain'])) | ||
status = crossref_email_content.get('status').lower() # from element doi_batch_diagnostic | ||
record_count = int(crossref_email_content.find('batch_data/record_count').text) | ||
records = crossref_email_content.xpath('//record_diagnostic') | ||
dois_processed = 0 | ||
|
||
if status == 'completed': | ||
guids = [] | ||
# Keep track of errors recieved, ignore those that are handled | ||
unexpected_errors = False | ||
for record in records: | ||
doi = getattr(record.find('doi'), 'text', None) | ||
guid = doi.split('/')[-1] if doi else None | ||
guids.append(guid) | ||
preprint = Preprint.load(guid) if guid else None | ||
if record.get('status').lower() == 'success' and doi: | ||
msg = record.find('msg').text | ||
created = bool(msg == 'Successfully added') | ||
legacy_doi = preprint.get_identifier(category='legacy_doi') | ||
if created or legacy_doi: | ||
# Sets preprint_doi_created and saves the preprint | ||
preprint.set_identifier_values(doi=doi, save=True) | ||
# Double records returned when possible matching DOI is found in crossref | ||
elif 'possible preprint/vor pair' not in msg.lower(): | ||
# Directly updates the identifier | ||
preprint.set_identifier_value(category='doi', value=doi) | ||
|
||
dois_processed += 1 | ||
|
||
# Mark legacy DOIs overwritten by newly batch confirmed crossref DOIs | ||
if legacy_doi: | ||
legacy_doi.remove() | ||
|
||
elif record.get('status').lower() == 'failure': | ||
if 'Relation target DOI does not exist' in record.find('msg').text: | ||
logger.warn('Related publication DOI does not exist, sending metadata again without it...') | ||
client = preprint.get_doi_client() | ||
client.create_identifier(preprint, category='doi', include_relation=False) | ||
else: | ||
unexpected_errors = True | ||
logger.info('Creation success email received from CrossRef for preprints: {}'.format(guids)) | ||
|
||
if dois_processed != record_count or status != 'completed': | ||
if unexpected_errors: | ||
batch_id = crossref_email_content.find('batch_id').text | ||
mails.send_mail( | ||
to_addr=settings.OSF_SUPPORT_EMAIL, | ||
mail=mails.CROSSREF_ERROR, | ||
batch_id=batch_id, | ||
email_content=request.POST['body-plain'], | ||
) | ||
logger.error('Error submitting metadata for batch_id {} with CrossRef, email sent to help desk'.format(batch_id)) | ||
|
||
return HttpResponse('Mail received', status=200) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.