Exemplo n.º 1
0
    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()
Exemplo n.º 2
0
    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()
Exemplo n.º 3
0
def update_request_readonly(application_id):
    # DOAJ BLL for this request
    applicationService = DOAJ.applicationService()
    authService = DOAJ.authorisationService()

    application, _ = applicationService.application(application_id)
    try:
        authService.can_view_application(current_user._get_current_object(),
                                         application)
    except AuthoriseException as e:
        abort(404)

    fc = formcontext.ApplicationFormFactory.get_form_context(
        role="update_request_readonly", source=application)
    return fc.render_template(no_sidebar=True)
 def setUp(self):
     super(TestBLLArticleBatchCreateArticle, self).setUp()
     self.svc = DOAJ.articleService()
     self._is_legitimate_owner = self.svc.is_legitimate_owner
     self._get_duplicate = self.svc.get_duplicate
     self._issn_ownership_status = self.svc.issn_ownership_status
     self._get_journal = Article.get_journal
Exemplo n.º 5
0
def metadata():
    # if this is a get request, give the blank form - there is no edit feature
    if request.method == "GET":
        form = ArticleForm()
        return render_template('publisher/metadata.html', form=form)

    # if this is a post request, a form button has been hit and we need to do
    # a bunch of work
    elif request.method == "POST":
        form = ArticleForm(request.form)

        # first we need to do any server-side form modifications which
        # the user might request by pressing the add/remove authors buttons
        more_authors = request.values.get("more_authors")
        remove_author = None
        for v in request.values.keys():
            if v.startswith("remove_authors"):
                remove_author = v.split("-")[1]

        # if the user wants more authors, add an extra entry
        if more_authors:
            form.authors.append_entry()
            return render_template('publisher/metadata.html', form=form)

        # if the user wants to remove an author, do the various back-flips required
        if remove_author is not None:
            keep = []
            while len(form.authors.entries) > 0:
                entry = form.authors.pop_entry()
                if entry.short_name == "authors-" + remove_author:
                    break
                else:
                    keep.append(entry)
            while len(keep) > 0:
                form.authors.append_entry(keep.pop().data)
            return render_template('publisher/metadata.html', form=form)

        # if we get to here, then this is the full submission, and we need to
        # validate and return
        enough_authors = _validate_authors(form)
        if form.validate():
            # if the form validates, then we have to do our own bit of validation,
            # which is to check that there is at least one author supplied
            if not enough_authors:
                return render_template('publisher/metadata.html',
                                       form=form,
                                       author_error=True)
            else:
                xwalk = ArticleFormXWalk()
                art = xwalk.crosswalk_form(form)
                articleService = DOAJ.articleService()
                articleService.create_article(
                    art, current_user._get_current_object())
                flash("Article created/updated", "success")
                form = ArticleForm()
                return render_template('publisher/metadata.html', form=form)
        else:
            return render_template('publisher/metadata.html',
                                   form=form,
                                   author_error=not enough_authors)
 def setUp(self):
     super(TestBLLArticleBatchCreateArticle, self).setUp()
     self.svc = DOAJ.articleService()
     self._is_legitimate_owner = self.svc.is_legitimate_owner
     self._get_duplicate = self.svc.get_duplicate
     self._issn_ownership_status = self.svc.issn_ownership_status
     self._get_journal = Article.get_journal
Exemplo n.º 7
0
    def test_02_get_application(self, name, application, application_id, account, lock_application, raises=None):
        if lock_application:
            lock.lock(constants.LOCK_APPLICATION, application.id, "someoneelse", blocking=True)

        svc = DOAJ.applicationService()

        if application is not None:
            application.save(blocking=True)

        if raises is not None:
            with self.assertRaises(raises):
                if account is None:
                    retrieved, _ = svc.application(application_id)
                else:
                    retrieved, jlock = svc.application(application_id, lock_application=True, lock_account=account)
        else:
            if account is None:
                retrieved, _ = svc.application(application_id)
                if retrieved is not None:
                    assert retrieved.data == application.data
                else:
                    assert retrieved is None
            else:
                retrieved, jlock = svc.application(application_id, lock_application=True, lock_account=account)
                if retrieved is not None:
                    assert retrieved.data == application.data
                else:
                    assert retrieved is None

                time.sleep(2)

                assert lock.has_lock(constants.LOCK_APPLICATION, application_id, account.id)
Exemplo n.º 8
0
    def test_01_get_journal(self, name, journal, journal_id, account, lock_journal, raises=None):

        if lock_journal:
            lock.lock("journal", journal.id, "someoneelse", blocking=True)

        svc = DOAJ.journalService()

        if journal is not None:
            journal.save(blocking=True)

        if raises is not None:
            with self.assertRaises(raises):
                if account is None:
                    retrieved, _ = svc.journal(journal_id)
                else:
                    retrieved, jlock = svc.journal(journal_id, lock_journal=True, lock_account=account)
        else:
            if account is None:
                retrieved, _ = svc.journal(journal_id)
                if retrieved is not None:
                    assert retrieved.data == journal.data
                else:
                    assert retrieved is None
            else:
                retrieved, jlock = svc.journal(journal_id, lock_journal=True, lock_account=account)
                if retrieved is not None:
                    assert retrieved.data == journal.data
                else:
                    assert retrieved is None

                time.sleep(2)

                assert lock.has_lock("journal", journal_id, account.id)
 def setUp(self):
     super(TestBLLPrepareUpdatePublisher, self).setUp()
     self.svc = DOAJ.articleService()
     self.is_id_updated = self.svc._doi_or_fulltext_updated
     self.has_permission = self.svc.has_permissions
     self.merge = Article.merge
     acc_source = AccountFixtureFactory.make_publisher_source()
     self.publisher = Account(**acc_source)
Exemplo n.º 10
0
 def test_01_create_update_request(self, name, journal, account, raises=None, expected=None):
     svc = DOAJ.authorisationService()
     if raises is not None:
         with self.assertRaises(raises):
             svc.can_create_update_request(account, journal)
     elif expected is not None:
         assert svc.can_create_update_request(account, journal) is expected
     else:
         assert False, "Specify either raises or expected"
Exemplo n.º 11
0
 def setUp(self):
     super(TestBLLArticleCreateArticle, self).setUp()
     self.svc = DOAJ.articleService()
     self.is_legitimate_owner = self.svc.is_legitimate_owner
     self.ownership = self.svc.issn_ownership_status
     self.duplicate = self.svc.get_duplicate
     self.permission = self.svc.has_permissions
     self.prepare_update_admin = self.svc._prepare_update_admin
     self.prepare_update_publisher = self.svc._prepare_update_publisher
Exemplo n.º 12
0
 def test_02_edit_update_request(self, name, application, account, raises=None, expected=None):
     svc = DOAJ.authorisationService()
     if raises is not None:
         with self.assertRaises(raises):
             svc.can_edit_application(account, application)
     elif expected is not None:
         assert svc.can_edit_application(account, application) is expected
     else:
         assert False, "Specify either raises or expected"
Exemplo n.º 13
0
 def test_01_journal_2_application(self, name, journal, account, raises=None, comparator=None):
     svc = DOAJ.journalService()
     if raises is not None:
         with self.assertRaises(raises):
             svc.journal_2_application(journal, account)
     elif comparator is not None:
         application = svc.journal_2_application(journal, account)
         comparator(journal, application)
     else:
         assert False, "Specify either raises or comparator"
Exemplo n.º 14
0
    def test_03_view_application(self,
                                 name,
                                 account_type,
                                 role,
                                 owner,
                                 application_type,
                                 raises=None,
                                 returns=None,
                                 auth_reason=None):
        # set up the objects
        application = None
        if application_type == "exists":
            application = Suggestion(
                **ApplicationFixtureFactory.make_application_source())

        account = None
        if account_type == "exists":
            if role == "none":
                account = Account(
                    **AccountFixtureFactory.make_publisher_source())
                account.remove_role("publisher")
            elif role == "publisher":
                account = Account(
                    **AccountFixtureFactory.make_publisher_source())
            elif role == "admin":
                account = Account(
                    **AccountFixtureFactory.make_managing_editor_source())

            if owner == "yes":
                application.set_owner(account.id)

        svc = DOAJ.authorisationService()
        if raises is not None and raises != "":
            exception = None
            with self.assertRaises(EXCEPTIONS[raises]):
                try:
                    svc.can_view_application(account, application)
                except Exception as e:
                    exception = e
                    raise e
            if raises == "AuthoriseException":
                if auth_reason == "not_owner":
                    assert exception.reason == exception.NOT_OWNER
                elif auth_reason == "wrong_role":
                    assert exception.reason == exception.WRONG_ROLE

        elif returns is not None:
            expected = returns == "true"
            assert svc.can_view_application(account, application) is expected
        else:
            assert False, "Specify either raises or returns"
