def ldap_sync(self: MonitoredTask, source_pk: str, sync_class: str): """Synchronization of an LDAP Source""" self.result_timeout_hours = 2 try: source: LDAPSource = LDAPSource.objects.get(pk=source_pk) except LDAPSource.DoesNotExist: # Because the source couldn't be found, we don't have a UID # to set the state with return sync = path_to_class(sync_class) self.set_uid( f"{source.slug}_{sync.__name__.replace('LDAPSynchronizer', '').lower()}" ) try: sync_inst = sync(source) count = sync_inst.sync() messages = sync_inst.messages messages.append(f"Synced {count} objects.") self.set_status(TaskResult( TaskResultStatus.SUCCESSFUL, messages, )) except LDAPException as exc: # No explicit event is created here as .set_status with an error will do that LOGGER.debug(exc) self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc))
def authenticate(request: HttpRequest, backends: list[str], **credentials: dict[str, Any]) -> Optional[User]: """If the given credentials are valid, return a User object. Customized version of django's authenticate, which accepts a list of backends""" for backend_path in backends: try: backend: BaseBackend = path_to_class(backend_path)() except ImportError: LOGGER.warning("Failed to import backend", path=backend_path) continue LOGGER.debug("Attempting authentication...", backend=backend_path) user = backend.authenticate(request, **credentials) if user is None: LOGGER.debug("Backend returned nothing, continuing", backend=backend_path) continue # Annotate the user object with the path of the backend. user.backend = backend_path LOGGER.debug("Successful authentication", user=user, backend=backend_path) return user # The credentials supplied are invalid to all backends, fire signal user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials), request=request)
def outpost_post_save(model_class: str, model_pk: Any): """If an Outpost is saved, Ensure that token is created/updated If an OutpostModel, or a model that is somehow connected to an OutpostModel is saved, we send a message down the relevant OutpostModels WS connection to trigger an update""" model: Model = path_to_class(model_class) try: instance = model.objects.get(pk=model_pk) except model.DoesNotExist: LOGGER.warning("Model does not exist", model=model, pk=model_pk) return if isinstance(instance, Outpost): LOGGER.debug("Ensuring token for outpost", instance=instance) _ = instance.token LOGGER.debug("Trigger reconcile for outpost") outpost_controller.delay(instance.pk) if isinstance(instance, (OutpostModel, Outpost)): LOGGER.debug("triggering outpost update from outpostmodel/outpost", instance=instance) outpost_send_update(instance) if isinstance(instance, OutpostServiceConnection): LOGGER.debug("triggering ServiceConnection state update", instance=instance) outpost_service_connection_state.delay(instance.pk) for field in instance._meta.get_fields(): # Each field is checked if it has a `related_model` attribute (when ForeginKeys or M2Ms) # are used, and if it has a value if not hasattr(field, "related_model"): continue if not field.related_model: continue if not issubclass(field.related_model, OutpostModel): continue field_name = f"{field.name}_set" if not hasattr(instance, field_name): continue LOGGER.debug("triggering outpost update from from field", field=field.name) # Because the Outpost Model has an M2M to Provider, # we have to iterate over the entire QS for reverse in getattr(instance, field_name).all(): outpost_send_update(reverse)
def test_path_to_class(self): """Test path_to_class""" self.assertIsNone(path_to_class(None)) self.assertEqual(path_to_class("datetime.datetime"), datetime)