def lock_for(self, user, hard_lock=False): """ Together with ``unlock_for`` this is probably the most important method on this model. If applicable to your use-case, you should lock for a specific user; that way, we can throw an exception when another user tries to unlock an object they haven't locked themselves. When using soft locks (the default), any process can still use the save method on this object. If you set ``hard_lock=True``, trying to save an object without first unlocking will raise an ``ObjectLockedError``. Don't use hard locks unless you really need them. See :doc:`design`. """ logging.info("Attempting to initiate a lock for user `%s`" % user) if not isinstance(user, auth.User): raise ValueError("You should pass a valid auth.User to lock_for.") if self.lock_applies_to(user): raise ObjectLockedError("This object is already locked by another user. \ May not override, except through the `unlock` method.") else: self._locked_at = datetime.today() self._locked_by = user self._hard_lock = self.__init_hard_lock = hard_lock date = self.locked_at.strftime("%H:%M:%S") logging.info("Initiated a %s lock for `%s` at %s" % (self.lock_type, self.locked_by, self.locked_at))
def unlock(self): """ This method serves solely to allow the application itself or admin users to do manual lock overrides, even if they haven't initiated these locks themselves. Otherwise, use ``unlock_for``. """ self._locked_at = self._locked_by = None logging.info("Disengaged lock on `%s`" % self)
def unlock_for(self, user): """ See ``lock_for``. If the lock was initiated for a specific user, unlocking will fail unless that same user requested the unlocking. Manual overrides should use the ``unlock`` method instead. Will raise a ObjectLockedError exception when the current user isn't authorized to unlock the object. """ logging.info("Attempting to open up a lock on `%s` by user `%s`" % (self, user)) # refactor: should raise exceptions instead if self.is_locked_by(user): self.unlock() else: raise ObjectLockedError("Trying to unlock for another user than the one who initiated the currently active lock. This is not allowed. You may want to try a manual override through the `unlock` method instead.")
def lock_applies_to(self, user): """ A lock does not apply to the user who initiated the lock. Thus, ``lock_applies_to`` is used to ascertain whether a user is allowed to edit a locked object. """ logging.info("Checking if the lock on `%s` applies to user `%s`" % (self, user)) # a lock does not apply to the person who initiated the lock if self.is_locked and self.locked_by != user: logging.info("Lock applies.") return True else: logging.info("Lock does not apply.") return False