Exemplo n.º 15
0
 def test_02_edit_update_request(self,
                                 name,
                                 application,
                                 account,
                                 raises=None,
                                 expected=None):
     svc = DOAJ.authorisationService()
     if raises is not None:
         with self.assertRaises(raises):
             svc.can_edit_application(account, application)
     elif expected is not None:
         assert svc.can_edit_application(account, application) is expected
     else:
         assert False, "Specify either raises or expected"
Exemplo n.º 16
0
 def test_01_create_update_request(self,
                                   name,
                                   journal,
                                   account,
                                   raises=None,
                                   expected=None):
     svc = DOAJ.authorisationService()
     if raises is not None:
         with self.assertRaises(raises):
             svc.can_create_update_request(account, journal)
     elif expected is not None:
         assert svc.can_create_update_request(account, journal) is expected
     else:
         assert False, "Specify either raises or expected"
Exemplo n.º 17
0
 def test_01_journal_2_application(self,
                                   name,
                                   journal,
                                   account,
                                   raises=None,
                                   comparator=None):
     svc = DOAJ.journalService()
     if raises is not None:
         with self.assertRaises(raises):
             svc.journal_2_application(journal, account)
     elif comparator is not None:
         application = svc.journal_2_application(journal, account)
         comparator(journal, application)
     else:
         assert False, "Specify either raises or comparator"
Exemplo n.º 18
0
    def setUp(self):
        super(TestBLLJournalCSV, self).setUp()
        self.svc = DOAJ.journalService()

        self.store_tmp_dir = app.config["STORE_TMP_DIR"]
        app.config["STORE_TMP_DIR"] = os.path.join("test_store", "tmp")
        self.store_local_dir = app.config["STORE_LOCAL_DIR"]
        app.config["STORE_LOCAL_DIR"] = os.path.join("test_store", "main")

        self.localStore = store.StoreLocal(None)
        self.tmpStore = store.TempStore()
        self.container_id = app.config.get("STORE_CACHE_CONTAINER")
        self.store_tmp_impl = app.config["STORE_TMP_IMPL"]
        self.store_impl = app.config["STORE_IMPL"]

        self.cache = models.cache.Cache
        models.cache.Cache = ModelCacheMockFactory.in_memory()
        models.Cache = models.cache.Cache
Exemplo n.º 19
0
    def setUp(self):
        super(TestBLLJournalCSV, self).setUp()
        self.svc = DOAJ.journalService()

        self.store_tmp_dir = app.config["STORE_TMP_DIR"]
        app.config["STORE_TMP_DIR"] = os.path.join("test_store", "tmp")
        self.store_local_dir = app.config["STORE_LOCAL_DIR"]
        app.config["STORE_LOCAL_DIR"] = os.path.join("test_store", "main")

        self.localStore = store.StoreLocal(None)
        self.tmpStore = store.TempStore()
        self.container_id = app.config.get("STORE_CACHE_CONTAINER")
        self.store_tmp_impl = app.config["STORE_TMP_IMPL"]
        self.store_impl = app.config["STORE_IMPL"]

        self.cache = models.cache.Cache
        models.cache.Cache = ModelCacheMockFactory.in_memory()
        models.Cache = models.cache.Cache
Exemplo n.º 20
0
    def create(cls, articles, account):
        # We run through the articles once, validating in dry-run mode
        # and deduplicating as we go. Then we .save() everything once
        # we know all incoming articles are valid.

        # 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()

        # convert the data into a suitable article models
        articles = [ArticlesCrudApi.prep_article(data) for data in articles]

        articleService = DOAJ.articleService()
        try:
            result = articleService.batch_create_articles(articles, account, add_journal_info=True)
            return [a.id for a in articles]
        except exceptions.IngestException as e:
            raise Api400Error(e.message)
Exemplo n.º 21
0
    def create(cls, articles, account):
        # We run through the articles once, validating in dry-run mode
        # and deduplicating as we go. Then we .save() everything once
        # we know all incoming articles are valid.

        # 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()

        # convert the data into a suitable article models
        articles = [ArticlesCrudApi.prep_article(data) for data in articles]

        articleService = DOAJ.articleService()
        try:
            result = articleService.batch_create_articles(articles, account)
            return [a.id for a in articles]
        except exceptions.IngestException as e:
            raise Api400Error(e.message)
Exemplo n.º 22
0
    def test_03_view_application(self, name, account_type, role, owner, application_type, raises=None, returns=None, auth_reason=None):
        # set up the objects
        application = None
        if application_type == "exists":
            application = Suggestion(**ApplicationFixtureFactory.make_application_source())

        account = None
        if account_type == "exists":
            if role == "none":
                account = Account(**AccountFixtureFactory.make_publisher_source())
                account.remove_role("publisher")
            elif role == "publisher":
                account = Account(**AccountFixtureFactory.make_publisher_source())
            elif role == "admin":
                account = Account(**AccountFixtureFactory.make_managing_editor_source())

            if owner == "yes":
                application.set_owner(account.id)


        svc = DOAJ.authorisationService()
        if raises is not None and raises != "":
            exception = None
            with self.assertRaises(EXCEPTIONS[raises]):
                try:
                    svc.can_view_application(account, application)
                except Exception as e:
                    exception = e
                    raise e
            if raises == "AuthoriseException":
                if auth_reason == "not_owner":
                    assert exception.reason == exception.NOT_OWNER
                elif auth_reason == "wrong_role":
                    assert exception.reason == exception.WRONG_ROLE

        elif returns is not None:
            expected = returns == "true"
            assert svc.can_view_application(account, application) is expected
        else:
            assert False, "Specify either raises or returns"
    def test_01_discover_duplicates(self, name, kwargs):

        article_arg = kwargs.get("article")
        owner_arg = kwargs.get("owner")
        article_doi_arg = kwargs.get("article_doi")
        doi_duplicate_arg = kwargs.get("doi_duplicate")
        article_fulltext_arg = kwargs.get("article_fulltext")
        fulltext_duplicate_arg = kwargs.get("fulltext_duplicate")
        articles_by_doi_arg = kwargs.get("articles_by_doi")
        articles_by_fulltext_arg = kwargs.get("articles_by_fulltext")
        raises_arg = kwargs.get("raises")

        raises = EXCEPTIONS.get(raises_arg)

        ###############################################
        ## set up

        owner = None
        if owner_arg != "none":
            owner = Account(**AccountFixtureFactory.make_publisher_source())

        owner_id = None
        if owner is not None:
            owner_id = owner.id

        # create a journal for the owner
        if owner_arg not in ["none"]:
            source = JournalFixtureFactory.make_journal_source(in_doaj=True)
            journal = Journal(**source)
            journal.set_owner(owner.id)
            journal.bibjson().remove_identifiers()
            journal.bibjson().add_identifier("eissn", "1234-5678")
            journal.bibjson().add_identifier("pissn", "9876-5432")
            journal.save(blocking=True)

        # determine what we need to load into the index
        article_ids = []
        aids_block = []
        if owner_arg not in ["none", "no_articles"]:
            for i, ident in enumerate(IDENTS):
                the_doi = ident["doi"]
                if doi_duplicate_arg == "padded":
                    the_doi = "  " + the_doi + "  "
                elif doi_duplicate_arg == "prefixed":
                    the_doi = "https://dx.doi.org/" + the_doi

                the_fulltext = ident["fulltext"]
                if article_fulltext_arg != "invalid":
                    if fulltext_duplicate_arg == "padded":
                        the_fulltext = "  http:" + the_fulltext
                    elif fulltext_duplicate_arg == "http":
                        the_fulltext = "http:" + the_fulltext
                    elif fulltext_duplicate_arg == "https":
                        the_fulltext = "https:" + the_fulltext
                    else:
                        the_fulltext = "http:" + the_fulltext

                source = ArticleFixtureFactory.make_article_source(eissn="1234-5678", pissn="9876-5432", doi=the_doi, fulltext=the_fulltext)
                article = Article(**source)
                article.set_id()
                article.save()
                article_ids.append(article.id)
                aids_block.append((article.id, article.last_updated))

        # generate our incoming article
        article = None
        doi = None
        fulltext = None
        if article_arg == "yes":
            eissn = "1234=5678" # one matching
            pissn = "6789-1234" # the other not - issn matches are not relevant to this test

            if article_doi_arg in ["yes", "padded"]:
                doi = "10.1234/abc/11"
                if doi_duplicate_arg in ["yes", "padded"]:
                    doi = IDENTS[0]["doi"]
                if article_doi_arg == "padded":
                    doi = "  doi:" + doi + "  "
            elif article_doi_arg in ["invalid"]:
                doi = IDENTS[-1]["doi"]

            if article_fulltext_arg in ["yes", "padded", "https"]:
                fulltext = "//example.com/11"
                if fulltext_duplicate_arg in ["yes", "padded", "https"]:
                    fulltext = IDENTS[0]["fulltext"]
                if fulltext_duplicate_arg == "padded":
                    fulltext = "  http:" + fulltext + "  "
                elif fulltext_duplicate_arg == "https":
                    fulltext = "https:" + fulltext
                else:
                    fulltext = "http:" + fulltext
            elif article_fulltext_arg == "invalid":
                fulltext = IDENTS[-1]["fulltext"]

            source = ArticleFixtureFactory.make_article_source(eissn=eissn, pissn=pissn, doi=doi, fulltext=fulltext)
            article = Article(**source)

            # we need to do this if doi or fulltext are none, because the factory will set a default if we don't
            # provide them
            if doi is None:
                article.bibjson().remove_identifiers("doi")
            if fulltext is None:
                article.bibjson().remove_urls("fulltext")

            article.set_id()

        Article.blockall(aids_block)

        ###########################################################
        # Execution

        svc = DOAJ.articleService()
        if raises is not None:
            with self.assertRaises(raises):
                svc.discover_duplicates(article, owner_id)
        else:
            possible_articles = svc.discover_duplicates(article, owner_id)

            if articles_by_doi_arg == "yes":
                assert "doi" in possible_articles
                assert len(possible_articles["doi"]) == 1
                # if this is the "invalid" doi, then we expect it to match the final article, otherwise match the first
                if article_doi_arg == "invalid":
                    assert possible_articles["doi"][0].id == article_ids[-1]
                else:
                    assert possible_articles["doi"][0].id == article_ids[0]
            else:
                if possible_articles is not None:
                    assert "doi" not in possible_articles

            if articles_by_fulltext_arg == "yes":
                assert "fulltext" in possible_articles
                assert len(possible_articles["fulltext"]) == 1
                # if this is the "invalid" fulltext url, then we expect it to match the final article, otherwise match the first
                if article_fulltext_arg == "invalid":
                    assert possible_articles["fulltext"][0].id == article_ids[-1]
                else:
                    assert possible_articles["fulltext"][0].id == article_ids[0]
            else:
                if possible_articles is not None:
                    assert "fulltext" not in possible_articles
