Пример #1
0
    def __init__(self, id, revision_id=None):
        """Create a `Patron` instance.

        Patron instances are not stored in the database
        but are indexed in ElasticSearch.
        """
        _id = int(id)  # internally it is an int
        _datastore = current_app.extensions["security"].datastore
        # if not _id throw PatronNotFoundError(_id)
        user = _datastore.get_user(_id)
        if not user:
            raise PatronNotFoundError(_id)

        self._user = user
        self.id = self._user.id
        # set revision as it is needed by the indexer but always to the same
        # value as we don't need it
        self.revision_id = 1
        self._profile = UserProfile.get_by_userid(id)
        self.name = self._profile.full_name if self._profile else ""
        self.email = self._user.email

        # currently no support for patrons affiliated to different
        # locations, return only the default location
        pid_value, _ = current_app_ils.get_default_location_pid
        self.location_pid = pid_value

        # add all fields to the dict so they can be accessed as a dict too
        super().__init__(self.dumps())
Пример #2
0
def test_patron_not_found(app):
    """Test PatronNotFoundError."""
    patron_pid = "1"
    msg = "Patron with PID `{patron_pid}` was not found."
    with pytest.raises(PatronNotFoundError) as ex:
        raise PatronNotFoundError(patron_pid)
    assert ex.value.code == PatronNotFoundError.code
    assert ex.value.description == msg.format(patron_pid=patron_pid)
Пример #3
0
    def get_patron(patron_pid):
        """Return the patron object given the patron_pid."""
        if not patron_pid:
            raise PatronNotFoundError(patron_pid)

        if str(patron_pid) == str(SystemAgent.id):
            return SystemAgent()

        return Patron(patron_pid)
Пример #4
0
    def get_patron(cls, patron_pid):
        """Return the patron object given the patron_pid."""
        if not patron_pid:
            raise PatronNotFoundError(patron_pid)

        SystemAgent = current_app.config["ILS_PATRON_SYSTEM_AGENT_CLASS"]
        if str(patron_pid) == str(SystemAgent.id):
            return SystemAgent()

        return cls(patron_pid)
Пример #5
0
def send_email_after_loan_change(_, prev_loan, loan, trigger):
    """Send email notification when the loan changes."""
    _datastore = current_app.extensions["security"].datastore

    patron_pid = loan["patron_pid"]
    patron = _datastore.get_user(patron_pid)

    if not patron:
        raise PatronNotFoundError(patron_pid)
    if not patron.email:
        msg = "Patron with PID {} has no email address".format(patron_pid)
        raise MissingRequiredParameterError(description=msg)

    send_ils_mail(loan_message_factory(),
                  prev_loan,
                  loan,
                  trigger,
                  recipients=[patron.email])
Пример #6
0
    def __init__(self, id, revision_id=None):
        """Create a `Patron` instance.

        Patron instances are not stored in the database
        but are indexed in ElasticSearch.
        """
        _id = int(id)  # internally it is an int
        _datastore = current_app.extensions["security"].datastore
        # if not _id throw PatronNotFoundError(_id)
        user = _datastore.get_user(_id)
        if not user:
            raise PatronNotFoundError(_id)

        self._user = user
        self.id = self._user.id
        # set revision as it is needed by the indexer but always to the same
        # value as we don't need it
        self.revision_id = 1
        self._profile = UserProfile.get_by_userid(id)
        self.name = self._profile.full_name if self._profile else ""
        self.email = self._user.email
Пример #7
0
    def get_patron(patron_pid):
        """Return the patron object given the patron_pid."""
        if not patron_pid:
            raise PatronNotFoundError(patron_pid)

        return Patron(patron_pid)
Пример #8
0
 def ensure_patron_exists(self, patron_pid):
     """Ensure patron exists or raise."""
     try:
         current_app_ils.patron_cls.get_patron(patron_pid)
     except PatronNotFoundError:
         raise PatronNotFoundError(patron_pid)
