def to_delegated_patron_identifier_uuid(self, library_uri, foreign_patron_identifier, value_generator=None): """Create or lookup a DelegatedPatronIdentifier containing an Adobe account ID for the given library and foreign patron ID. :return: A 2-tuple (UUID, label) """ if not library_uri or not foreign_patron_identifier: return None, None value_generator = value_generator or self.uuid identifier, is_new = DelegatedPatronIdentifier.get_one_or_create( self._db, library_uri, foreign_patron_identifier, DelegatedPatronIdentifier.ADOBE_ACCOUNT_ID, value_generator, ) if identifier is None: return None, None return ( identifier.delegated_identifier, self.urn_to_label(identifier.delegated_identifier), )
def test_migrate_adobe_id_success(self): from api.opds import CirculationManagerAnnotator patron = self._patron() # This patron has a Credential containing their Adobe ID data_source = DataSource.lookup(self._db, DataSource.ADOBE) adobe_id = Credential( patron=patron, data_source=data_source, type=AdobeVendorIDModel.VENDOR_ID_UUID_TOKEN_TYPE, credential="My Adobe ID" ) # Run the migration. new_credential, delegated_identifier = self.authdata.migrate_adobe_id(patron) # The patron now has _two_ Credentials -- the old one # containing the Adobe ID, and a new one. eq_(set([new_credential, adobe_id]), set(patron.credentials)) # The new credential contains an anonymized patron identifier # used solely to connect the patron to their Adobe ID. eq_(AuthdataUtility.ADOBE_ACCOUNT_ID_PATRON_IDENTIFIER, new_credential.type) # We can use that identifier to look up a DelegatedPatronIdentifier # def explode(): # This method won't be called because the # DelegatedPatronIdentifier already exists. raise Exception() identifier, is_new = DelegatedPatronIdentifier.get_one_or_create( self._db, self.authdata.library_uri, new_credential.credential, DelegatedPatronIdentifier.ADOBE_ACCOUNT_ID, explode ) eq_(delegated_identifier, identifier) eq_(False, is_new) eq_("My Adobe ID", identifier.delegated_identifier) # An integration-level test: # AdobeVendorIDModel.to_delegated_patron_identifier_uuid works # now. model = AdobeVendorIDModel(self._default_library, None, None) uuid, label = model.to_delegated_patron_identifier_uuid( self.authdata.library_uri, new_credential.credential ) eq_("My Adobe ID", uuid) eq_('Delegated account ID My Adobe ID', label) # If we run the migration again, nothing new happens. new_credential_2, delegated_identifier_2 = self.authdata.migrate_adobe_id(patron) eq_(new_credential, new_credential_2) eq_(delegated_identifier, delegated_identifier_2) eq_(2, len(patron.credentials)) uuid, label = model.to_delegated_patron_identifier_uuid( self.authdata.library_uri, new_credential.credential ) eq_("My Adobe ID", uuid) eq_('Delegated account ID My Adobe ID', label)
def migrate_adobe_id(self, patron): """If the given patron has an Adobe ID stored as a Credential, also store it as a DelegatedPatronIdentifier. This method and its test should be removed once all instances have run the migration script 20161102-adobe-id-is-delegated-patron-identifier.py. """ _db = Session.object_session(patron) credential = get_one( _db, Credential, patron=patron, type=AdobeVendorIDModel.VENDOR_ID_UUID_TOKEN_TYPE, ) if not credential: # This patron has no Adobe ID. Do nothing. return None, None adobe_id = credential.credential # Create a new Credential containing an anonymized patron ID. patron_identifier_credential = ( AdobeVendorIDModel.get_or_create_patron_identifier_credential( patron)) # Then create a DelegatedPatronIdentifier mapping that # anonymized patron ID to the patron's Adobe ID. def create_function(): """This will be called as the DelegatedPatronIdentifier is created. We already know the patron's Adobe ID and just want to store it in the DPI. """ return adobe_id delegated_identifier, is_new = DelegatedPatronIdentifier.get_one_or_create( _db, self.library_uri, patron_identifier_credential.credential, DelegatedPatronIdentifier.ADOBE_ACCOUNT_ID, create_function, ) return patron_identifier_credential, delegated_identifier