question

Kim Strasser avatar image
Kim Strasser asked

Is it possible that a player updates his PlayFab data without my permission?

I don't want that a player updates his country data and display name frequently. I use this code to create the data. For example:

var resultprofile = await PlayFabClientAPI.UpdateUserDataAsync(new UpdateUserDataRequest()
{
    Data = new Dictionary<string, string>() {
    {"Country", "Germany"}
    }
});

var resultupdate = await PlayFabClientAPI.UpdateUserTitleDisplayNameAsync(new UpdateUserTitleDisplayNameRequest()
{
    DisplayName = "Bart Simpson"
});

You can enter your PlayFab display name and country in my application when you start it the first time. Then, this code is executed. After that, it is no more possible to run this code in my application. But would it still be possible that a player could update the country data and display name somehow because it is always allowed in the Client Profile Options in Game Manager?

Is it possible to only allow creating/updating the PlayFab display name and country once(when the player starts the game the very first time)?

If not, is it at least possible to reduce updating it at once a month?

EDIT:

I get another error message. What is wrong with PlayerProfile?

Raw event JSON
{
    "EventName": "player_executed_cloudscript",
    "Source": "CloudScript",
    "FunctionName": "UpdateDisplayname",
    "CloudScriptExecutionResult": {
        "FunctionName": "UpdateDisplayname",
        "Revision": 20,
        "FunctionResult": null,
        "FunctionResultTooLarge": null,
        "Logs": [],
        "LogsTooLarge": null,
        "ExecutionTimeSeconds": 0.024806699999999998,
        "ProcessorTimeSeconds": 0,
        "MemoryConsumedBytes": 40784,
        "APIRequestsIssued": 1,
        "HttpRequestsIssued": 0,
        "Error": {
            "Error": "JavascriptException",
            "Message": "JavascriptException",
            "StackTrace": "TypeError: Cannot read property 'PlayerProfile' of undefined\n    at handlers.UpdateDisplayname (BFD0A-main.js:9:32)"
        }
    },
    "EventNamespace": "com.playfab",
    "EntityType": "player",
    "TitleId": "BFD0A",
    "EntityId": "A8C95897B42FE00A",
    "EventId": "6c8d1d5e2dcf404c981cc5780948a2c2",
    "SourceType": "BackEnd",
    "Timestamp": "2019-09-18T11:12:41.9851659Z",
    "History": null,
    "CustomTags": null,
    "Reserved": null,
    "PlayFabEnvironment": {
        "Vertical": "master",
        "Cloud": "main",
        "Application": "logicserver",
        "Commit": "41925c5"
    }
}

My cloudScript:

handlers.UpdateDisplayname = function (args, context)
{
   var NewDisplayname = args.DesiredDisplayname;
   
   var resultprofile = server.GetPlayerProfile({PlayFabID: currentPlayerId, ProfileConstraints: {ShowDisplayName: true}})
   var CurrentDisplayName = "";
   if (resultprofile.Error == null)
   {
      if (resultprofile.Result.PlayerProfile != null)
      {
        CurrentDisplayName = resultprofile.Result.PlayerProfile.DisplayName;
       
      if ((CurrentDisplayName == null) || (CurrentDisplayName == ""))
       UpdateUserTitleDisplayNameFromCloudScript(NewDisplayname, currentPlayerId);
      else
        log.info("You already have a display name. It's not possible to change it:" + CurrentDisplayName.toString());
      }
   }
}

function UpdateUserTitleDisplayNameFromCloudScript(DesiredDisplayname, PlayFabId)
{
    var contentBodyTemp = {
        "DisplayName": DesiredDisplayname,
        "PlayFabId": PlayFabId
    };
    
    let url = "https://BFD0A.playfabapi.com/Admin/UpdateUserTitleDisplayName";
    let method = "POST";
    let contentBody = `{"PlayFabId": "${PlayFabId}", "DisplayName": "${DesiredDisplayname}"}`;
    let contentType = "application/json";
    let headers = { "X-SecretKey": "..." };
    let responseString = http.request(url, method, contentBody, contentType, headers);
    let responseJSONObj = JSON.parse(responseString);
    return (responseJSONObj.data);
}

