internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: saleor/saleor

Issue:
productVariantStocksUpdate should accept empty list
### What I'm trying to achieve
To make all-doing mutation and include`productVariantStocksUpdate` in it. Unfortunately it throws `GRAPHQL_ERROR` if `[]` is used as an input.

### Steps to reproduce the problem
1. Make `productVariantStocksUpdate` mutation with `stocks: []` 
2. Get an error

### What I expected to happen
To get success, because it did what I wanted, which is nothing 🤷‍♂️



Discussion:

Resolving patch:
diff --git a/saleor/graphql/product/bulk_mutations/products.py b/saleor/graphql/product/bulk_mutations/products.py
--- a/saleor/graphql/product/bulk_mutations/products.py
+++ b/saleor/graphql/product/bulk_mutations/products.py
@@ -437,14 +437,15 @@ def perform_mutation(cls, root, info, **data):
         variant = cls.get_node_or_error(
             info, data["variant_id"], only_type=ProductVariant
         )
-        warehouse_ids = [stock["warehouse"] for stock in stocks]
-        cls.check_for_duplicates(warehouse_ids, errors)
-        if errors:
-            raise ValidationError(errors)
-        warehouses = cls.get_nodes_or_error(
-            warehouse_ids, "warehouse", only_type=Warehouse
-        )
-        cls.update_or_create_variant_stocks(variant, stocks, warehouses)
+        if stocks:
+            warehouse_ids = [stock["warehouse"] for stock in stocks]
+            cls.check_for_duplicates(warehouse_ids, errors)
+            if errors:
+                raise ValidationError(errors)
+            warehouses = cls.get_nodes_or_error(
+                warehouse_ids, "warehouse", only_type=Warehouse
+            )
+            cls.update_or_create_variant_stocks(variant, stocks, warehouses)
         return cls(product_variant=variant)
 
     @classmethod