Exemplo n.º 24
0
 def setUp(self):
     super(TestBLLPrepareUpdatePublisher, self).setUp()
     self.svc = DOAJ.articleService()
     self.is_id_updated = self.svc._doi_or_fulltext_updated
     self.merge = Article.merge
     self.pull = Article.pull
Exemplo n.º 25
0
    def test_01_is_legitimate_owner(self, name, kwargs):

        article_arg = kwargs.get("article")
        owner_arg = kwargs.get("owner")
        article_eissn_arg = kwargs.get("article_eissn")
        article_pissn_arg = kwargs.get("article_pissn")
        seen_eissn_arg = kwargs.get("seen_eissn")
        seen_pissn_arg = kwargs.get("seen_pissn")
        journal_owner_arg = kwargs.get("journal_owner")

        raises_arg = kwargs.get("raises")
        legit_arg = kwargs.get("legit")

        raises = EXCEPTIONS.get(raises_arg)

        ###############################################
        ## set up

        owner = None
        if owner_arg != "none":
            owner = Account(**AccountFixtureFactory.make_publisher_source())

        owner_id = None
        if owner is not None:
            owner_id = owner.id

        # generate our incoming article
        article = None
        eissn = None
        pissn = None
        if article_arg == "exists":
            source = ArticleFixtureFactory.make_article_source()
            article = Article(**source)
            article.set_id()

            article.bibjson().remove_identifiers("pissn")
            if article_pissn_arg == "yes":
                pissn = "1234-5678"
                article.bibjson().add_identifier("pissn", pissn)

            article.bibjson().remove_identifiers("eissn")
            if article_eissn_arg == "yes":
                eissn = "9876-5432"
                article.bibjson().add_identifier("eissn", eissn)

        # assemble the issns that will appear to be in the index.  One that is irrelevant, and just
        # serves to be "noise" in the database, and the other that matches the spec required by
        # the test
        issns = [("1111-1111", "2222-2222")]
        if eissn is not None and pissn is not None and seen_eissn_arg == "yes" and seen_pissn_arg == "yes":
            issns.append((eissn, pissn))
        if eissn is not None and seen_eissn_arg == "yes":
            issns.append((eissn, None))
        if pissn is not None and seen_pissn_arg == "yes":
            issns.append((None, pissn))

        owners = []
        if journal_owner_arg == "none":
            owners = [None]
        elif journal_owner_arg == "correct" and owner_id is not None:
            owners = [owner_id]
        elif journal_owner_arg == "incorrect":
            owners = ["randomowner"]
        elif journal_owner_arg == "mix" and owner_id is not None:
            owners.append(owner_id)
            owners.append("randomowner")
            owners.append(None)

        mock = ModelJournalMockFactory.find_by_issn(issns, owners)
        Journal.find_by_issn = mock

        ###########################################################
        # Execution

        svc = DOAJ.articleService()

        if raises is not None:
            with self.assertRaises(raises):
                svc.is_legitimate_owner(article, owner_id)
        else:
            legit = svc.is_legitimate_owner(article, owner_id)

            if legit_arg == "no":
                assert legit is False
            elif legit_arg == "yes":
                assert legit is True
Exemplo n.º 26
0
    def test_02_application_2_journal(self, name, application_type,
                                      manual_update_arg, app_key_properties,
                                      current_journal, raises):
        # set up for the test
        #########################################

        cj = None
        has_seal = bool(randint(0, 1))
        application = None
        if application_type == "present":
            application = Suggestion(
                **ApplicationFixtureFactory.make_application_source())
            application.set_id(application.makeid())
            application.remove_contacts()
            application.remove_editor_group()
            application.remove_editor()
            application.remove_owner()
            application.remove_current_journal()
            application.remove_notes()

            if app_key_properties == "yes":
                application.add_contact("Application",
                                        "*****@*****.**")
                application.set_editor_group("appeditorgroup")
                application.set_editor("appeditor")
                application.set_owner("appowner")

            application.set_seal(has_seal)
            application.add_note("Application Note")

            if current_journal == "present":
                journal = Journal(
                    **JournalFixtureFactory.make_journal_source())
                journal.remove_contacts()
                journal.add_contact("Journal", "*****@*****.**")
                journal.set_editor_group("journaleditorgroup")
                journal.set_editor("journaleditor")
                journal.set_owner("journalowner")
                journal.remove_current_application()
                journal.remove_notes()
                journal.add_note("Journal Note")
                journal.save(blocking=True)
                application.set_current_journal(journal.id)
                cj = journal
            elif current_journal == "missing":
                application.set_current_journal("123456789987654321")

        manual_update = None
        if manual_update_arg == "true":
            manual_update = True
        elif manual_update_arg == "false":
            manual_update = False

        # execute the test
        ########################################

        svc = DOAJ.applicationService()
        if raises is not None and raises != "":
            with self.assertRaises(EXCEPTIONS[raises]):
                svc.application_2_journal(application, manual_update)
        else:
            journal = svc.application_2_journal(application, manual_update)

            # check the result
            ######################################

            assert journal is not None
            assert isinstance(journal, Journal)
            assert journal.is_in_doaj() is True

            jbj = journal.bibjson().data
            del jbj["active"]
            assert jbj == application.bibjson().data

            if current_journal == "present":
                assert len(journal.related_applications) == 3
            else:
                assert len(journal.related_applications) == 1
            related = journal.related_application_record(application.id)
            assert related is not None

            if manual_update_arg == "true":
                assert journal.last_manual_update is not None and journal.last_manual_update != "1970-01-01T00:00:00Z"

            if app_key_properties == "yes":
                contacts = journal.contacts()
                assert len(contacts) == 1
                assert contacts[0].get("name") == "Application"
                assert contacts[0].get("email") == "*****@*****.**"
                assert journal.editor_group == "appeditorgroup"
                assert journal.editor == "appeditor"
                assert journal.owner == "appowner"
                assert journal.has_seal() == has_seal

                if current_journal == "present":
                    assert len(journal.notes) == 2
                else:
                    assert len(journal.notes) == 1

            elif app_key_properties == "no":
                if current_journal == "present":
                    contacts = journal.contacts()
                    assert len(contacts) == 1
                    assert contacts[0].get("name") == "Journal"
                    assert contacts[0].get("email") == "*****@*****.**"
                    assert journal.editor_group == "journaleditorgroup"
                    assert journal.editor == "journaleditor"
                    assert journal.owner == "journalowner"
                    assert journal.has_seal() == has_seal
                    assert len(journal.notes) == 2

                elif current_journal == "none" or current_journal == "missing":
                    contacts = journal.contacts()
                    assert len(contacts) == 0
                    assert journal.editor_group is None
                    assert journal.editor is None
                    assert journal.owner is None
                    assert journal.has_seal() == has_seal
                    assert len(journal.notes) == 1

            if current_journal == "present":
                assert cj.id == journal.id
                assert cj.created_date == journal.created_date
