Repository: saleor/saleor

Issue:
Product permissions are not properly checked for service accounts
### What I'm trying to achieve
I want to access all products using service account. 

### Steps to reproduce the problem
1. Configure service account
2. Create unpublished product
3. Fetch product using service account token

### What I expected to happen
Query returns existing product, it fails to find it instead.

---

### Analysis
We do check product visibility based on users permissions: https://github.com/mirumee/saleor/blob/b0a0a04b4e0ab228f354b7d0b8b9023dfa096787/saleor/core/models.py#L53-L56
This does not work for service accounts because _user_ is anonymous on this level.
In mutation we have this issue covered with:
https://github.com/mirumee/saleor/blob/b0a0a04b4e0ab228f354b7d0b8b9023dfa096787/saleor/graphql/core/mutations.py#L268-L270

### Solution
One of two solutions could be applied:
- inject sevice account into _user_ and let all standard permission check pass, this introduces problem with possible attempt to fetch any user context data in application
- always check for service account OR user permission in resolvers


Discussion:

Resolving patch:
diff --git a/saleor/graphql/product/resolvers.py b/saleor/graphql/product/resolvers.py
--- a/saleor/graphql/product/resolvers.py
+++ b/saleor/graphql/product/resolvers.py
@@ -142,6 +142,8 @@ def resolve_products(
 ):
 
     user = info.context.user
+    if user.is_anonymous and info.context.service_account:
+        user = info.context.service_account
     qs = models.Product.objects.visible_to_user(user)
     qs = sort_products(qs, sort_by)
 


Test patch:
diff --git a/tests/api/test_product.py b/tests/api/test_product.py
--- a/tests/api/test_product.py
+++ b/tests/api/test_product.py
@@ -86,26 +86,43 @@ def query_categories_with_filter():
     return query
 
 
-def test_fetch_all_products(user_api_client, product):
-    query = """
+QUERY_FETCH_ALL_PRODUCTS = """
     query {
         products(first: 1) {
             totalCount
             edges {
                 node {
-                    id
+                    name
+                    isPublished
                 }
             }
         }
     }
-    """
-    response = user_api_client.post_graphql(query)
+"""
+
+
+def test_fetch_all_products(user_api_client, product):
+    response = user_api_client.post_graphql(QUERY_FETCH_ALL_PRODUCTS)
     content = get_graphql_content(response)
     num_products = Product.objects.count()
     assert content["data"]["products"]["totalCount"] == num_products
     assert len(content["data"]["products"]["edges"]) == num_products
 
 
+def test_fetch_all_products_service_account(
+    service_account_api_client,
+    service_account,
+    unavailable_product,
+    permission_manage_products,
+):
+    service_account.permissions.add(permission_manage_products)
+    response = service_account_api_client.post_graphql(QUERY_FETCH_ALL_PRODUCTS)
+    content = get_graphql_content(response)
+    product_data = content["data"]["products"]["edges"][0]["node"]
+    assert product_data["name"] == unavailable_product.name
+    assert product_data["isPublished"] == unavailable_product.is_published
+
+
 def test_fetch_unavailable_products(user_api_client, product):
     Product.objects.update(is_published=False)
     query = """