Test patch:
diff --git a/tests/api/test_variant.py b/tests/api/test_variant.py
--- a/tests/api/test_variant.py
+++ b/tests/api/test_variant.py
@@ -1708,6 +1708,24 @@ def test_product_variant_stocks_update(
         assert res in expected_result
 
 
+def test_product_variant_stocks_update_with_empty_stock_list(
+    staff_api_client, variant, warehouse, permission_manage_products
+):
+    variant_id = graphene.Node.to_global_id("ProductVariant", variant.pk)
+    stocks = []
+    variables = {"variantId": variant_id, "stocks": stocks}
+    response = staff_api_client.post_graphql(
+        VARIANT_STOCKS_UPDATE_MUTATIONS,
+        variables,
+        permissions=[permission_manage_products],
+    )
+    content = get_graphql_content(response)
+    data = content["data"]["productVariantStocksUpdate"]
+
+    assert not data["bulkStockErrors"]
+    assert len(data["productVariant"]["stocks"]) == len(stocks)
+
+
 def test_variant_stocks_update_stock_duplicated_warehouse(
     staff_api_client, variant, warehouse, permission_manage_products
 ):
Repository: saleor/saleor

Issue:
Adding the AWS setting AWS_QUERYSTRING_EXPIRE
### What I'm trying to achieve
I want to change the validity time of S3 images and files.

### Describe a proposed solution
Just add the setting to the settings file and let's go ;) 

Created this pull request:
#5763 



Discussion:

Resolving patch:
diff --git a/saleor/settings.py b/saleor/settings.py
--- a/saleor/settings.py
+++ b/saleor/settings.py
@@ -396,6 +396,7 @@ def get_host():
 AWS_MEDIA_BUCKET_NAME = os.environ.get("AWS_MEDIA_BUCKET_NAME")
 AWS_MEDIA_CUSTOM_DOMAIN = os.environ.get("AWS_MEDIA_CUSTOM_DOMAIN")
 AWS_QUERYSTRING_AUTH = get_bool_from_env("AWS_QUERYSTRING_AUTH", False)
+AWS_QUERYSTRING_EXPIRE = get_bool_from_env("AWS_QUERYSTRING_EXPIRE", 3600)
 AWS_S3_CUSTOM_DOMAIN = os.environ.get("AWS_STATIC_CUSTOM_DOMAIN")
 AWS_S3_ENDPOINT_URL = os.environ.get("AWS_S3_ENDPOINT_URL", None)
 AWS_S3_REGION_NAME = os.environ.get("AWS_S3_REGION_NAME", None)


Test patch:
Repository: saleor/saleor

Issue:
Product repetitions in homepage featured products
On Home page `FEATURED` products, I'm getting multiple instances of the same product (number of instances seems to match the number of product variants). I think it is the issue with the backend because the Graphql query returns the same product multiple times.

### Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->
![image](https://user-images.githubusercontent.com/6453010/87536871-0b981180-c69a-11ea-8195-1295a2e26585.png)


**System information**
Saleor platform (docker)
[storefront 44940260295f1fd495036c237fb3ddb57407aef8](https://github.com/mirumee/saleor-storefront/commit/44940260295f1fd495036c237fb3ddb57407aef8)
[api 053173ccc72c9d03d6f707fe78a8112940c1cf01](https://github.com/mirumee/saleor/commit/053173ccc72c9d03d6f707fe78a8112940c1cf01)




Discussion:
Hey, thanks for opening the issue, I've noticed this bug already a few days ago - I think it's related to data loaders which we added to optimize the homepage database queries. I suppose there is a missing `distinct` somewhere in the dataloader implementation that causes the issue.
example query presenting bug:
``` graphql
query FeaturedProducts {
    shop {
      homepageCollection {
        id
        products(first: 20) {
          edges {
            node {
              id
              name
              category {
                id
                name
              }
            }
          }
        }
      }
    }
  }
```

Resolving patch:
diff --git a/saleor/product/models.py b/saleor/product/models.py
--- a/saleor/product/models.py
+++ b/saleor/product/models.py
@@ -125,7 +125,7 @@ def collection_sorted(self, user: "User"):
 
     def published_with_variants(self):
         published = self.published()
-        return published.filter(variants__isnull=False)
+        return published.filter(variants__isnull=False).distinct()
 
     def visible_to_user(self, user):
         if self.user_has_access_to_all(user):


Test patch:
Repository: saleor/saleor

Issue:
Tidy HTML error page logging.
Django error page has a lot of tidy warnings. They cover the traceback in the console.



Discussion:
Fixed in ca5b95b followed by 11b74cd. Now it only prints warnings for 2xx responses.


Resolving patch:
diff --git a/saleor/graphql/webhook/subscription_payload.py b/saleor/graphql/webhook/subscription_payload.py
--- a/saleor/graphql/webhook/subscription_payload.py
+++ b/saleor/graphql/webhook/subscription_payload.py
@@ -4,12 +4,14 @@
 from django.core.handlers.base import BaseHandler
 from django.http import HttpRequest
 from django.test.client import RequestFactory
+from django.utils.functional import SimpleLazyObject
 from graphql import GraphQLDocument, get_default_backend, parse
 from graphql.error import GraphQLSyntaxError
 from graphql.language.ast import FragmentDefinition, OperationDefinition
 from promise import Promise
 
 from ...app.models import App
+from ...settings import get_host
 
 logger = get_task_logger(__name__)
 
@@ -54,10 +56,11 @@ def initialize_context() -> HttpRequest:
     return: HttpRequest
     """
     handler = BaseHandler()
-    context = RequestFactory().request()
+    context = RequestFactory().request(SERVER_NAME=SimpleLazyObject(get_host))
     handler.load_middleware()
     response = handler.get_response(context)
-    assert response.status_code == 200
+    if not response.status_code == 200:
+        raise Exception("Unable to initialize context for webhook.")
     return context
 
 


Test patch:
diff --git a/saleor/tests/fixtures.py b/saleor/tests/fixtures.py
--- a/saleor/tests/fixtures.py
+++ b/saleor/tests/fixtures.py
@@ -261,6 +261,7 @@ def site_settings(db, settings) -> SiteSettings:
         default_mail_sender_address="mirumee@example.com",
     )[0]
     settings.SITE_ID = site.pk
+    settings.ALLOWED_HOSTS += [site.domain]
 
     main_menu = Menu.objects.get_or_create(
         name=settings.DEFAULT_MENUS["top_menu_name"],
Repository: saleor/saleor

Issue:
Fix stock by ID dataloader
I want to merge this change because it fixes problem with dataloader that causes it to return stocks in wrong order. That in some situations (like in linked ticket) caused API to return data inconsistent with data from DB.

<!-- Please mention all relevant issue numbers. -->

# Impact

* [ ] New migrations
* [ ] New/Updated API fields or mutations
* [ ] Deprecated API fields or mutations
* [ ] Removed API types, fields, or mutations
* [ ] Documentation needs to be updated

# Pull Request Checklist

<!-- Please keep this section. It will make the maintainer's life easier. -->

* [ ] Privileged queries and mutations are guarded by proper permission checks
* [ ] Database queries are optimized and the number of queries is constant
* [ ] Database migration files are up to date
* [ ] The changes are tested
* [ ] GraphQL schema and type definitions are up to date
* [ ] Changes are mentioned in the changelog



Discussion:

Resolving patch:
diff --git a/saleor/graphql/warehouse/dataloaders.py b/saleor/graphql/warehouse/dataloaders.py
--- a/saleor/graphql/warehouse/dataloaders.py
+++ b/saleor/graphql/warehouse/dataloaders.py
@@ -346,4 +346,5 @@ class StockByIdLoader(DataLoader):
     context_key = "stock_by_id"
 
     def batch_load(self, keys):
-        return Stock.objects.using(self.database_connection_name).in_bulk(keys).values()
+        stocks = Stock.objects.using(self.database_connection_name).in_bulk(keys)
+        return [stocks.get(key) for key in keys]


Test patch:
Repository: saleor/saleor

Issue:
Schema doesn't document the deprecation of `secretKey`
It was noticed that we didn't update the docs to contain information about the deprecation of the [`secretKey` in Synchronous Webhooks](https://docs.saleor.io/docs/3.x/developer/extending/apps/synchronous-webhooks/key-concepts#payload-signature). 

I already submitted a [PR](https://github.com/saleor/saleor-docs/pull/490) to @saleor/docs to update that, but the schema doesn't reflect this deprecation as well.


Discussion:

Resolving patch:
diff --git a/saleor/graphql/webhook/mutations.py b/saleor/graphql/webhook/mutations.py
--- a/saleor/graphql/webhook/mutations.py
+++ b/saleor/graphql/webhook/mutations.py
@@ -38,7 +38,9 @@ class WebhookCreateInput(graphene.InputObjectType):
         description="Determine if webhook will be set active or not.", required=False
     )
     secret_key = graphene.String(
-        description="The secret key used to create a hash signature with each payload.",
+        description="The secret key used to create a hash signature with each payload."
+        f"{DEPRECATED_IN_3X_INPUT} As of Saleor 3.5, webhook payloads default to "
+        "signing using a verifiable JWS.",
         required=False,
     )
     query = graphene.String(
@@ -155,7 +157,10 @@ class WebhookUpdateInput(graphene.InputObjectType):
         description="Determine if webhook will be set active or not.", required=False
     )
     secret_key = graphene.String(
-        description="Use to create a hash signature with each payload.", required=False
+        description="Use to create a hash signature with each payload."
+        f"{DEPRECATED_IN_3X_INPUT} As of Saleor 3.5, webhook payloads default to "
+        "signing using a verifiable JWS.",
+        required=False,
     )
     query = graphene.String(
         description="Subscription query used to define a webhook payload."
diff --git a/saleor/graphql/webhook/types.py b/saleor/graphql/webhook/types.py
--- a/saleor/graphql/webhook/types.py
+++ b/saleor/graphql/webhook/types.py
@@ -177,11 +177,11 @@ class Webhook(ModelObjectType):
         required=True, description="Informs if webhook is activated."
     )
     secret_key = graphene.String(
-        description=(
-            "Used to create a hash signature with each payload."
-            "\n\nIf not set, since Saleor 3.5, your payload will be "
-            "signed using private key used also to sign JWT tokens."
-        )
+        description="Used to create a hash signature for each payload.",
+        deprecation_reason=(
+            f"{DEPRECATED_IN_3X_FIELD} As of Saleor 3.5, webhook payloads default to "
+            "signing using a verifiable JWS."
+        ),
     )
     subscription_query = graphene.String(
         description="Used to define payloads for specific events."


Test patch:
Repository: saleor/saleor

Issue:
Not able to Compose Supergraph because of Subscriptions
I'm not able to use Apllo Federation to extend Saleor because Federation is not supporting Subscription yet.

https://www.apollographql.com/docs/federation/#how-it-works:~:text=Apollo%20Federation%20does%20not%20currently%20support%20GraphQL%20subscription%20operations.


Discussion:
We'll look into it. Saleor itself does not support subscriptions using WebSockets so I think it's mostly a matter of hiding that part of the schema from the federation protocol.
@patrys when can we expect a patch for this in the main release? I think the issue is while building the federated schema, there's a   subscription object being passed to the method. 

https://github.com/saleor/saleor/blob/97129cf0c960fbc319f728a672552187b33697b1/saleor/graphql/core/federation/schema.py#L51

Resolving patch:
diff --git a/saleor/graphql/core/federation/schema.py b/saleor/graphql/core/federation/schema.py
--- a/saleor/graphql/core/federation/schema.py
+++ b/saleor/graphql/core/federation/schema.py
@@ -135,8 +135,14 @@ def resolve_entities(_, info, *, representations):
 
 
 def create_service_sdl_resolver(schema):
+    # subscriptions are not handled by the federation protocol
+    schema_sans_subscriptions = graphene.Schema(
+        query=schema._query, mutation=schema._mutation, types=schema.types
+    )
     # Render schema to string
-    federated_schema_sdl = print_schema(schema)
+    federated_schema_sdl = print_schema(schema_sans_subscriptions)
+
+    del schema_sans_subscriptions
 
     # Remove "schema { ... }"
     schema_start = federated_schema_sdl.find("schema {")


Test patch:
Repository: saleor/saleor

Issue:
giftCardCreate mutation tries to create GiftCard and GiftCardTag on different databases
[Error from Sentry](https://sentry.io/organizations/saleor/issues/3526888361/):
Cannot add "<GiftCardTag: GiftCardTag object (290)>": instance is on database "replica", value is on database "default"

This happened on staging when executing giftCardCreate mutation. Apparently GiftCard instance was created on `replica` database and the Tag is created on `default` db.


Discussion:
Create an app with permissions MANAGE_APPS, MANAGE_GIFT_CARD 
Use app token and send mutation giftCardCreate

 ```
mutation{
    giftCardCreate(input:{
      addTags: "new" // I added this tag via dashboard for other gift card
      isActive: true
      balance: {
        currency: "PLN"
        amount: 45
      }
    }){
      errors{
        field
        message
      }
      giftCard{
        code
        id
        isActive
      }
    }
  }
```

response
```
{
    "errors": [
        {
            "message": "Cannot add \"<GiftCardTag: GiftCardTag object (716)>\": instance is on database \"replica\", value is on database \"default\"",
            "locations": [
                {
                    "line": 2,
                    "column": 5
                }
            ],
            "path": [
                "giftCardCreate"
            ],
            "extensions": {
                "exception": {
                    "code": "ValueError"
                }
            }
        }
    ],
    "data": {
        "giftCardCreate": null
    },
    "extensions": {
        "cost": {
            "requestedQueryCost": 0,
            "maximumAvailable": 50000
        }
    }
}
```
env. master.staging, v37.staging
To fix this we need to implement [a db router with proper `allow_relation`](https://docs.djangoproject.com/en/4.1/topics/db/multi-db/#allow_relation)

Resolving patch:
diff --git a/saleor/core/db_routers.py b/saleor/core/db_routers.py
new file mode 100644
--- /dev/null
+++ b/saleor/core/db_routers.py
@@ -0,0 +1,11 @@
+from django.conf import settings
+
+
+class PrimaryReplicaRouter:
+    def db_for_write(self, model, **hints):
+        """Write only to primary."""
+        return settings.DATABASE_CONNECTION_DEFAULT_NAME
+
+    def allow_relation(self, obj1, obj2, **hints):
+        """All relations are allowed as we don't have pool separation."""
+        return True
diff --git a/saleor/settings.py b/saleor/settings.py
--- a/saleor/settings.py
+++ b/saleor/settings.py
@@ -89,6 +89,8 @@ def get_bool_from_env(name, default_value):
     # ),
 }
 
+DATABASE_ROUTERS = ["saleor.core.db_routers.PrimaryReplicaRouter"]
+
 DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
 
 TIME_ZONE = "UTC"


Test patch:
Repository: saleor/saleor

Issue:
Unable to filter customers with 0 orders
### **Steps to reproduce the problem:**
```graphql
query Customers{
  customers(filter: {numberOfOrders: {lte: 0, gte: 0}},  first: 10){
    edges{
      node{
        id
        email
        orders{
          totalCount
        }
      }
    }
    totalCount
  }
}
```

### **Current result:**
Backend returns all customers instead of those with 0 orders

### **Expected result:**
Return all customers with 0 orders

### **Screenshots:**

### **System information:**

### **Environment:**
master.staging core v3.8.0-a

### **Additional info/links:**
https://master.staging.saleor.cloud/dashboard/customers/?asc=true&sort=name&numberOfOrdersFrom=0&numberOfOrdersTo=0


Discussion:
I would like to work on this bug, can you please assign this to me

Resolving patch:
diff --git a/saleor/graphql/utils/filters.py b/saleor/graphql/utils/filters.py
--- a/saleor/graphql/utils/filters.py
+++ b/saleor/graphql/utils/filters.py
@@ -21,10 +21,10 @@ def filter_by_period(queryset, period, field_name):
 
 def filter_range_field(qs, field, value):
     gte, lte = value.get("gte"), value.get("lte")
-    if gte:
+    if gte is not None:
         lookup = {f"{field}__gte": gte}
         qs = qs.filter(**lookup)
-    if lte:
+    if lte is not None:
         lookup = {f"{field}__lte": lte}
         qs = qs.filter(**lookup)
     return qs


Test patch:
diff --git a/saleor/graphql/core/tests/test_core.py b/saleor/graphql/core/tests/test_core.py
--- a/saleor/graphql/core/tests/test_core.py
+++ b/saleor/graphql/core/tests/test_core.py
@@ -446,6 +446,18 @@ def test_filter_range_field(value, count, product_indexes, product_list):
     assert list(result) == expected_products
 
 
+def test_filter_products_with_zero_discount(product_list):
+    product_list[0].channel_listings.update(discounted_price_amount=0)
+    qs = ProductChannelListing.objects.all().order_by("pk")
+    field = "discounted_price_amount"
+
+    result = filter_range_field(qs, field, {"lte": 0, "gte": 0})
+
+    expected_products = list(qs.filter(product=product_list[0]))
+    assert result.count() == 1
+    assert list(result) == expected_products
+
+
 def test_get_duplicated_values():
     values = ("a", "b", "a", 1, 1, 1, 2)
Repository: saleor/saleor

Issue:
Bug: Lack of validation in cleaning manifest data
### What are you trying to achieve?

The `KeyError` is raised when `manifest_data` doesn't have `tokenTargetUrl`.

### Steps to reproduce the problem

1. Run `AppFetchManifest` with URL that contains JSON data without `tokenTargetUrl`.
2. You will get the `KeyError`.

### What did you expect to happen?

The `ValidationError` should be raised.

### Logs

https://sentry.io/organizations/saleor/issues/3749157627/?project=6417854

### Environment

Saleor version: 3.9 (to check if it also affect other versions)


Discussion:

Resolving patch:
diff --git a/saleor/app/manifest_validations.py b/saleor/app/manifest_validations.py
--- a/saleor/app/manifest_validations.py
+++ b/saleor/app/manifest_validations.py
@@ -99,7 +99,8 @@ def clean_manifest_data(manifest_data):
 
     validate_required_fields(manifest_data, errors)
     try:
-        _clean_app_url(manifest_data["tokenTargetUrl"])
+        if "tokenTargetUrl" in manifest_data:
+            _clean_app_url(manifest_data["tokenTargetUrl"])
     except (ValidationError, AttributeError):
         errors["tokenTargetUrl"].append(
             ValidationError(


Test patch:
diff --git a/saleor/app/tests/test_installation_utils.py b/saleor/app/tests/test_installation_utils.py
--- a/saleor/app/tests/test_installation_utils.py
+++ b/saleor/app/tests/test_installation_utils.py
@@ -407,3 +407,28 @@ def test_install_app_webhook_incorrect_query(
     error_dict = excinfo.value.error_dict
     assert "webhooks" in error_dict
     assert error_dict["webhooks"][0].message == "Subscription query is not valid."
+
+
+def test_install_app_lack_of_token_target_url_in_manifest_data(
+    app_manifest, app_installation, monkeypatch, permission_manage_products
+):
+    # given
+    app_manifest.pop("tokenTargetUrl")
+
+    app_manifest["permissions"] = ["MANAGE_PRODUCTS"]
+    mocked_get_response = Mock()
+    mocked_get_response.json.return_value = app_manifest
+
+    monkeypatch.setattr(requests, "get", Mock(return_value=mocked_get_response))
+    mocked_post = Mock()
+    monkeypatch.setattr(requests, "post", mocked_post)
+
+    app_installation.permissions.set([permission_manage_products])
+
+    # when & then
+    with pytest.raises(ValidationError) as excinfo:
+        install_app(app_installation, activate=True)
+
+    error_dict = excinfo.value.error_dict
+    assert "tokenTargetUrl" in error_dict
+    assert error_dict["tokenTargetUrl"][0].message == "Field required."
Repository: saleor/saleor

Issue:
Bug: CUSTOMER_UPDATED webhook triggers for address actions 
### What are you trying to achieve?

I was testing triggers for the `CUSTOMER_UPDATED` webhook.

### Steps to reproduce the problem

Create a new app with webhook async Customer Update event trigger
Edit customer address -> webhook is triggered
Add a new address to user address book -> webhook is not triggered
Edit the newly created address -> webhook is triggered

### What did you expect to happen?

The generic `CUSTOMER_UPDATED` webhook is not triggered for address actions 


### Environment

Saleor version: 
dashboard v3.7.14
core v3.7.43
OS and version: …



Discussion:

Resolving patch:
diff --git a/saleor/graphql/account/mutations/base.py b/saleor/graphql/account/mutations/base.py
--- a/saleor/graphql/account/mutations/base.py
+++ b/saleor/graphql/account/mutations/base.py
@@ -334,7 +334,6 @@ def perform_mutation(cls, _root, info, **data):
             user.search_document = prepare_user_search_document_value(user)
             user.save(update_fields=["search_document", "updated_at"])
         manager = get_plugin_manager_promise(info.context).get()
-        cls.call_event(manager.customer_updated, user)
         address = manager.change_user_address(address, None, user)
         cls.call_event(manager.address_updated, address)
 
@@ -397,7 +396,6 @@ def perform_mutation(cls, _root, info, **data):
 
         response.user = user
         manager = get_plugin_manager_promise(info.context).get()
-        cls.call_event(manager.customer_updated, user)
         cls.call_event(manager.address_deleted, instance)
         return response
 


Test patch:
diff --git a/saleor/graphql/account/tests/test_account.py b/saleor/graphql/account/tests/test_account.py
--- a/saleor/graphql/account/tests/test_account.py
+++ b/saleor/graphql/account/tests/test_account.py
@@ -4488,7 +4488,7 @@ def test_customer_address_update_trigger_webhook(
 
     # then
     assert content["data"]["accountAddressUpdate"]
-    mocked_webhook_trigger.assert_called_with(
+    mocked_webhook_trigger.assert_called_once_with(
         *generate_address_webhook_call_args(
             address,
             WebhookEventAsyncType.ADDRESS_UPDATED,
@@ -4614,7 +4614,7 @@ def test_address_delete_mutation_trigger_webhook(
 
     # then
     assert content["data"]["addressDelete"]
-    mocked_webhook_trigger.assert_called_with(
+    mocked_webhook_trigger.assert_called_once_with(
         *generate_address_webhook_call_args(
             address,
             WebhookEventAsyncType.ADDRESS_DELETED,