Exemplo n.º 27
0
    def test_01_reject_application(self,
                                   name,
                                   application,
                                   application_status,
                                   account,
                                   prov,
                                   current_journal,
                                   note,
                                   save,
                                   raises=None):

        #######################################
        ## set up

        if save == "fail":
            Suggestion.save = mock_save_fail

        ap = None
        journal = None
        if application == "exists":
            ap = Suggestion(
                **ApplicationFixtureFactory.make_application_source())
            ap.set_application_status(application_status)
            ap.set_id(ap.makeid())
            ap.remove_notes()
            if current_journal == "yes":
                journal = Journal(**JournalFixtureFactory.make_journal_source(
                    in_doaj=True))
                journal.set_id(journal.makeid())
                journal.set_current_application(ap.id)
                journal.save(blocking=True)
                ap.set_current_journal(journal.id)
            else:
                ap.remove_current_journal()

        acc = None
        if account == "publisher":
            acc = Account(**AccountFixtureFactory.make_publisher_source())
        elif account == "admin":
            acc = Account(
                **AccountFixtureFactory.make_managing_editor_source())

        provenance = None
        if prov != "none":
            provenance = prov == "true"

        thenote = None
        if note == "yes":
            thenote = "abcdefg"

        ########################################
        ## execute

        svc = DOAJ.applicationService()
        if raises is not None and raises != "":
            with self.assertRaises(EXCEPTIONS[raises]):
                svc.reject_application(ap, acc, provenance, note=thenote)
        else:
            svc.reject_application(ap, acc, provenance, note=thenote)
            time.sleep(1)

            #######################################
            ## Check

            ap2 = Suggestion.pull(ap.id)
            assert ap2 is not None
            assert ap2.application_status == constants.APPLICATION_STATUS_REJECTED
            assert ap2.current_journal is None

            # check the updated and manually updated date are essentially the same (they can theoretically differ
            # by a small amount just based on when they are set)
            updated_spread = abs(
                (ap2.last_updated_timestamp -
                 ap2.last_manual_update_timestamp).total_seconds())
            assert updated_spread <= 1.0

            if current_journal == "yes" and journal is not None:
                j2 = Journal.pull(journal.id)
                assert j2 is not None
                assert j2.current_application is None
                assert ap2.related_journal == j2.id

            if prov == "true":
                pr = Provenance.get_latest_by_resource_id(ap.id)
                assert pr is not None

            if note == "yes":
                assert len(ap2.notes) == 1
                assert ap2.notes[0].get("note") == "abcdefg"
            elif note == "no":
                assert len(ap2.notes) == 0
Exemplo n.º 28
0
def update_request(journal_id):
    # DOAJ BLL for this request
    journalService = DOAJ.journalService()
    applicationService = DOAJ.applicationService()

    # if this is a delete request, deal with it first and separately from the below logic
    if request.method == "DELETE":
        journal, _ = journalService.journal(journal_id)
        application_id = journal.current_application
        if application_id is not None:
            applicationService.delete_application(
                application_id, current_user._get_current_object())
        else:
            abort(404)
        return ""

    # load the application either directly or by crosswalking the journal object
    application = None
    jlock = None
    alock = None
    try:
        application, jlock, alock = applicationService.update_request_for_journal(
            journal_id, account=current_user._get_current_object())
    except AuthoriseException as e:
        if e.reason == AuthoriseException.WRONG_STATUS:
            journal, _ = journalService.journal(journal_id)
            return render_template(
                "publisher/application_already_submitted.html",
                journal=journal)
        else:
            abort(404)
    except lock.Locked as e:
        journal, _ = journalService.journal(journal_id)
        return render_template("publisher/locked.html",
                               journal=journal,
                               lock=e.lock)

    # if we didn't find an application or journal, 404 the user
    if application is None:
        if jlock is not None: jlock.delete()
        if alock is not None: alock.delete()
        abort(404)

    # if we have a live application and cancel was hit, then cancel the operation and redirect
    # first determine if this is a cancel request on the form
    cancelled = request.values.get("cancel")
    if cancelled is not None:
        if jlock is not None: jlock.delete()
        if alock is not None: alock.delete()
        return redirect(url_for("publisher.updates_in_progress"))

    # if we are requesting the page with a GET, we just want to show the form
    if request.method == "GET":
        fc = formcontext.ApplicationFormFactory.get_form_context(
            role="publisher", source=application)
        return fc.render_template(edit_suggestion_page=True)

    # if we are requesting the page with a POST, we need to accept the data and handle it
    elif request.method == "POST":
        fc = formcontext.ApplicationFormFactory.get_form_context(
            role="publisher", form_data=request.form, source=application)
        if fc.validate():
            try:
                fc.finalise()
                Messages.flash(Messages.APPLICATION_UPDATE_SUBMITTED_FLASH)
                for a in fc.alert:
                    Messages.flash_with_url(a, "success")
                return redirect(url_for("publisher.updates_in_progress"))
            except formcontext.FormContextException as e:
                Messages.flash(e.message)
                return redirect(
                    url_for("publisher.update_request",
                            journal_id=journal_id,
                            _anchor='cannot_edit'))
            finally:
                if jlock is not None: jlock.delete()
                if alock is not None: alock.delete()
        else:
            return fc.render_template(edit_suggestion_page=True)
Exemplo n.º 29
0
    def test_01_delete_application(self, name, application_type, account_type,
                                   current_journal, related_journal, raises):

        ###############################################
        ## set up

        # create the test application (if needed), and the associated current_journal and related_journal in suitable states
        application = None
        cj = None
        rj = None
        if application_type == "found" or application_type == "locked":
            application = Suggestion(
                **ApplicationFixtureFactory.make_application_source())

            if current_journal == "none":
                application.remove_current_journal()
            elif current_journal == "not_found":
                application.set_current_journal("123456789987654321")
            elif current_journal == "found":
                cj = Journal(**JournalFixtureFactory.make_journal_source())
                cj.set_id(cj.makeid())
                cj.save(blocking=True)
                application.set_current_journal(cj.id)
            elif current_journal == "locked":
                cj = Journal(**JournalFixtureFactory.make_journal_source())
                cj.set_id(cj.makeid())
                cj.save(blocking=True)
                application.set_current_journal(cj.id)
                lock.lock(constants.LOCK_JOURNAL, cj.id, "otheruser")

            if related_journal == "none":
                application.remove_related_journal()
            elif related_journal == "not_found":
                application.set_related_journal("123456789987654321")
            elif related_journal == "found":
                rj = Journal(**JournalFixtureFactory.make_journal_source())
                rj.set_id(rj.makeid())
                rj.save(blocking=True)
                application.set_related_journal(rj.id)
            elif related_journal == "locked":
                rj = Journal(**JournalFixtureFactory.make_journal_source())
                rj.set_id(rj.makeid())
                rj.save(blocking=True)
                application.set_related_journal(rj.id)
                lock.lock(constants.LOCK_JOURNAL, rj.id, "otheruser")

        acc = None
        if account_type != "none":
            acc = Account(**AccountFixtureFactory.make_publisher_source())
            if account_type == "not_permitted":
                acc.remove_role("publisher")
            if application_type == "locked":
                thelock = lock.lock(constants.LOCK_APPLICATION, application.id,
                                    "otheruser")
                # we can't explicitly block on the lock, but we can halt until we confirm it is saved
                thelock.blockall([(thelock.id, thelock.last_updated)])

        application_id = None
        if application is not None:
            if acc is not None:
                application.set_owner(acc.id)
            application.save(blocking=True)
            application_id = application.id
        elif application_type == "not_found":
            application_id = "sdjfasofwefkwflkajdfasjd"

        ###########################################################
        # Execution

        svc = DOAJ.applicationService()
        if raises != "":
            with self.assertRaises(EXCEPTIONS[raises]):
                svc.delete_application(application_id, acc)
            time.sleep(1)
            check_locks(application, cj, rj, acc)
        else:
            svc.delete_application(application_id, acc)

            # we need to sleep, so the index catches up
            time.sleep(1)

            # check that no locks remain set for this user
            check_locks(application, cj, rj, acc)

            # check that the application actually is gone
            if application is not None:
                assert Suggestion.pull(application.id) is None

            # check that the current journal no longer has a reference to the application
            if cj is not None:
                cj = Journal.pull(cj.id)
                assert cj.current_application is None

            # check that the related journal has a record that the application was deleted
            if rj is not None:
                rj = Journal.pull(rj.id)
                record = rj.related_application_record(application.id)
                assert "status" in record
                assert record["status"] == "deleted"