Пример #9
0
def anonymize_patron_data(patron_pid, force=False):
    """Anonymize all the data/activity related to the given patron pid."""
    if patron_pid is None:
        raise ValueError("No patron pid was provided.")

    SystemAgent = current_app.config["ILS_PATRON_SYSTEM_AGENT_CLASS"]
    if str(patron_pid) == str(SystemAgent.id):
        raise ValueError("The patron pid cannot be the SystemAgent")

    try:
        patron = current_app_ils.patron_cls.get_patron(patron_pid)
    except PatronNotFoundError:
        patron = None
        if not force:
            raise PatronNotFoundError(patron_pid)

    n_loans = get_active_loans_by_patron_pid(patron_pid).count()
    if n_loans > 0:
        raise AnonymizationActiveLoansError(
            "Cannot delete user {0}: found {1} active loans.".format(
                patron_pid, n_loans))
    OrderSearch = current_ils_acq.order_search_cls
    n_orders = (
        OrderSearch().get_ongoing_orders_by_patron_pid(patron_pid).count())
    if n_orders > 0:
        raise AnonymizationActiveLoansError(
            "Cannot delete user {0}: found {1} active orders.".format(
                patron_pid, n_orders))

    # get anonymous patron values
    cls = current_app.config["ILS_PATRON_ANONYMOUS_CLASS"]
    anonymous_patron_fields = cls().dumps_loader()

    patron_loans = get_loans_by_patron_pid(patron_pid).scan()

    Loan = current_circulation.loan_record_cls
    indices = 0
    for hit in patron_loans:
        loan = Loan.get_record_by_pid(hit.pid)

        completed = (current_app.config["CIRCULATION_STATES_LOAN_CANCELLED"] +
                     current_app.config["CIRCULATION_STATES_LOAN_COMPLETED"])
        if loan["state"] not in completed:
            params = deepcopy(loan)
            params.update(
                dict(
                    cancel_reason="Loan request cancelled by the system.",
                    transaction_user_pid=str(SystemAgent.id),
                ))
            loan = current_circulation.circulation.trigger(
                loan, **dict(params, trigger="cancel"))
        loan["patron_pid"] = anonymous_patron_fields["pid"]
        loan["patron"] = anonymous_patron_fields
        loan.commit()
        current_circulation.loan_indexer().index(loan)
        indices += 1

    BorrowingRequestsSearch = current_ils_ill.borrowing_request_search_cls
    patron_borrowing_requests = (
        BorrowingRequestsSearch().search_by_patron_pid(patron_pid).scan())

    BorrowingRequest = current_ils_ill.borrowing_request_record_cls
    indexer = current_ils_ill.borrowing_request_indexer_cls()
    for hit in patron_borrowing_requests:
        borrowing_request = BorrowingRequest.get_record_by_pid(hit.pid)
        borrowing_request["patron"] = anonymous_patron_fields
        borrowing_request["patron_pid"] = anonymous_patron_fields["pid"]
        borrowing_request.commit()
        indexer.index(borrowing_request)
        indices += 1

    DocumentRequestSearch = current_app_ils.document_request_search_cls
    patron_document_requests = (
        DocumentRequestSearch().search_by_patron_pid(patron_pid).scan())

    DocumentRequest = current_app_ils.document_request_record_cls
    for hit in patron_document_requests:
        document_request = DocumentRequest.get_record_by_pid(hit.pid)
        if document_request["state"] == "PENDING":
            document_request["state"] = "DECLINED"
            document_request["decline_reason"] = "USER_CANCEL"
        document_request["patron"] = anonymous_patron_fields
        document_request["patron_pid"] = anonymous_patron_fields["pid"]
        document_request.commit()
        current_app_ils.document_request_indexer.index(document_request)
        indices += 1

    patron_acquisitions = OrderSearch().search_by_patron_pid(patron_pid).scan()

    Order = current_ils_acq.order_record_cls
    for hit in patron_acquisitions:
        acquisition = Order.get_record_by_pid(hit.pid)
        for line in acquisition["order_lines"]:
            if line["patron_pid"] == patron_pid:
                line["patron_pid"] = anonymous_patron_fields["pid"]
        acquisition.commit()
        current_ils_acq.order_indexer.index(acquisition)
        indices += 1

    # delete rows from db
    dropped = delete_user_account(patron_pid)

    # anonymize recipient id in emails
    emails = anonymize_patron_in_email_logs(patron_pid)

    db.session.commit()
    if patron:
        try:
            patron_indexer = current_app_ils.patron_indexer
            patron_indexer.delete(patron)
        except NotFoundError:
            pass

    return dropped, indices, emails