Beispiel #1
0
    def run(self):
        """
        Execute the task as specified by the background_job 
        :return:
        """
        job = self.background_job

        journalService = DOAJ.journalService()
        url = journalService.csv()
        job.add_audit_message(
            u"CSV generated; will be served from {y}".format(y=url))
Beispiel #2
0
    def run(self):
        """
        Execute the task as specified by the background_job 
        :return:
        """
        job = self.background_job

        journalService = DOAJ.journalService()
        url, action_register = journalService.csv()
        for ar in action_register:
            job.add_audit_message(ar)
        job.add_audit_message(u"CSV generated; will be served from {y}".format(y=url))
Beispiel #3
0
    def delete_application(self, application_id, account):
        """
        Function to delete an application, and all references to it in other objects (current and related journals)

        The application and all related journals need to be locked before this process can proceed, so you may get a
        lock.Locked exception

        :param application_id:
        :param account:
        :return:
        """
        # first validate the incoming arguments to ensure that we've got the right thing
        argvalidate("delete_application", [{
            "arg": application_id,
            "instance": unicode,
            "allow_none": False,
            "arg_name": "application_id"
        }, {
            "arg": account,
            "instance": models.Account,
            "allow_none": False,
            "arg_name": "account"
        }], exceptions.ArgumentException)

        journalService = DOAJ.journalService()
        authService = DOAJ.authorisationService()

        # get hold of a copy of the application.  If there isn't one, our work here is done
        # (note the application could be locked, in which case this will raise a lock.Locked exception)

        # get the application
        application, _ = self.application(application_id)
        if application is None:
            raise exceptions.NoSuchObjectException

        # determine if the user can edit the application
        authService.can_edit_application(account, application)

        # attempt to lock the record (this may raise a Locked exception)
        alock = lock.lock(constants.LOCK_APPLICATION, application_id,
                          account.id)

        # obtain the current journal, with associated lock
        current_journal = None
        cjlock = None
        if application.current_journal is not None:
            try:
                current_journal, cjlock = journalService.journal(
                    application.current_journal,
                    lock_journal=True,
                    lock_account=account)
            except lock.Locked as e:
                # if the resource is locked, we have to back out
                if alock is not None: alock.delete()
                raise

        # obtain the related journal, with associated lock
        related_journal = None
        rjlock = None
        if application.related_journal is not None:
            try:
                related_journal, rjlock = journalService.journal(
                    application.related_journal,
                    lock_journal=True,
                    lock_account=account)
            except lock.Locked as e:
                # if the resource is locked, we have to back out
                if alock is not None: alock.delete()
                if cjlock is not None: cjlock.delete()
                raise

        try:
            if current_journal is not None:
                current_journal.remove_current_application()
                saved = current_journal.save()
                if saved is None:
                    raise exceptions.SaveException(
                        "Unable to save journal record")

            if related_journal is not None:
                relation_record = related_journal.related_application_record(
                    application_id)
                if relation_record is None:
                    relation_record = {}
                related_journal.add_related_application(
                    application_id, relation_record.get("date_accepted"),
                    "deleted")
                saved = related_journal.save()
                if saved is None:
                    raise exceptions.SaveException(
                        "Unable to save journal record")

            application.delete()

        finally:
            if alock is not None: alock.delete()
            if cjlock is not None: cjlock.delete()
            if rjlock is not None: rjlock.delete()

        return