Exemplo n.º 30
0
    def _process(self, file_upload):
        job = self.background_job
        upload_dir = app.config.get("UPLOAD_DIR")
        path = os.path.join(upload_dir, file_upload.local_filename)

        if not os.path.exists(path):
            job.add_audit_message(
                u"File not found at path {} . Retrying job later.".format(
                    path))
            count = self.get_param(job.params, "attempts")
            retry_limit = app.config.get("HUEY_TASKS",
                                         {}).get("ingest_articles",
                                                 {}).get("retries", 0)
            self.set_param(job.params, "attempts", count + 1)

            if retry_limit <= count:
                job.add_audit_message(
                    u"File still not found at path {} . Giving up.".format(
                        path))
                job.fail()

            raise RetryException()

        job.add_audit_message(u"Importing from {x}".format(x=path))

        articleService = DOAJ.articleService()
        account = models.Account.pull(file_upload.owner)

        xwalk_name = app.config.get("ARTICLE_CROSSWALKS",
                                    {}).get(file_upload.schema)
        xwalk = plugin.load_class(xwalk_name)()

        ingest_exception = False
        result = {}
        try:
            with open(path) as handle:
                articles = xwalk.crosswalk_file(
                    handle, add_journal_info=False
                )  # don't import the journal info, as we haven't validated ownership of the ISSNs in the article yet
                for article in articles:
                    article.set_upload_id(file_upload.id)
                result = articleService.batch_create_articles(
                    articles, account, add_journal_info=True)
        except IngestException as e:
            job.add_audit_message(
                u"IngestException: {msg}. Inner message: {inner}.  Stack: {x}".
                format(msg=e.message, inner=e.inner_message, x=e.trace()))
            file_upload.failed(e.message, e.inner_message)
            result = e.result
            try:
                file_failed(path)
                ingest_exception = True
            except:
                job.add_audit_message(
                    u"Error cleaning up file which caused IngestException: {x}"
                    .format(x=traceback.format_exc()))
        except (DuplicateArticleException, ArticleNotAcceptable) as e:
            job.add_audit_message(
                u"One or more articles did not contain either a DOI or a Fulltext URL"
            )
            file_upload.failed(
                u"One or more articles did not contain either a DOI or a Fulltext URL"
            )
            try:
                file_failed(path)
            except:
                job.add_audit_message(
                    u"Error cleaning up file which caused Exception: {x}".
                    format(x=traceback.format_exc()))
                return
        except Exception as e:
            job.add_audit_message(
                u"Unanticipated error: {x}".format(x=traceback.format_exc()))
            file_upload.failed("Unanticipated error when importing articles")
            try:
                file_failed(path)
            except:
                job.add_audit_message(
                    u"Error cleaning up file which caused Exception: {x}".
                    format(x=traceback.format_exc()))
                return

        success = result.get("success", 0)
        fail = result.get("fail", 0)
        update = result.get("update", 0)
        new = result.get("new", 0)
        shared = result.get("shared", [])
        unowned = result.get("unowned", [])
        unmatched = result.get("unmatched", [])

        if success == 0 and fail > 0 and not ingest_exception:
            file_upload.failed("All articles in file failed to import")
            job.add_audit_message("All articles in file failed to import")
        if success > 0 and fail == 0:
            file_upload.processed(success, update, new)
        if success > 0 and fail > 0:
            file_upload.partial(success, fail, update, new)
            job.add_audit_message(
                "Some articles in file failed to import correctly, so no articles imported"
            )

        file_upload.set_failure_reasons(list(shared), list(unowned),
                                        list(unmatched))
        job.add_audit_message("Shared ISSNs: " + ", ".join(list(shared)))
        job.add_audit_message("Unowned ISSNs: " + ", ".join(list(unowned)))
        job.add_audit_message("Unmatched ISSNs: " + ", ".join(list(unmatched)))

        if not ingest_exception:
            try:
                os.remove(path)  # just remove the file, no need to keep it
            except Exception as e:
                job.add_audit_message(
                    u"Error while deleting file {x}: {y}".format(x=path,
                                                                 y=e.message))
Exemplo n.º 31
0
    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))
Exemplo n.º 32
0
    def test_01_reject_application(self, name, application, application_status, account, prov, current_journal, note, save, raises=None):

        #######################################
        ## set up

        if save == "fail":
            Suggestion.save = mock_save_fail

        ap = None
        journal = None
        if application == "exists":
            ap = Suggestion(**ApplicationFixtureFactory.make_application_source())
            ap.set_application_status(application_status)
            ap.set_id(ap.makeid())
            ap.remove_notes()
            if current_journal == "yes":
                journal = Journal(**JournalFixtureFactory.make_journal_source(in_doaj=True))
                journal.set_id(journal.makeid())
                journal.set_current_application(ap.id)
                journal.save(blocking=True)
                ap.set_current_journal(journal.id)
            else:
                ap.remove_current_journal()

        acc = None
        if account == "publisher":
            acc = Account(**AccountFixtureFactory.make_publisher_source())
        elif account == "admin":
            acc = Account(**AccountFixtureFactory.make_managing_editor_source())

        provenance = None
        if prov != "none":
            provenance = prov == "true"

        thenote = None
        if note == "yes":
            thenote = "abcdefg"

        ########################################
        ## execute

        svc = DOAJ.applicationService()
        if raises is not None and raises != "":
            with self.assertRaises(EXCEPTIONS[raises]):
                svc.reject_application(ap, acc, provenance, note=thenote)
        else:
            svc.reject_application(ap, acc, provenance, note=thenote)
            time.sleep(1)

            #######################################
            ## Check

            ap2 = Suggestion.pull(ap.id)
            assert ap2 is not None
            assert ap2.application_status == constants.APPLICATION_STATUS_REJECTED
            assert ap2.current_journal is None

            # check the updated and manually updated date are essentially the same (they can theoretically differ
            # by a small amount just based on when they are set)
            updated_spread = abs((ap2.last_updated_timestamp - ap2.last_manual_update_timestamp).total_seconds())
            assert updated_spread <= 1.0

            if current_journal == "yes" and journal is not None:
                j2 = Journal.pull(journal.id)
                assert j2 is not None
                assert j2.current_application is None
                assert ap2.related_journal == j2.id

            if prov == "true":
                pr = Provenance.get_latest_by_resource_id(ap.id)
                assert pr is not None

            if note == "yes":
                assert len(ap2.notes) == 1
                assert ap2.notes[0].get("note") == "abcdefg"
            elif note == "no":
                assert len(ap2.notes) == 0