Client code:

 private async Task UpdateDisplayname()
 {
     var result = await PlayFabClientAPI.ExecuteCloudScriptAsync(new ExecuteCloudScriptRequest()
     {
         FunctionName = "UpdateDisplayname",
         FunctionParameter = new { DesiredDisplayname = "Mynewdisplayname" },
         GeneratePlayStreamEvent = true
     });

     if (result.Error != null)
         Console.WriteLine(result.Error.Error.ToString());
     else
         Console.WriteLine("Your new displayname: " + "Mynewdisplayname");
 }
Player Data
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

1 Answer

·
Citrus Yan avatar image
Citrus Yan answered

Hi Kim,

>>But would it still be possible that a player could update the country data and display name somehow because it is always allowed in the Client Profile Options in Game Manager?

Yes, it’s possible that a player could update the country data and display name once he were able to get the needed info (SessionTicket would be enough for this case) to make API calls by himself.

And there is one thing to clarify, UpdateUserTitleDisplayName API always works even if the “Display name” option is checked in the Client Profile Options. Client Profile Options controls the access to profile properties(for instance, GetPlayerProfile won’t be able to return display name if you don’t allow it) but does not control changes to them.

>> Is it possible to only allow creating/updating the PlayFab display name and country once(when the player starts the game the very first time)?

Yes, it’s possible. However, it’s hard to implement this solely depending on the clients since they cannot be trusted. You need a bit of help from the server. Regarding creating/updating the PlayFab display name, here is the basic workflow for you:

1)use UpdatePolicy API to disable UpdateUserTitleDisplayName API from the client.

2)Write a function in CloudScript responsible for updating the player’s display name. In this function, first checks whether the player already has a display name, return immediately if he does, else update his display name.

3)From the client, make ExecuteCloudScript API call with required parameters(such as display name) to update the player’s display name.

Regarding creating/updating country, I noticed that you were using UpdateUserData API, disabling it will certainly affect operations on other user data of your players. It’s probably better for you to use the server API UpdateUserReadOnlyData to create, update, or delete county info and the Client API GetUserReadOnlyData to read it for the player. This data is visible to the player, but can only be modified by the server. Apart from this, the basic workflow for creating/updating country is pretty much the same as the one for display name talked before.

6 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Kim Strasser avatar image Kim Strasser commented ·

I don't know how to write a function in CloudScript for updating the player's display name. My cloud script always fails: https://community.playfab.com/questions/33810/problem-with-updating-player-display-name-with-clo.html

Do you have a working cloudScript example for updating the player's display name?

I have not understand if I need to write a function in CloudScript for creating/updating the player's country. Should I use UpdateUserReadOnlyData to create/update the player's country info and GetUserReadOnlyData to read/display the country info in my client code? Is it not necessary to write a function in cloudScript for creating/updating the country info?

0 Likes 0 ·
Citrus Yan avatar image Citrus Yan Kim Strasser commented ·

Hi, in order to check whether the player's DisplayName is null you must get it first, you can use server.GetPlayerProfile() to retrieve it. I noticed that you are not able to call UpdateUserTitleDisplayName in CloudScript since it's not included in server API set, a workaround for you is to write a POST request to make the call, you can refer to this thread where kamyker posted a example of calling GetStoreItems. Calling UpdateUserTitleDisplayName should work the same.

>>Should I use UpdateUserReadOnlyData to create/update the player's country info and GetUserReadOnlyData to read/display the country info in my client code?Is it not necessary to write a function in cloudScript for creating/updating the country info?

If you don't want the players to change their info from the client, then you may need to save it as Read Only Data. Since UpdateUserReadOnlyData only exists in Admin or Server set, it's necessary for you to write a function in CloudScript to creat/update the country info.

0 Likes 0 ·
Kim Strasser avatar image Kim Strasser Citrus Yan commented ·

I edited my question with my new code. How can I change the GetStoreItems POST request code from this thread to UpdateUserTitleDisplayName POST request code?

0 Likes 0 ·
Show more comments

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.