Repository: saleor/saleor

Issue:
Add query for changing user email, firstName, lastName
Please add mutation which adds posibility to modify users email, firstName, lastName


Discussion:
It should be done by changing input for: `loggedUserUpdate(input: UserAddressInput!): LoggedUserUpdate`

Resolving patch:
diff --git a/saleor/graphql/account/mutations.py b/saleor/graphql/account/mutations.py
--- a/saleor/graphql/account/mutations.py
+++ b/saleor/graphql/account/mutations.py
@@ -116,6 +116,17 @@ class StaffInput(UserInput):
     )
 
 
+class AccountInput(graphene.InputObjectType):
+    first_name = graphene.String(description="Given name.")
+    last_name = graphene.String(description="Family name.")
+    default_billing_address = AddressInput(
+        description="Billing address of the customer."
+    )
+    default_shipping_address = AddressInput(
+        description="Shipping address of the customer."
+    )
+
+
 class StaffCreateInput(StaffInput):
     send_password_email = graphene.Boolean(
         description="Send an email with a link to set a password"
@@ -245,7 +256,33 @@ class Arguments:
         )
 
     class Meta:
-        description = "Updates data of the logged in user."
+        description = (
+            "DEPRECATED: Use AccountUpdate instead. "
+            "Updates data of the logged in user."
+        )
+        exclude = ["password"]
+        model = models.User
+
+    @classmethod
+    def check_permissions(cls, user):
+        return user.is_authenticated
+
+    @classmethod
+    def perform_mutation(cls, root, info, **data):
+        user = info.context.user
+        data["id"] = graphene.Node.to_global_id("User", user.id)
+        return super().perform_mutation(root, info, **data)
+
+
+class AccountUpdate(CustomerCreate):
+    class Arguments:
+        input = AccountInput(
+            description="Fields required to update the account of the logged-in user.",
+            required=True,
+        )
+
+    class Meta:
+        description = "Updates the account of the logged-in user."
         exclude = ["password"]
         model = models.User
 
diff --git a/saleor/graphql/account/schema.py b/saleor/graphql/account/schema.py
--- a/saleor/graphql/account/schema.py
+++ b/saleor/graphql/account/schema.py
@@ -8,6 +8,7 @@
 from .enums import CountryCodeEnum
 from .filters import CustomerFilter, StaffUserFilter
 from .mutations import (
+    AccountUpdate,
     AddressCreate,
     AddressDelete,
     AddressSetDefault,
@@ -109,6 +110,7 @@ class AccountMutations(graphene.ObjectType):
     customer_set_default_address = CustomerSetDefaultAddress.Field()
 
     logged_user_update = LoggedUserUpdate.Field()
+    account_update = AccountUpdate.Field()
 
     staff_create = StaffCreate.Field()
     staff_delete = StaffDelete.Field()


Test patch:
diff --git a/tests/api/test_account.py b/tests/api/test_account.py
--- a/tests/api/test_account.py
+++ b/tests/api/test_account.py
@@ -820,6 +820,55 @@ def test_customer_update_without_any_changes_generates_no_event(
     assert not account_events.CustomerEvent.objects.exists()
 
 
+ACCOUNT_UPDATE_QUERY = """
+    mutation accountUpdate(
+            $billing: AddressInput, $shipping: AddressInput, $firstName: String,
+            $lastName: String) {
+        accountUpdate(
+          input: {
+            defaultBillingAddress: $billing,
+            defaultShippingAddress: $shipping,
+            firstName: $firstName,
+            lastName: $lastName,
+        }) {
+            errors {
+                field
+                message
+            }
+            user {
+                firstName
+                lastName
+                email
+                defaultBillingAddress {
+                    id
+                }
+                defaultShippingAddress {
+                    id
+                }
+            }
+        }
+    }
+"""
+
+
+def test_logged_customer_update_names(user_api_client):
+    first_name = "first"
+    last_name = "last"
+    user = user_api_client.user
+    assert user.first_name != first_name
+    assert user.last_name != last_name
+
+    variables = {"firstName": first_name, "lastName": last_name}
+    response = user_api_client.post_graphql(ACCOUNT_UPDATE_QUERY, variables)
+    content = get_graphql_content(response)
+    data = content["data"]["accountUpdate"]
+
+    user.refresh_from_db()
+    assert not data["errors"]
+    assert user.first_name == first_name
+    assert user.last_name == last_name
+
+
 UPDATE_LOGGED_CUSTOMER_QUERY = """
     mutation UpdateLoggedCustomer($billing: AddressInput,
                                   $shipping: AddressInput) {
@@ -846,7 +895,16 @@ def test_customer_update_without_any_changes_generates_no_event(
 """
 
 
-def test_logged_customer_update(user_api_client, graphql_address_data):
+@pytest.mark.parametrize(
+    "query, mutation_name",
+    [
+        (UPDATE_LOGGED_CUSTOMER_QUERY, "loggedUserUpdate"),
+        (ACCOUNT_UPDATE_QUERY, "accountUpdate"),
+    ],
+)
+def test_logged_customer_update_addresses(
+    user_api_client, graphql_address_data, query, mutation_name
+):
     # this test requires addresses to be set and checks whether new address
     # instances weren't created, but the existing ones got updated
     user = user_api_client.user
@@ -856,9 +914,9 @@ def test_logged_customer_update(user_api_client, graphql_address_data):
     assert user.default_billing_address.first_name != new_first_name
     assert user.default_shipping_address.first_name != new_first_name
     variables = {"billing": graphql_address_data, "shipping": graphql_address_data}
-    response = user_api_client.post_graphql(UPDATE_LOGGED_CUSTOMER_QUERY, variables)
+    response = user_api_client.post_graphql(query, variables)
     content = get_graphql_content(response)
-    data = content["data"]["loggedUserUpdate"]
+    data = content["data"][mutation_name]
     assert not data["errors"]
 
     # check that existing instances are updated
@@ -872,8 +930,11 @@ def test_logged_customer_update(user_api_client, graphql_address_data):
     assert user.default_shipping_address.first_name == new_first_name
 
 
-def test_logged_customer_update_anonymous_user(api_client):
-    response = api_client.post_graphql(UPDATE_LOGGED_CUSTOMER_QUERY, {})
+@pytest.mark.parametrize(
+    "query", [(UPDATE_LOGGED_CUSTOMER_QUERY), (ACCOUNT_UPDATE_QUERY)]
+)
+def test_logged_customer_update_anonymous_user(api_client, query):
+    response = api_client.post_graphql(query, {})
     assert_no_permission(response)