def delete(cls, id, account, dry_run=False): # as long as authentication (in the layer above) has been successful, and the account exists, then # we are good to proceed if account is None: raise Api401Error() applicationService = DOAJ.applicationService() authService = DOAJ.authorisationService() if dry_run: application, _ = applicationService.application(id) if application is not None: try: authService.can_edit_application(account, application) except AuthoriseException as e: if e.reason == e.WRONG_STATUS: raise Api403Error() raise Api404Error() else: raise Api404Error() else: try: applicationService.delete_application(id, account) except AuthoriseException as e: if e.reason == e.WRONG_STATUS: raise Api403Error() raise Api404Error() except NoSuchObjectException as e: raise Api404Error()
def retrieve(cls, id, account): # is the article id valid? ar = models.Article.pull(id) if ar is None: raise Api404Error() # at this point we're happy to return the article if it's # meant to be seen by the public if ar.is_in_doaj(): try: return OutgoingArticleDO.from_model(ar) except: raise Api500Error() # as long as authentication (in the layer above) has been successful, and the account exists, then # we are good to proceed if account is None or account.is_anonymous: raise Api401Error() # Check we're allowed to retrieve this article articleService = DOAJ.articleService() if not articleService.is_legitimate_owner(ar, account.id): raise Api404Error() # not found for this account # Return the article oa = OutgoingArticleDO.from_model(ar) return oa
def retrieve(cls, jid, account): # is the journal id valid try: j = models.Journal.pull(jid) except Exception as e: raise Api400Error(str(e)) if j is None: raise Api404Error() # at this point we're happy to return the journal if it's # meant to be seen by the public if j.is_in_doaj(): return OutgoingJournal.from_model(j) # as long as authentication (in the layer above) has been successful, and the account exists, then # we are good to proceed if account is None: raise Api401Error() # this journal's metadata is not currently published in DOAJ, so # we need to check ownership # is the current account the owner of the journal # if not we raise a 404 because that id does not exist for that user account. if account.is_anonymous or j.owner != account.id: raise Api404Error() return OutgoingJournal.from_model(j)
def retrieve(cls, id, account): # as long as authentication (in the layer above) has been successful, and the account exists, then # we are good to proceed if account is None: raise Api401Error() # is the application id valid ap = models.Suggestion.pull(id) if ap is None: raise Api404Error() # is the current account the owner of the application # if not we raise a 404 because that id does not exist for that user account. if ap.owner != account.id: raise Api404Error() # if we get to here we're going to give the user back the application oa = OutgoingApplication.from_model(ap) return oa
def delete(cls, id, account, dry_run=False): # as long as authentication (in the layer above) has been successful, and the account exists, then # we are good to proceed if account is None: raise Api401Error() # now see if there's something for us to delete ar = models.Article.pull(id) if ar is None: raise Api404Error() # Check we're allowed to retrieve this article articleService = DOAJ.articleService() if not articleService.is_legitimate_owner(ar, account.id): raise Api404Error() # not found for this account # issue the delete (no record of the delete required) if not dry_run: ar.delete()
def update(cls, id, data, account): # as long as authentication (in the layer above) has been successful, and the account exists, then # we are good to proceed if account is None: raise Api401Error() # now see if there's something for us to delete ar = models.Article.pull(id) if ar is None: raise Api404Error() # Check we're allowed to edit this article articleService = DOAJ.articleService() if not articleService.is_legitimate_owner(ar, account.id): raise Api404Error() # not found for this account # next thing to do is a structural validation of the replacement data, by instantiating the object try: ia = IncomingArticleDO(data) except dataobj.DataStructureException as e: raise Api400Error(str(e)) # if that works, convert it to an Article object bringing over everything outside the # incoming article from the original article new_ar = ia.to_article_model(ar) # we need to ensure that any properties of the existing article that aren't allowed to change # are copied over new_ar.set_id(id) new_ar.set_created(ar.created_date) new_ar.bibjson().set_subjects(ar.bibjson().subjects()) new_ar = cls.__handle_journal_info(new_ar) # finally save the new article, and return to the caller new_ar.save() return new_ar
def create(cls, data, account, dry_run=False): # as long as authentication (in the layer above) has been successful, and the account exists, then # we are good to proceed if account is None: raise Api401Error() # first thing to do is a structural validation, but instantiating the data object try: ia = IncomingApplication(data) except dataobj.DataStructureException as e: raise Api400Error(e.message) # if that works, convert it to a Suggestion object ap = ia.to_application_model() # now augment the suggestion object with all the additional information it requires # # suggester name and email from the user account ap.set_suggester(account.name, account.email) # they are not allowed to set "subject" ap.bibjson().remove_subjects() # if this is an update request on an existing journal if ap.current_journal is not None: # DOAJ BLL for this request applicationService = DOAJ.applicationService() # load the update_request application either directly or by crosswalking the journal object vanilla_ap = None jlock = None alock = None try: vanilla_ap, jlock, alock = applicationService.update_request_for_journal( ap.current_journal, account=account) except AuthoriseException as e: if e.reason == AuthoriseException.WRONG_STATUS: raise Api403Error( "The application is no longer in a state in which it can be edited via the API" ) else: raise Api404Error() except lock.Locked as e: raise Api409Error( "The application you are requesting an update for is locked for editing by another user" ) # if we didn't find an application or journal, 404 the user if vanilla_ap is None: if jlock is not None: jlock.delete() if alock is not None: alock.delete() raise Api404Error() # convert the incoming application into the web form form = MultiDict(xwalk.SuggestionFormXWalk.obj2form(ap)) fc = formcontext.ApplicationFormFactory.get_form_context( role="publisher", form_data=form, source=vanilla_ap) if fc.validate(): try: save_target = not dry_run fc.finalise(save_target=save_target, email_alert=False) return fc.target except formcontext.FormContextException as e: raise Api400Error(e.message) finally: if jlock is not None: jlock.delete() if alock is not None: alock.delete() else: if jlock is not None: jlock.delete() if alock is not None: alock.delete() raise Api400Error(cls._validation_message(fc)) # otherwise, this is a brand-new application else: # convert the incoming application into the web form form = MultiDict(xwalk.SuggestionFormXWalk.obj2form(ap)) # create a template that will hold all the values we want to persist across the form submission template = models.Suggestion() template.set_owner(account.id) fc = formcontext.ApplicationFormFactory.get_form_context( form_data=form, source=template) if fc.validate(): try: save_target = not dry_run fc.finalise(save_target=save_target, email_alert=False) return fc.target except formcontext.FormContextException as e: raise Api400Error(e.message) else: raise Api400Error(cls._validation_message(fc))
def update(cls, id, data, account): # as long as authentication (in the layer above) has been successful, and the account exists, then # we are good to proceed if account is None: raise Api401Error() # next thing to do is a structural validation of the replacement data, by instantiating the object try: ia = IncomingApplication(data) except dataobj.DataStructureException as e: raise Api400Error(e.message) # now see if there's something for us to update ap = models.Suggestion.pull(id) if ap is None: raise Api404Error() # if that works, convert it to a Suggestion object new_ap = ia.to_application_model() # now augment the suggestion object with all the additional information it requires # # suggester name and email from the user account new_ap.set_suggester(account.name, account.email) # they are not allowed to set "subject" new_ap.bibjson().remove_subjects() # DOAJ BLL for this request applicationService = DOAJ.applicationService() authService = DOAJ.authorisationService() # if a current_journal is specified on the incoming data if new_ap.current_journal is not None: # once an application has a current_journal specified, you can't change it if new_ap.current_journal != ap.current_journal: raise Api400Error( "current_journal cannot be changed once set. current_journal is {x}; this request tried to change it to {y}" .format(x=ap.current_journal, y=new_ap.current_journal)) # load the update_request application either directly or by crosswalking the journal object vanilla_ap = None jlock = None alock = None try: vanilla_ap, jlock, alock = applicationService.update_request_for_journal( new_ap.current_journal, account=account) except AuthoriseException as e: if e.reason == AuthoriseException.WRONG_STATUS: raise Api403Error( "The application is no longer in a state in which it can be edited via the API" ) else: raise Api404Error() except lock.Locked as e: raise Api409Error( "The application is locked for editing by another user - most likely your application is being reviewed by an editor" ) # if we didn't find an application or journal, 404 the user if vanilla_ap is None: if jlock is not None: jlock.delete() if alock is not None: alock.delete() raise Api404Error() # convert the incoming application into the web form form = MultiDict(xwalk.SuggestionFormXWalk.obj2form(new_ap)) fc = formcontext.ApplicationFormFactory.get_form_context( role="publisher", form_data=form, source=vanilla_ap) if fc.validate(): try: fc.finalise(email_alert=False) return fc.target except formcontext.FormContextException as e: raise Api400Error(e.message) finally: if jlock is not None: jlock.delete() if alock is not None: alock.delete() else: if jlock is not None: jlock.delete() if alock is not None: alock.delete() raise Api400Error(cls._validation_message(fc)) else: try: authService.can_edit_application(account, ap) except AuthoriseException as e: if e.reason == e.WRONG_STATUS: raise Api403Error( "The application is no longer in a state in which it can be edited via the API" ) else: raise Api404Error() # convert the incoming application into the web form form = MultiDict(xwalk.SuggestionFormXWalk.obj2form(new_ap)) fc = formcontext.ApplicationFormFactory.get_form_context( form_data=form, source=ap) if fc.validate(): try: fc.finalise(email_alert=False) return fc.target except formcontext.FormContextException as e: raise Api400Error(e.message) else: raise Api400Error(cls._validation_message(fc))
def missing_resource(invalid_path): docs_url = app.config.get("BASE_URL", "") + url_for('.docs') spec_url = app.config.get("BASE_URL", "") + url_for('.api_spec') raise Api404Error("No endpoint at {0}. See {1} for valid paths or read the documentation at {2}.".format(invalid_path, spec_url, docs_url))