def reactivate_user_backend(request: HttpRequest, user_profile: UserProfile, user_id: int) -> HttpResponse: target = access_user_by_id(user_profile, user_id, allow_deactivated=True, allow_bots=True, for_admin=True) if target.is_bot: assert target.bot_type is not None check_bot_creation_policy(user_profile, target.bot_type) do_reactivate_user(target, acting_user=user_profile) return json_success(request)
def test_user_activation(self) -> None: realm = get_realm("zulip") now = timezone_now() user = do_create_user("email", "password", realm, "full_name", acting_user=None) do_deactivate_user(user, acting_user=user) do_activate_mirror_dummy_user(user, acting_user=user) do_deactivate_user(user, acting_user=user) do_reactivate_user(user, acting_user=user) self.assertEqual( RealmAuditLog.objects.filter(event_time__gte=now).count(), 6) event_types = list( RealmAuditLog.objects.filter( realm=realm, acting_user=user, modified_user=user, modified_stream=None, event_time__gte=now, event_time__lte=now + timedelta(minutes=60), ).order_by("event_time").values_list("event_type", flat=True)) self.assertEqual( event_types, [ RealmAuditLog.USER_CREATED, RealmAuditLog.USER_DEACTIVATED, RealmAuditLog.USER_ACTIVATED, RealmAuditLog.USER_DEACTIVATED, RealmAuditLog.USER_REACTIVATED, ], ) for event in RealmAuditLog.objects.filter( realm=realm, acting_user=user, modified_user=user, modified_stream=None, event_time__gte=now, event_time__lte=now + timedelta(minutes=60), ): extra_data = orjson.loads(assert_is_not_none(event.extra_data)) self.check_role_count_schema(extra_data[RealmAuditLog.ROLE_COUNT]) self.assertNotIn(RealmAuditLog.OLD_VALUE, extra_data)
def save(self) -> None: """ This method is called at the end of operations modifying a user, and is responsible for actually applying the requested changes, writing them to the database. """ realm = RequestNotes.get_notes(self._request).realm assert realm is not None email_new_value = getattr(self, "_email_new_value", None) is_active_new_value = getattr(self, "_is_active_new_value", None) full_name_new_value = getattr(self, "_full_name_new_value", None) password = getattr(self, "_password_set_to", None) # Clean up the internal "pending change" state, now that we've # fetched the values: self._email_new_value = None self._is_active_new_value = None self._full_name_new_value = None self._password_set_to = None if email_new_value: try: # Note that the validate_email check that usually # appears adjacent to email_allowed_for_realm is # present in save(). email_allowed_for_realm(email_new_value, realm) except DomainNotAllowedForRealmError: raise scim_exceptions.BadRequestError( "This email domain isn't allowed in this organization.") except DisposableEmailError: # nocoverage raise scim_exceptions.BadRequestError( "Disposable email domains are not allowed for this realm.") except EmailContainsPlusError: # nocoverage raise scim_exceptions.BadRequestError( "Email address can't contain + characters.") try: validate_email_not_already_in_realm(realm, email_new_value) except ValidationError as e: raise ConflictError("Email address already in use: " + str(e)) if self.is_new_user(): assert full_name_new_value is not None self.obj = do_create_user( email_new_value, password, realm, full_name_new_value, acting_user=None, ) return # TODO: The below operations should ideally be executed in a single # atomic block to avoid failing with partial changes getting saved. # This can be fixed once we figure out how do_deactivate_user can be run # inside an atomic block. # We process full_name first here, since it's the only one that can fail. if full_name_new_value: check_change_full_name(self.obj, full_name_new_value, acting_user=None) if email_new_value: do_change_user_delivery_email(self.obj, email_new_value) if is_active_new_value is not None and is_active_new_value: do_reactivate_user(self.obj, acting_user=None) elif is_active_new_value is not None and not is_active_new_value: do_deactivate_user(self.obj, acting_user=None)