Exemplo n.º 33
0
    def test_02_application_2_journal(self, name, application_type, manual_update_arg, app_key_properties, current_journal, raises):
        # set up for the test
        #########################################

        cj = None
        has_seal = bool(randint(0, 1))
        application = None
        if application_type == "present":
            application = Suggestion(**ApplicationFixtureFactory.make_application_source())
            application.set_id(application.makeid())
            application.remove_contacts()
            application.remove_editor_group()
            application.remove_editor()
            application.remove_owner()
            application.remove_current_journal()
            application.remove_notes()

            if app_key_properties == "yes":
                application.add_contact("Application", "*****@*****.**")
                application.set_editor_group("appeditorgroup")
                application.set_editor("appeditor")
                application.set_owner("appowner")

            application.set_seal(has_seal)
            application.add_note("Application Note")

            if current_journal == "present":
                journal = Journal(**JournalFixtureFactory.make_journal_source())
                journal.remove_contacts()
                journal.add_contact("Journal", "*****@*****.**")
                journal.set_editor_group("journaleditorgroup")
                journal.set_editor("journaleditor")
                journal.set_owner("journalowner")
                journal.remove_current_application()
                journal.remove_notes()
                journal.add_note("Journal Note")
                journal.save(blocking=True)
                application.set_current_journal(journal.id)
                cj = journal
            elif current_journal == "missing":
                application.set_current_journal("123456789987654321")

        manual_update = None
        if manual_update_arg == "true":
            manual_update = True
        elif manual_update_arg == "false":
            manual_update = False

        # execute the test
        ########################################

        svc = DOAJ.applicationService()
        if raises is not None and raises != "":
            with self.assertRaises(EXCEPTIONS[raises]):
                svc.application_2_journal(application, manual_update)
        else:
            journal = svc.application_2_journal(application, manual_update)

            # check the result
            ######################################

            assert journal is not None
            assert isinstance(journal, Journal)
            assert journal.is_in_doaj() is True

            jbj = journal.bibjson().data
            del jbj["active"]
            assert jbj == application.bibjson().data

            if current_journal == "present":
                assert len(journal.related_applications) == 3
            else:
                assert len(journal.related_applications) == 1
            related = journal.related_application_record(application.id)
            assert related is not None

            if manual_update_arg == "true":
                assert journal.last_manual_update is not None and journal.last_manual_update != "1970-01-01T00:00:00Z"

            if app_key_properties == "yes":
                contacts = journal.contacts()
                assert len(contacts) == 1
                assert contacts[0].get("name") == "Application"
                assert contacts[0].get("email") == "*****@*****.**"
                assert journal.editor_group == "appeditorgroup"
                assert journal.editor == "appeditor"
                assert journal.owner == "appowner"
                assert journal.has_seal() == has_seal

                if current_journal == "present":
                    assert len(journal.notes) == 2
                else:
                    assert len(journal.notes) == 1

            elif app_key_properties == "no":
                if current_journal == "present":
                    contacts = journal.contacts()
                    assert len(contacts) == 1
                    assert contacts[0].get("name") == "Journal"
                    assert contacts[0].get("email") == "*****@*****.**"
                    assert journal.editor_group == "journaleditorgroup"
                    assert journal.editor == "journaleditor"
                    assert journal.owner == "journalowner"
                    assert journal.has_seal() == has_seal
                    assert len(journal.notes) == 2

                elif current_journal == "none" or current_journal == "missing":
                    contacts = journal.contacts()
                    assert len(contacts) == 0
                    assert journal.editor_group is None
                    assert journal.editor is None
                    assert journal.owner is None
                    assert journal.has_seal() == has_seal
                    assert len(journal.notes) == 1

            if current_journal == "present":
                assert cj.id == journal.id
                assert cj.created_date == journal.created_date
    def test_01_accept_application(self, name, application_type, account_type, manual_update, provenance, raises, result_provenance, result_manual_update):

        ###############################################
        ## set up

        # create the application
        application = None
        if application_type == "save_fail":
            application = Suggestion(**ApplicationFixtureFactory.make_application_source())
            application.save = mock_save
            Journal.save = mock_save
        elif application_type == "with_current_journal":
            application = Suggestion(**ApplicationFixtureFactory.make_application_source())
            application.remove_notes()
            application.add_note("unique 1", "2002-01-01T00:00:00Z")
            application.add_note("duplicate", "2001-01-01T00:00:00Z")
            cj = application.current_journal
            journal = Journal(**JournalFixtureFactory.make_journal_source())
            journal.set_id(cj)
            journal.remove_notes()
            journal.add_note("unique 2", "2003-01-01T00:00:00Z")
            journal.add_note("duplicate", "2001-01-01T00:00:00Z")
            journal.save(blocking=True)
        elif application_type == "no_current_journal":
            application = Suggestion(**ApplicationFixtureFactory.make_application_source())
            application.remove_current_journal()


        acc = None
        if account_type == "not_allowed":
            acc = Account(**AccountFixtureFactory.make_publisher_source())
        elif account_type == "allowed":
            acc = Account(**AccountFixtureFactory.make_managing_editor_source())

        mu = None
        if manual_update in ["true", "false"]:
            mu = manual_update == "true"

        prov = None
        if provenance in ["true", "false"]:
            prov = provenance == "true"

        save = bool(randint(0,1))

        ###########################################################
        # Execution

        svc = DOAJ.applicationService()
        if raises != "":
            with self.assertRaises(EXCEPTIONS[raises]):
                svc.accept_application(application, acc, mu, prov)
        else:
            journal = svc.accept_application(application, acc, mu, prov, save_journal=save, save_application=save)

            # we need to sleep, so the index catches up
            time.sleep(1)

            # check a few common things
            assert application.application_status == constants.APPLICATION_STATUS_ACCEPTED
            assert application.current_journal is None
            assert journal.current_application is None
            assert application.related_journal == journal.id

            related = journal.related_applications
            if application_type == "with_current_journal":
                assert len(related) == 3
            elif application_type == "no_current_journal":
                assert len(related) == 1
            assert related[0].get("application_id") == application.id
            assert related[0].get("date_accepted") is not None

            if result_manual_update == "yes":
                assert journal.last_manual_update is not None
                assert journal.last_manual_update != "1970-01-01T00:00:00Z"
                assert application.last_manual_update is not None
                assert application.last_manual_update != "1970-01-01T00:00:00Z"
            elif result_manual_update == "no":
                assert journal.last_manual_update is None
                assert application.last_manual_update is None

            if application_type == "with_current_journal":
                assert len(journal.notes) == 3
                notevals = [note.get("note") for note in journal.notes]
                assert "duplicate" in notevals
                assert "unique 1" in notevals
                assert "unique 2" in notevals

            app_prov = Provenance.get_latest_by_resource_id(application.id)
            if result_provenance == "yes":
                assert app_prov is not None
            elif result_provenance == "no":
                assert app_prov is None

            if save:
                pass
Exemplo n.º 35
0
    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))
Exemplo n.º 36
0
    def test_01_discover_duplicates(self, name, kwargs):

        article_arg = kwargs.get("article")
        owner_arg = kwargs.get("owner")
        article_doi_arg = kwargs.get("article_doi")
        doi_duplicate_arg = kwargs.get("doi_duplicate")
        article_fulltext_arg = kwargs.get("article_fulltext")
        fulltext_duplicate_arg = kwargs.get("fulltext_duplicate")
        articles_by_doi_arg = kwargs.get("articles_by_doi")
        articles_by_fulltext_arg = kwargs.get("articles_by_fulltext")
        raises_arg = kwargs.get("raises")

        raises = EXCEPTIONS.get(raises_arg)

        ###############################################
        ## set up

        owner = None
        if owner_arg != "none":
            owner = Account(**AccountFixtureFactory.make_publisher_source())

        owner_id = None
        if owner is not None:
            owner_id = owner.id

        # create a journal for the owner
        if owner_arg not in ["none"]:
            source = JournalFixtureFactory.make_journal_source(in_doaj=True)
            journal = Journal(**source)
            journal.set_owner(owner.id)
            journal.bibjson().remove_identifiers()
            journal.bibjson().add_identifier("eissn", "1234-5678")
            journal.bibjson().add_identifier("pissn", "9876-5432")
            journal.save()

        # determine what we need to load into the index
        article_ids = []
        aids_block = []
        if owner_arg not in ["none", "no_articles"]:
            for i, ident in enumerate(IDENTS):
                the_doi = ident["doi"]
                if doi_duplicate_arg == "padded":
                    the_doi = "  " + the_doi + "  "
                elif doi_duplicate_arg == "prefixed":
                    the_doi = "https://dx.doi.org/" + the_doi

                the_fulltext = ident["fulltext"]
                if article_fulltext_arg != "invalid":
                    if fulltext_duplicate_arg == "padded":
                        the_fulltext = "  http:" + the_fulltext
                    elif fulltext_duplicate_arg == "http":
                        the_fulltext = "http:" + the_fulltext
                    elif fulltext_duplicate_arg == "https":
                        the_fulltext = "https:" + the_fulltext
                    else:
                        the_fulltext = "http:" + the_fulltext

                source = ArticleFixtureFactory.make_article_source(
                    eissn="1234-5678",
                    pissn="9876-5432",
                    doi=the_doi,
                    fulltext=the_fulltext)
                article = Article(**source)
                article.set_id()
                article.save(blocking=True)
                article_ids.append(article.id)
                aids_block.append((article.id, article.last_updated))

        # generate our incoming article
        article = None
        doi = None
        fulltext = None
        if article_arg == "yes":
            eissn = "1234=5678"  # one matching
            pissn = "6789-1234"  # the other not - issn matches are not relevant to this test

            if article_doi_arg in ["yes", "padded"]:
                doi = "10.1234/abc/11"
                if doi_duplicate_arg in ["yes", "padded"]:
                    doi = IDENTS[0]["doi"]
                if article_doi_arg == "padded":
                    doi = "  doi:" + doi + "  "
            elif article_doi_arg in ["invalid"]:
                doi = IDENTS[-1]["doi"]

            if article_fulltext_arg in ["yes", "padded", "https"]:
                fulltext = "//example.com/11"
                if fulltext_duplicate_arg in ["yes", "padded", "https"]:
                    fulltext = IDENTS[0]["fulltext"]
                if fulltext_duplicate_arg == "padded":
                    fulltext = "  http:" + fulltext + "  "
                elif fulltext_duplicate_arg == "https":
                    fulltext = "https:" + fulltext
                else:
                    fulltext = "http:" + fulltext
            elif article_fulltext_arg == "invalid":
                fulltext = IDENTS[-1]["fulltext"]

            source = ArticleFixtureFactory.make_article_source(
                eissn=eissn, pissn=pissn, doi=doi, fulltext=fulltext)
            article = Article(**source)

            # we need to do this if doi or fulltext are none, because the factory will set a default if we don't
            # provide them
            if doi is None:
                article.bibjson().remove_identifiers("doi")
            if fulltext is None:
                article.bibjson().remove_urls("fulltext")

            article.set_id()

        Article.blockall(aids_block)

        ###########################################################
        # Execution

        svc = DOAJ.articleService()
        if raises is not None:
            with self.assertRaises(raises):
                svc.discover_duplicates(article)
        else:
            possible_articles = svc.discover_duplicates(article)

            if articles_by_doi_arg == "yes":
                assert "doi" in possible_articles
                assert len(possible_articles["doi"]) == 1
                # if this is the "invalid" doi, then we expect it to match the final article, otherwise match the first
                if article_doi_arg == "invalid":
                    assert possible_articles["doi"][0].id == article_ids[-1]
                else:
                    assert possible_articles["doi"][0].id == article_ids[0]
            else:
                if possible_articles is not None:
                    assert "doi" not in possible_articles

            if articles_by_fulltext_arg == "yes":
                assert "fulltext" in possible_articles
                assert len(possible_articles["fulltext"]) == 1
                # if this is the "invalid" fulltext url, then we expect it to match the final article, otherwise match the first
                if article_fulltext_arg == "invalid":
                    assert possible_articles["fulltext"][0].id == article_ids[
                        -1]
                else:
                    assert possible_articles["fulltext"][0].id == article_ids[
                        0]
            else:
                if possible_articles is not None:
                    assert "fulltext" not in possible_articles
 def setUp(self):
     super(TestBLLArticleGetDuplicates, self).setUp()
     self.svc = DOAJ.articleService()
     self._old_discover_duplicates = self.svc.discover_duplicates
