def sync_ldap_user_data(user_profiles: List[UserProfile], deactivation_protection: bool=True) -> None: logger.info("Starting update.") with transaction.atomic(): realms = set([u.realm.string_id for u in user_profiles]) for u in user_profiles: # This will save the user if relevant, and will do nothing if the user # does not exist. try: sync_user_from_ldap(u, logger) except ZulipLDAPException as e: logger.error("Error attempting to update user %s:" % (u.delivery_email,)) logger.error(e) if deactivation_protection: if not UserProfile.objects.filter(is_bot=False, is_active=True).exists(): error_msg = ("Ldap sync would have deactivated all users. This is most likely due " + "to a misconfiguration of ldap settings. Rolling back...\n" + "Use the --force option if the mass deactivation is intended.") logger.error(error_msg) # Raising an exception in this atomic block will rollback the transaction. raise Exception(error_msg) for string_id in realms: if not UserProfile.objects.filter(is_bot=False, is_active=True, realm__string_id=string_id, role__gte=UserProfile.ROLE_REALM_ADMINISTRATOR).exists(): error_msg = ("Ldap sync would have deactivated all administrators of realm %s. " + "This is most likely due " + "to a misconfiguration of ldap settings. Rolling back...\n" + "Use the --force option if the mass deactivation is intended.") error_msg = error_msg % (string_id,) logger.error(error_msg) raise Exception(error_msg) logger.info("Finished update.")
def sync_ldap_user_data(user_profiles: List[UserProfile]) -> None: logger.info("Starting update.") for u in user_profiles: # This will save the user if relevant, and will do nothing if the user # does not exist. try: sync_user_from_ldap(u, logger) except ZulipLDAPException as e: logger.error("Error attempting to update user %s:" % (u.email,)) logger.error(e) logger.info("Finished update.")
def sync_ldap_user_data(user_profiles: List[UserProfile], deactivation_protection: bool = True) -> None: logger.info("Starting update.") try: realms = {u.realm.string_id for u in user_profiles} for u in user_profiles: # This will save the user if relevant, and will do nothing if the user # does not exist. try: sync_user_from_ldap(u, logger) except ZulipLDAPException as e: logger.error("Error attempting to update user %s:", u.delivery_email) logger.error(e.args[0]) if deactivation_protection: if not UserProfile.objects.filter(is_bot=False, is_active=True).exists(): raise Exception( "LDAP sync would have deactivated all users. This is most likely due " "to a misconfiguration of LDAP settings. Rolling back...\n" "Use the --force option if the mass deactivation is intended." ) for string_id in realms: if not UserProfile.objects.filter( is_bot=False, is_active=True, realm__string_id=string_id, role=UserProfile.ROLE_REALM_OWNER, ).exists(): raise Exception( f"LDAP sync would have deactivated all owners of realm {string_id}. " "This is most likely due " "to a misconfiguration of LDAP settings. Rolling back...\n" "Use the --force option if the mass deactivation is intended." ) except Exception: logger.error("LDAP sync failed", exc_info=True) raise logger.info("Finished update.")
def test_sync_user_from_ldap_with_email_attr(self) -> None: """In LDAP configurations with LDAP_EMAIL_ATTR configured and LDAP_DEACTIVATE_NON_MATCHING_USERS set, a possible failure mode if django_to_ldap_username isn't configured correctly is all LDAP users having their accounts deactivated. Before the introduction of AUTH_LDAP_REVERSE_EMAIL_SEARCH, this would happen even in valid LDAP configurations using LDAP_EMAIL_ATTR. This test confirms that such a failure mode doesn't happen with a valid LDAP configuration. """ user_profile = self.example_user("hamlet") with self.settings(): sync_user_from_ldap(user_profile, mock.Mock()) # Syncing didn't deactivate the user: self.assertTrue(user_profile.is_active) with self.settings(AUTH_LDAP_REVERSE_EMAIL_SEARCH=None): # Without email search, the user will get deactivated. sync_user_from_ldap(user_profile, mock.Mock()) self.assertFalse(user_profile.is_active)
def sync_ldap_user_data(user_profiles: List[UserProfile]) -> None: logger.info("Starting update.") for u in user_profiles: # This will save the user if relevant, and will do nothing if the user # does not exist. try: if sync_user_from_ldap(u): logger.info("Updated %s." % (u.email,)) else: logger.warning("Did not find %s in LDAP." % (u.email,)) if settings.LDAP_DEACTIVATE_NON_MATCHING_USERS: logger.info("Deactivated non-matching user: %s" % (u.email,)) except ZulipLDAPException as e: logger.error("Error attempting to update user %s:" % (u.email,)) logger.error(e) logger.info("Finished update.")
def sync_ldap_user_data(user_profiles: List[UserProfile]) -> None: logger.info("Starting update.") for u in user_profiles: # This will save the user if relevant, and will do nothing if the user # does not exist. try: if sync_user_from_ldap(u): logger.info("Updated %s." % (u.email, )) else: logger.warning("Did not find %s in LDAP." % (u.email, )) if settings.LDAP_DEACTIVATE_NON_MATCHING_USERS: logger.info("Deactivated non-matching user: %s" % (u.email, )) except ZulipLDAPException as e: logger.error("Error attempting to update user %s:" % (u.email, )) logger.error(e) logger.info("Finished update.")