def create_new_environment_permissions(  # type: ignore[no-untyped-def]
    from_permission_key: str,
    model_class: type,
    reverse_attribute_name: str,
    new_permission_objects: typing.List[PermissionModel],
):
    """
    Whenever we introduce a new permission, more often than not, we do that in
    order to allow users to create more granular permissions.

    But we also need to make sure that the existing users who currently
    have less granular(super set) permissions, also get the new permissions. This function does
    excatly that.

    Args:
        from_permission_key: The permission key of the less granular permission, e.g: MANAGE_IDENTITIES.
        model_class: The model class for which we are creating the new permissions, e.g: UserEnvironmentPermission.
        reverse_attribute_name: The name of the reverse attribute on the model class, e.g: userenvironmentpermission.
        new_permission_objects: The list of the new permission model objects.

    """
    new_environment_permission_through_models = []
    environment_permission_through_model_class = model_class.permissions.through  # type: ignore[attr-defined]

    for environment_permission in model_class.objects.filter(  # type: ignore[attr-defined]
        permissions__key=from_permission_key
    ):
        new_environment_permission_through_models.extend(
            [
                environment_permission_through_model_class(
                    **{
                        f"{reverse_attribute_name}_id": environment_permission.id,
                        "permissionmodel_id": permission_model.key,
                    }
                )
                for permission_model in new_permission_objects
            ]
        )

    environment_permission_through_model_class.objects.bulk_create(
        new_environment_permission_through_models
    )

    Whenever we introduce a new permission, more often than not, we do that in
    order to allow users to create more granular permissions.

    But we also need to make sure that the existing users who currently
    have less granular(super set) permissions, also get the new permissions. This function does
    excatly that.

    Args:
        from_permission_key: The permission key of the less granular permission, e.g: MANAGE_IDENTITIES.
        model_class: The model class for which we are creating the new permissions, e.g: UserEnvironmentPermission.
        reverse_attribute_name: The name of the reverse attribute on the model class, e.g: userenvironmentpermission.
        new_permission_objects: The list of the new permission model objects.

    
api/core/migration_helpers.py