Exemplo n.º 38
0
    def test_01_delete_application(self, name, application_type, account_type, current_journal, related_journal, raises):

        ###############################################
        ## set up

        # create the test application (if needed), and the associated current_journal and related_journal in suitable states
        application = None
        cj = None
        rj = None
        if application_type == "found" or application_type == "locked":
            application = Suggestion(**ApplicationFixtureFactory.make_application_source())

            if current_journal == "none":
                application.remove_current_journal()
            elif current_journal == "not_found":
                application.set_current_journal("123456789987654321")
            elif current_journal == "found":
                cj = Journal(**JournalFixtureFactory.make_journal_source())
                cj.set_id(cj.makeid())
                cj.save(blocking=True)
                application.set_current_journal(cj.id)
            elif current_journal == "locked":
                cj = Journal(**JournalFixtureFactory.make_journal_source())
                cj.set_id(cj.makeid())
                cj.save(blocking=True)
                application.set_current_journal(cj.id)
                lock.lock(constants.LOCK_JOURNAL, cj.id, "otheruser")

            if related_journal == "none":
                application.remove_related_journal()
            elif related_journal == "not_found":
                application.set_related_journal("123456789987654321")
            elif related_journal == "found":
                rj = Journal(**JournalFixtureFactory.make_journal_source())
                rj.set_id(rj.makeid())
                rj.save(blocking=True)
                application.set_related_journal(rj.id)
            elif related_journal == "locked":
                rj = Journal(**JournalFixtureFactory.make_journal_source())
                rj.set_id(rj.makeid())
                rj.save(blocking=True)
                application.set_related_journal(rj.id)
                lock.lock(constants.LOCK_JOURNAL, rj.id, "otheruser")


        acc = None
        if account_type != "none":
            acc = Account(**AccountFixtureFactory.make_publisher_source())
            if account_type == "not_permitted":
                acc.remove_role("publisher")
            if application_type == "locked":
                thelock = lock.lock(constants.LOCK_APPLICATION, application.id, "otheruser")
                # we can't explicitly block on the lock, but we can halt until we confirm it is saved
                thelock.blockall([(thelock.id, thelock.last_updated)])

        application_id = None
        if application is not None:
            if acc is not None:
                application.set_owner(acc.id)
            application.save(blocking=True)
            application_id = application.id
        elif application_type == "not_found":
            application_id = u"sdjfasofwefkwflkajdfasjd"

        ###########################################################
        # Execution

        svc = DOAJ.applicationService()
        if raises != "":
            with self.assertRaises(EXCEPTIONS[raises]):
                svc.delete_application(application_id, acc)
            time.sleep(1)
            check_locks(application, cj, rj, acc)
        else:
            svc.delete_application(application_id, acc)

            # we need to sleep, so the index catches up
            time.sleep(1)

            # check that no locks remain set for this user
            check_locks(application, cj, rj, acc)

            # check that the application actually is gone
            if application is not None:
                assert Suggestion.pull(application.id) is None

            # check that the current journal no longer has a reference to the application
            if cj is not None:
                cj = Journal.pull(cj.id)
                assert cj.current_application is None

            # check that the related journal has a record that the application was deleted
            if rj is not None:
                rj = Journal.pull(rj.id)
                record = rj.related_application_record(application.id)
                assert "status" in record
                assert record["status"] == "deleted"
    def test_01_issn_ownership_status(self, name, kwargs):

        article_arg = kwargs.get("article")
        owner_arg = kwargs.get("owner")
        article_eissn_arg = kwargs.get("article_eissn")
        article_pissn_arg = kwargs.get("article_pissn")
        seen_eissn_arg = kwargs.get("seen_eissn")
        seen_pissn_arg = kwargs.get("seen_pissn")
        journal_owner_arg = kwargs.get("journal_owner")

        raises_arg = kwargs.get("raises")

        raises = EXCEPTIONS.get(raises_arg)

        ###############################################
        ## set up

        owner = None
        if owner_arg != "none":
            owner = Account(**AccountFixtureFactory.make_publisher_source())

        owner_id = None
        if owner is not None:
            owner_id = owner.id

        # generate our incoming article
        article = None
        eissn = None
        pissn = None
        if article_arg == "exists":
            source = ArticleFixtureFactory.make_article_source()
            article = Article(**source)
            article.set_id()

            article.bibjson().remove_identifiers("pissn")
            if article_pissn_arg == "yes":
                pissn = "1234-5678"
                article.bibjson().add_identifier("pissn", pissn)

            article.bibjson().remove_identifiers("eissn")
            if article_eissn_arg == "yes":
                eissn = "9876-5432"
                article.bibjson().add_identifier("eissn", eissn)

        issns = []
        if eissn is not None and pissn is not None and seen_eissn_arg == "yes" and seen_pissn_arg == "yes":
            issns.append((eissn, pissn))
        if eissn is not None and seen_eissn_arg == "yes":
            issns.append((eissn, "4321-9876"))
            issns.append((eissn, None))
        if pissn is not None and seen_pissn_arg == "yes":
            issns.append(("6789-4321", pissn))
            issns.append((None, pissn))

        owners = []
        if journal_owner_arg == "none":
            owners = [None]
        elif journal_owner_arg == "correct" and owner_id is not None:
            owners = [owner_id]
        elif journal_owner_arg == "incorrect":
            owners = ["randomowner"]
        elif journal_owner_arg == "mix" and owner_id is not None:
            owners.append(owner_id)
            owners.append("randomowner")
            owners.append(None)

        mock = ModelJournalMockFactory.find_by_issn(issns, owners)
        Journal.find_by_issn = mock

        ###########################################################
        # Execution

        svc = DOAJ.articleService()

        if raises is not None:
            with self.assertRaises(raises):
                svc.issn_ownership_status(article, owner_id)
        else:
            owned, shared, unowned, unmatched = svc.issn_ownership_status(
                article, owner_id)

            owned_count = 0
            if seen_eissn_arg == "yes" and eissn is not None and journal_owner_arg in [
                    "correct"
            ]:
                assert eissn in owned
                owned_count += 1
            elif eissn is not None:
                assert eissn not in owned

            if seen_pissn_arg == "yes" and pissn is not None and journal_owner_arg in [
                    "correct"
            ]:
                assert pissn in owned
                owned_count += 1
            elif pissn is not None:
                assert pissn not in owned

            assert len(owned) == owned_count

            shared_count = 0
            if seen_eissn_arg == "yes" and eissn is not None and journal_owner_arg in [
                    "mix"
            ]:
                assert eissn in shared
                shared_count += 1
            elif eissn is not None:
                assert eissn not in shared

            if seen_pissn_arg == "yes" and pissn is not None and journal_owner_arg in [
                    "mix"
            ]:
                assert pissn in shared
                shared_count += 1
            elif pissn is not None:
                assert pissn not in shared

            assert len(shared) == shared_count

            unowned_count = 0
            if seen_eissn_arg == "yes" and eissn is not None and journal_owner_arg in [
                    "incorrect", "none"
            ]:
                assert eissn in unowned
                unowned_count += 1
            elif eissn is not None:
                assert eissn not in unowned

            if seen_pissn_arg == "yes" and pissn is not None and journal_owner_arg in [
                    "incorrect", "none"
            ]:
                assert pissn in unowned
                unowned_count += 1
            elif pissn is not None:
                assert pissn not in unowned

            assert len(unowned) == unowned_count

            unmatched_count = 0
            if seen_eissn_arg == "no" and eissn is not None:
                assert eissn in unmatched
                unmatched_count += 1
            elif eissn is not None:
                assert eissn not in unmatched

            if seen_pissn_arg == "no" and pissn is not None:
                assert pissn in unmatched
                unmatched_count += 1
            elif pissn is not None:
                assert pissn not in unmatched

            assert len(unmatched) == unmatched_count
Exemplo n.º 40
0
    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))