Beispiel #4
0
    def update_request_for_journal(self,
                                   journal_id,
                                   account=None,
                                   lock_timeout=None):
        """
        Obtain an update request application object for the journal with the given journal_id

        An update request may either be loaded from the database, if it already exists, or created
        in-memory if it has not previously been created.

        If an account is provided, this will validate that the account holder is allowed to make
        the conversion from journal to application, if a conversion is required.

        When this request runs, the journal will be locked to the provided account if an account is
        given.  If the application is loaded from the database, this will also be locked for the account
        holder.

        :param journal_id:
        :param account:
        :return: a tuple of (Application Object, Journal Lock, Application Lock)
        """
        # first validate the incoming arguments to ensure that we've got the right thing
        argvalidate("update_request_for_journal", [{
            "arg": journal_id,
            "instance": basestring,
            "allow_none": False,
            "arg_name": "journal_id"
        }, {
            "arg": account,
            "instance": models.Account,
            "allow_none": True,
            "arg_name": "account"
        }, {
            "arg": lock_timeout,
            "instance": int,
            "allow_none": True,
            "arg_name": "lock_timeout"
        }], exceptions.ArgumentException)

        if app.logger.isEnabledFor("debug"):
            app.logger.debug("Entering update_request_for_journal")

        journalService = DOAJ.journalService()
        authService = DOAJ.authorisationService()

        # first retrieve the journal, and return empty if there isn't one.
        # We don't attempt to obtain a lock at this stage, as we want to check that the user is authorised first
        journal_lock = None
        journal, _ = journalService.journal(journal_id)
        if journal is None:
            app.logger.info(
                "Request for journal {x} did not find anything in the database"
                .format(x=journal_id))
            return None, None, None

        # if the journal is not in_doaj, we won't create an update request for it
        if not journal.is_in_doaj():
            app.logger.info(
                "Request for journal {x} found it is not in_doaj; will not create update request"
                .format(x=journal_id))
            return None, None, None

        # retrieve the latest application attached to this journal
        application_lock = None
        application = models.Suggestion.find_latest_by_current_journal(
            journal_id)

        # if no such application exists, create one in memory (this will check that the user is permitted to create one)
        # at the same time, create the lock for the journal.  This will throw an AuthorisedException or a Locked exception
        # (in that order of preference) if any problems arise.
        if application is None:
            app.logger.info(
                "No existing update request for journal {x}; creating one".
                format(x=journal.id))
            application = journalService.journal_2_application(journal,
                                                               account=account)
            lra_id = journal.latest_related_application_id()
            if lra_id is not None:
                lra, _ = self.application(lra_id)
                if lra is not None:
                    self.patch_application(application, lra)
            if account is not None:
                journal_lock = lock.lock("journal", journal_id, account.id)

        # otherwise check that the user (if given) has the rights to edit the application
        # then lock the application and journal to the account.
        # If a lock cannot be obtained, unlock the journal and application before we return
        elif account is not None:
            try:
                authService.can_edit_application(account, application)
                application_lock = lock.lock("suggestion", application.id,
                                             account.id)
                journal_lock = lock.lock("journal", journal_id, account.id)
            except lock.Locked as e:
                if application_lock is not None: application_lock.delete()
                if journal_lock is not None: journal_lock.delete()
                raise
            except exceptions.AuthoriseException as e:
                msg = "Account {x} is not permitted to edit the current update request on journal {y}".format(
                    x=account.id, y=journal.id)
                app.logger.info(msg)
                e.message = msg
                raise

            app.logger.info(
                "Using existing application {y} as update request for journal {x}"
                .format(y=application.id, x=journal.id))

        if app.logger.isEnabledFor("debug"):
            app.logger.debug(
                "Completed update_request_for_journal; return application object"
            )

        return application, journal_lock, application_lock
Beispiel #5
0
    def reject_application(self,
                           application,
                           account,
                           provenance=True,
                           note=None,
                           manual_update=True):
        """
        Reject an application.  This will:
        * set the application status to "rejected" (if not already)
        * remove the current_journal field, and move it to related_journal (if needed)
        * remove the current_application field from the related journal (if needed)
        * save the application
        * write a provenance record for the rejection (if requested)

        :param application:
        :param account:
        :param provenance:
        :param manual_update:
        :return:
        """
        # first validate the incoming arguments to ensure that we've got the right thing
        argvalidate("reject_application", [{
            "arg": application,
            "instance": models.Suggestion,
            "allow_none": False,
            "arg_name": "application"
        }, {
            "arg": account,
            "instance": models.Account,
            "allow_none": False,
            "arg_name": "account"
        }, {
            "arg": provenance,
            "instance": bool,
            "allow_none": False,
            "arg_name": "provenance"
        }, {
            "arg": note,
            "instance": basestring,
            "allow_none": True,
            "arg_name": "note"
        }, {
            "arg": manual_update,
            "instance": bool,
            "allow_none": False,
            "arg_name": "manual_update"
        }], exceptions.ArgumentException)

        if app.logger.isEnabledFor("debug"):
            app.logger.debug("Entering reject_application")

        journalService = DOAJ.journalService()

        # check we're allowed to carry out this action
        if not account.has_role("reject_application"):
            raise exceptions.AuthoriseException(
                message="This user is not allowed to reject applications",
                reason=exceptions.AuthoriseException.WRONG_ROLE)

        # ensure the application status is "rejected"
        if application.application_status != constants.APPLICATION_STATUS_REJECTED:
            application.set_application_status(
                constants.APPLICATION_STATUS_REJECTED)

        # add the note to the application
        if note is not None:
            application.add_note(note)

        # retrieve the id of the current journal if there is one
        cj_id = application.current_journal
        cj = None

        # if there is a current_journal record, remove it, and record
        # it as a related journal.  This will let us come back later and know
        # which journal record this was intended as an update against if needed.
        if cj_id is not None:
            cj, _ = journalService.journal(cj_id)
            application.remove_current_journal()
            if cj is not None:
                application.set_related_journal(cj_id)
                cj.remove_current_application()

        # if there is a current journal, we will have modified it above, so save it
        if cj is not None:
            saved = cj.save()
            if saved is None:
                raise exceptions.SaveException(
                    "Save on current_journal in reject_application failed")

        # if we were asked to record this as a manual update, record that on the application
        if manual_update:
            application.set_last_manual_update()

        saved = application.save()
        if saved is None:
            raise exceptions.SaveException(
                "Save on application in reject_application failed")

        # record a provenance record that this action took place
        if provenance:
            models.Provenance.make(account,
                                   constants.PROVENANCE_STATUS_REJECTED,
                                   application)

        if app.logger.isEnabledFor("debug"):
            app.logger.debug("Completed reject_application")
