def journal_2_application(self, journal, account=None, keep_editors=False): """ Function to convert a given journal into an application object. Provide the journal, and it will be converted in-memory to the application object (currently a Suggestion). The new application WILL NOT be saved by this method. If an account is provided, this will validate that the account holder is allowed to make this conversion :param journal: a journal to convert :param account: an account doing the action - optional, if specified the application will only be created if the account is allowed to :return: Suggestion object """ # first validate the incoming arguments to ensure that we've got the right thing argvalidate("journal_2_application", [{ "arg": journal, "instance": models.Journal, "allow_none": False, "arg_name": "journal" }, { "arg": account, "instance": models.Account, "arg_name": "account" }], exceptions.ArgumentException) if app.logger.isEnabledFor(logging.DEBUG): app.logger.debug("Entering journal_2_application") authService = DOAJ.authorisationService() # if an account is specified, check that it is allowed to perform this action if account is not None: try: authService.can_create_update_request( account, journal) # throws exception if not allowed except exceptions.AuthoriseException as e: msg = "Account {x} is not permitted to create an update request on journal {y}".format( x=account.id, y=journal.id) app.logger.info(msg) e.args += (msg, ) raise # copy all the relevant information from the journal to the application bj = journal.bibjson() contacts = journal.contacts() notes = journal.notes first_contact = None application = models.Suggestion() application.set_application_status( constants.APPLICATION_STATUS_UPDATE_REQUEST) for c in contacts: application.add_contact(c.get("name"), c.get("email")) if first_contact is None: first_contact = c application.set_current_journal(journal.id) if keep_editors is True: if journal.editor is not None: application.set_editor(journal.editor) if journal.editor_group is not None: application.set_editor_group(journal.editor_group) for n in notes: application.add_note(n.get("note"), n.get("date")) application.set_owner(journal.owner) application.set_seal(journal.has_seal()) application.set_bibjson(bj) if first_contact is not None: application.set_suggester(first_contact.get("name"), first_contact.get("email")) application.suggested_on = dates.now() if app.logger.isEnabledFor(logging.DEBUG): app.logger.debug( "Completed journal_2_application; return application object") return application
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
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
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
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
def journal_2_application(self, journal, account=None, keep_editors=False): """ Function to convert a given journal into an application object. Provide the journal, and it will be converted in-memory to the application object (currently a Suggestion). The new application WILL NOT be saved by this method. If an account is provided, this will validate that the account holder is allowed to make this conversion :param journal: a journal to convert :param account: an account doing the action - optional, if specified the application will only be created if the account is allowed to :return: Suggestion object """ # first validate the incoming arguments to ensure that we've got the right thing argvalidate("journal_2_application", [ {"arg": journal, "instance" : models.Journal, "allow_none" : False, "arg_name" : "journal"}, {"arg" : account, "instance" : models.Account, "arg_name" : "account"} ], exceptions.ArgumentException) if app.logger.isEnabledFor("debug"): app.logger.debug("Entering journal_2_application") authService = DOAJ.authorisationService() # if an account is specified, check that it is allowed to perform this action if account is not None: try: authService.can_create_update_request(account, journal) # throws exception if not allowed except exceptions.AuthoriseException as e: msg = "Account {x} is not permitted to create an update request on journal {y}".format(x=account.id, y=journal.id) app.logger.info(msg) e.message = msg raise # copy all the relevant information from the journal to the application bj = journal.bibjson() contacts = journal.contacts() notes = journal.notes first_contact = None application = models.Suggestion() application.set_application_status(constants.APPLICATION_STATUS_UPDATE_REQUEST) for c in contacts: application.add_contact(c.get("name"), c.get("email")) if first_contact is None: first_contact = c application.set_current_journal(journal.id) if keep_editors is True: if journal.editor is not None: application.set_editor(journal.editor) if journal.editor_group is not None: application.set_editor_group(journal.editor_group) for n in notes: application.add_note(n.get("note"), n.get("date")) application.set_owner(journal.owner) application.set_seal(journal.has_seal()) application.set_bibjson(bj) if first_contact is not None: application.set_suggester(first_contact.get("name"), first_contact.get("email")) application.suggested_on = dates.now() if app.logger.isEnabledFor("debug"): app.logger.debug("Completed journal_2_application; return application object") return application