Exemplo n.º 41
0
    def test_01_update_request(self, name, journal_id, journal_lock, account,
                               account_role, account_is_owner,
                               current_applications, application_lock,
                               application_status, completed_applications,
                               raises, return_app, return_jlock, return_alock,
                               db_jlock, db_alock, db_app):

        ###############################################
        ## set up

        # create the journal
        journal = None
        jid = None
        if journal_id == "valid":
            journal = Journal(**JournalFixtureFactory.make_journal_source(
                in_doaj=True))
            journal.remove_related_applications()
            journal.remove_current_application()
            jid = journal.id
        elif journal_id == "not_in_doaj":
            journal = Journal(**JournalFixtureFactory.make_journal_source(
                in_doaj=False))
            journal.remove_related_applications()
            journal.remove_current_application()
            jid = journal.id
        elif journal_id == "missing":
            jid = uuid.uuid4().hex

        acc = None
        if account == "yes":
            acc = Account(**AccountFixtureFactory.make_publisher_source())
            if account_role == "none":
                acc.remove_role("publisher")
            elif account_role == "admin":
                acc.remove_role("publisher")
                acc.add_role("admin")
            acc.set_id(acc.makeid())
            if account_is_owner == "yes":
                acc.set_id(journal.owner)

        if journal_lock == "yes":
            lock.lock("journal", jid, "someoneelse", blocking=True)

        latest_app = None
        current_app_count = int(current_applications)
        for i in range(current_app_count):
            app = Suggestion(
                **ApplicationFixtureFactory.make_application_source())
            app.set_id(app.makeid())
            app.set_created("198" + str(i) + "-01-01T00:00:00Z")
            app.set_current_journal(jid)
            app.save()
            latest_app = app
            if journal is not None:
                journal.set_current_application(app.id)

        comp_app_count = int(completed_applications)
        for i in range(comp_app_count):
            app = Suggestion(
                **ApplicationFixtureFactory.make_application_source())
            app.set_id(app.makeid())
            app.set_created("197" + str(i) + "-01-01T00:00:00Z")
            app.set_related_journal(jid)
            app.save()
            if journal is not None:
                journal.add_related_application(app.id,
                                                date_accepted=app.created_date)

        if current_app_count == 0 and comp_app_count == 0:
            # save at least one record to initialise the index mapping, otherwise tests fail
            app = Suggestion(
                **ApplicationFixtureFactory.make_application_source())
            app.set_id(app.makeid())
            app.save()

        if application_lock == "yes":
            lock.lock("suggestion",
                      latest_app.id,
                      "someoneelse",
                      blocking=True)

        if application_status != "n/a":
            latest_app.set_application_status(application_status)
            latest_app.save(blocking=True)

        # finally save the journal record, ensuring we get a blocking save, so everything
        # above here should be synchronised with the repo
        if journal is not None:
            journal.save(blocking=True)

        ###########################################################
        # Execution

        svc = DOAJ.applicationService()
        if raises != "":
            with self.assertRaises(EXCEPTIONS[raises]):
                svc.update_request_for_journal(jid, acc)
        else:
            application, jlock, alock = svc.update_request_for_journal(
                jid, acc)

            # we need to sleep, so the index catches up
            time.sleep(1)

            if return_app == "none":
                assert application is None
            elif return_app == "yes":
                assert application is not None

            if return_jlock == "none":
                assert jlock is None
            elif return_jlock == "yes":
                assert jlock is not None

            if return_alock == "none":
                assert alock is None
            elif return_alock == "yes":
                assert alock is not None

            if db_jlock == "no" and acc is not None:
                assert not lock.has_lock("journal", jid, acc.id)
            elif db_jlock == "yes" and acc is not None:
                l = lock.has_lock("journal", jid, acc.id)
                assert lock.has_lock("journal", jid, acc.id)

            if db_alock == "no" and application.id is not None and acc is not None:
                assert not lock.has_lock("suggestion", application.id, acc.id)
            elif db_alock == "yes" and application.id is not None and acc is not None:
                assert lock.has_lock("suggestion", application.id, acc.id)

            if db_app == "no" and application.id is not None:
                indb = Suggestion.q2obj(q="id.exact:" + application.id)
                assert indb is None
            elif db_app == "yes" and application.id is not None:
                indb = Suggestion.q2obj(q="id.exact:" + application.id)
                assert indb is not None

            if current_app_count == 0 and comp_app_count == 0 and application is not None:
                assert application.article_metadata is None
                assert application.articles_last_year is None
            elif application is not None:
                assert application.article_metadata is not None
                assert application.articles_last_year is not None
Exemplo n.º 42
0
    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))
Exemplo n.º 43
0
    def test_01_update_request(self, name, journal_id, journal_lock,
                               account, account_role, account_is_owner,
                               current_applications, application_lock, application_status,
                               completed_applications, raises,
                               return_app, return_jlock, return_alock,
                               db_jlock, db_alock, db_app):

        ###############################################
        ## set up

        # create the journal
        journal = None
        jid = None
        if journal_id == "valid":
            journal = Journal(**JournalFixtureFactory.make_journal_source(in_doaj=True))
            journal.remove_related_applications()
            journal.remove_current_application()
            jid = journal.id
        elif journal_id == "not_in_doaj":
            journal = Journal(**JournalFixtureFactory.make_journal_source(in_doaj=False))
            journal.remove_related_applications()
            journal.remove_current_application()
            jid = journal.id
        elif journal_id == "missing":
            jid = uuid.uuid4().hex

        acc = None
        if account == "yes":
            acc = Account(**AccountFixtureFactory.make_publisher_source())
            if account_role == "none":
                acc.remove_role("publisher")
            elif account_role == "admin":
                acc.remove_role("publisher")
                acc.add_role("admin")
            acc.set_id(acc.makeid())
            if account_is_owner == "yes":
                acc.set_id(journal.owner)

        if journal_lock == "yes":
            lock.lock("journal", jid, "someoneelse", blocking=True)

        latest_app = None
        current_app_count = int(current_applications)
        for i in range(current_app_count):
            app = Suggestion(**ApplicationFixtureFactory.make_application_source())
            app.set_id(app.makeid())
            app.set_created("198" + str(i) + "-01-01T00:00:00Z")
            app.set_current_journal(jid)
            app.save()
            latest_app = app
            if journal is not None:
                journal.set_current_application(app.id)

        comp_app_count = int(completed_applications)
        for i in range(comp_app_count):
            app = Suggestion(**ApplicationFixtureFactory.make_application_source())
            app.set_id(app.makeid())
            app.set_created("197" + str(i) + "-01-01T00:00:00Z")
            app.set_related_journal(jid)
            app.save()
            if journal is not None:
                journal.add_related_application(app.id, date_accepted=app.created_date)

        if current_app_count == 0 and comp_app_count == 0:
            # save at least one record to initialise the index mapping, otherwise tests fail
            app = Suggestion(**ApplicationFixtureFactory.make_application_source())
            app.set_id(app.makeid())
            app.save()

        if application_lock == "yes":
            lock.lock("suggestion", latest_app.id, "someoneelse", blocking=True)

        if application_status != "n/a":
            latest_app.set_application_status(application_status)
            latest_app.save(blocking=True)

        # finally save the journal record, ensuring we get a blocking save, so everything
        # above here should be synchronised with the repo
        if journal is not None:
            journal.save(blocking=True)

        ###########################################################
        # Execution

        svc = DOAJ.applicationService()
        if raises != "":
            with self.assertRaises(EXCEPTIONS[raises]):
                svc.update_request_for_journal(jid, acc)
        else:
            application, jlock, alock = svc.update_request_for_journal(jid, acc)

            # we need to sleep, so the index catches up
            time.sleep(1)

            if return_app == "none":
                assert application is None
            elif return_app == "yes":
                assert application is not None

            if return_jlock == "none":
                assert jlock is None
            elif return_jlock == "yes":
                assert jlock is not None

            if return_alock == "none":
                assert alock is None
            elif return_alock == "yes":
                assert alock is not None

            if db_jlock == "no" and acc is not None:
                assert not lock.has_lock("journal", jid, acc.id)
            elif db_jlock == "yes" and acc is not None:
                assert lock.has_lock("journal", jid, acc.id)

            if db_alock == "no" and application.id is not None and acc is not None:
                assert not lock.has_lock("suggestion", application.id, acc.id)
            elif db_alock == "yes" and application.id is not None and acc is not None:
                assert lock.has_lock("suggestion", application.id, acc.id)

            if db_app == "no" and application.id is not None:
                indb = Suggestion.q2obj(q="id.exact:" + application.id)
                assert indb is None
            elif db_app == "yes" and application.id is not None:
                indb = Suggestion.q2obj(q="id.exact:" + application.id)
                assert indb is not None

            if current_app_count == 0 and comp_app_count == 0 and application is not None:
                assert application.article_metadata is None
                assert application.articles_last_year is None
            elif application is not None:
                assert application.article_metadata is not None
                assert application.articles_last_year is not None