Beispiel #6
0
    def delete_application(self, application_id, account):
        """
        Function to delete an application, and all references to it in other objects (current and related journals)

        The application and all related journals need to be locked before this process can proceed, so you may get a
        lock.Locked exception

        :param application_id:
        :param account:
        :return:
        """
        # first validate the incoming arguments to ensure that we've got the right thing
        argvalidate("delete_application", [
            {"arg": application_id, "instance" : unicode, "allow_none" : False, "arg_name" : "application_id"},
            {"arg" : account, "instance" : models.Account, "allow_none" : False, "arg_name" : "account"}
        ], exceptions.ArgumentException)

        journalService = DOAJ.journalService()
        authService = DOAJ.authorisationService()

        # get hold of a copy of the application.  If there isn't one, our work here is done
        # (note the application could be locked, in which case this will raise a lock.Locked exception)

        # get the application
        application, _ = self.application(application_id)
        if application is None:
            raise exceptions.NoSuchObjectException

        # determine if the user can edit the application
        authService.can_edit_application(account, application)

        # attempt to lock the record (this may raise a Locked exception)
        alock = lock.lock(constants.LOCK_APPLICATION, application_id, account.id)

        # obtain the current journal, with associated lock
        current_journal = None
        cjlock = None
        if application.current_journal is not None:
            try:
                current_journal, cjlock = journalService.journal(application.current_journal, lock_journal=True, lock_account=account)
            except lock.Locked as e:
                # if the resource is locked, we have to back out
                if alock is not None: alock.delete()
                raise

        # obtain the related journal, with associated lock
        related_journal = None
        rjlock = None
        if application.related_journal is not None:
            try:
                related_journal, rjlock = journalService.journal(application.related_journal, lock_journal=True, lock_account=account)
            except lock.Locked as e:
                # if the resource is locked, we have to back out
                if alock is not None: alock.delete()
                if cjlock is not None: cjlock.delete()
                raise

        try:
            if current_journal is not None:
                current_journal.remove_current_application()
                saved = current_journal.save()
                if saved is None:
                    raise exceptions.SaveException("Unable to save journal record")

            if related_journal is not None:
                relation_record = related_journal.related_application_record(application_id)
                if relation_record is None:
                    relation_record = {}
                related_journal.add_related_application(application_id, relation_record.get("date_accepted"), "deleted")
                saved = related_journal.save()
                if saved is None:
                    raise exceptions.SaveException("Unable to save journal record")

            application.delete()

        finally:
            if alock is not None: alock.delete()
            if cjlock is not None: cjlock.delete()
            if rjlock is not None: rjlock.delete()

        return
Beispiel #7
0
    def update_request_for_journal(self, journal_id, account=None, lock_timeout=None):
        """
        Obtain an update request application object for the journal with the given journal_id

        An update request may either be loaded from the database, if it already exists, or created
        in-memory if it has not previously been created.

        If an account is provided, this will validate that the account holder is allowed to make
        the conversion from journal to application, if a conversion is required.

        When this request runs, the journal will be locked to the provided account if an account is
        given.  If the application is loaded from the database, this will also be locked for the account
        holder.

        :param journal_id:
        :param account:
        :return: a tuple of (Application Object, Journal Lock, Application Lock)
        """
        # first validate the incoming arguments to ensure that we've got the right thing
        argvalidate("update_request_for_journal", [
            {"arg": journal_id, "instance" : basestring, "allow_none" : False, "arg_name" : "journal_id"},
            {"arg" : account, "instance" : models.Account, "allow_none" : True, "arg_name" : "account"},
            {"arg" : lock_timeout, "instance" : int, "allow_none" : True, "arg_name" : "lock_timeout"}
        ], exceptions.ArgumentException)

        if app.logger.isEnabledFor("debug"): app.logger.debug("Entering update_request_for_journal")

        journalService = DOAJ.journalService()
        authService = DOAJ.authorisationService()

        # first retrieve the journal, and return empty if there isn't one.
        # We don't attempt to obtain a lock at this stage, as we want to check that the user is authorised first
        journal_lock = None
        journal, _ = journalService.journal(journal_id)
        if journal is None:
            app.logger.info("Request for journal {x} did not find anything in the database".format(x=journal_id))
            return None, None, None

        # if the journal is not in_doaj, we won't create an update request for it
        if not journal.is_in_doaj():
            app.logger.info("Request for journal {x} found it is not in_doaj; will not create update request".format(x=journal_id))
            return None, None, None

        # retrieve the latest application attached to this journal
        application_lock = None
        application = models.Suggestion.find_latest_by_current_journal(journal_id)

        # if no such application exists, create one in memory (this will check that the user is permitted to create one)
        # at the same time, create the lock for the journal.  This will throw an AuthorisedException or a Locked exception
        # (in that order of preference) if any problems arise.
        if application is None:
            app.logger.info("No existing update request for journal {x}; creating one".format(x=journal.id))
            application = journalService.journal_2_application(journal, account=account)
            lra_id = journal.latest_related_application_id()
            if lra_id is not None:
                lra, _ = self.application(lra_id)
                if lra is not None:
                    self.patch_application(application, lra)
            if account is not None:
                journal_lock = lock.lock("journal", journal_id, account.id)

        # otherwise check that the user (if given) has the rights to edit the application
        # then lock the application and journal to the account.
        # If a lock cannot be obtained, unlock the journal and application before we return
        elif account is not None:
            try:
                authService.can_edit_application(account, application)
                application_lock = lock.lock("suggestion", application.id, account.id)
                journal_lock = lock.lock("journal", journal_id, account.id)
            except lock.Locked as e:
                if application_lock is not None: application_lock.delete()
                if journal_lock is not None: journal_lock.delete()
                raise
            except exceptions.AuthoriseException as e:
                msg = "Account {x} is not permitted to edit the current update request on journal {y}".format(x=account.id, y=journal.id)
                app.logger.info(msg)
                e.message = msg
                raise

            app.logger.info("Using existing application {y} as update request for journal {x}".format(y=application.id, x=journal.id))

        if app.logger.isEnabledFor("debug"): app.logger.debug("Completed update_request_for_journal; return application object")

        return application, journal_lock, application_lock
Beispiel #8
0
    def reject_application(self, application, account, provenance=True, note=None, manual_update=True):
        """
        Reject an application.  This will:
        * set the application status to "rejected" (if not already)
        * remove the current_journal field, and move it to related_journal (if needed)
        * remove the current_application field from the related journal (if needed)
        * save the application
        * write a provenance record for the rejection (if requested)

        :param application:
        :param account:
        :param provenance:
        :param manual_update:
        :return:
        """
        # first validate the incoming arguments to ensure that we've got the right thing
        argvalidate("reject_application", [
            {"arg": application, "instance" : models.Suggestion, "allow_none" : False, "arg_name" : "application"},
            {"arg" : account, "instance" : models.Account, "allow_none" : False, "arg_name" : "account"},
            {"arg" : provenance, "instance" : bool, "allow_none" : False, "arg_name" : "provenance"},
            {"arg" : note, "instance" : basestring, "allow_none" : True, "arg_name" : "note"},
            {"arg" : manual_update, "instance" : bool, "allow_none" : False, "arg_name" : "manual_update"}
        ], exceptions.ArgumentException)

        if app.logger.isEnabledFor("debug"): app.logger.debug("Entering reject_application")

        journalService = DOAJ.journalService()

        # check we're allowed to carry out this action
        if not account.has_role("reject_application"):
            raise exceptions.AuthoriseException(message="This user is not allowed to reject applications", reason=exceptions.AuthoriseException.WRONG_ROLE)

        # ensure the application status is "rejected"
        if application.application_status != constants.APPLICATION_STATUS_REJECTED:
            application.set_application_status(constants.APPLICATION_STATUS_REJECTED)

        # add the note to the application
        if note is not None:
            application.add_note(note)

         # retrieve the id of the current journal if there is one
        cj_id = application.current_journal
        cj = None

        # if there is a current_journal record, remove it, and record
        # it as a related journal.  This will let us come back later and know
        # which journal record this was intended as an update against if needed.
        if cj_id is not None:
            cj, _ = journalService.journal(cj_id)
            application.remove_current_journal()
            if cj is not None:
                application.set_related_journal(cj_id)
                cj.remove_current_application()

        # if there is a current journal, we will have modified it above, so save it
        if cj is not None:
            saved = cj.save()
            if saved is None:
                raise exceptions.SaveException("Save on current_journal in reject_application failed")

        # if we were asked to record this as a manual update, record that on the application
        if manual_update:
            application.set_last_manual_update()

        saved = application.save()
        if saved is None:
            raise exceptions.SaveException("Save on application in reject_application failed")

        # record a provenance record that this action took place
        if provenance:
            models.Provenance.make(account, constants.PROVENANCE_STATUS_REJECTED, application)

        if app.logger.isEnabledFor("debug"): app.logger.debug("Completed reject_application")