Search Unity

Resolved How to delete entries (Cloud Code)

Discussion in 'Leaderboards' started by Brogan89, May 17, 2023.

  1. Brogan89

    Brogan89

    Joined:
    Jul 10, 2014
    Posts:
    244
    I'm wanting to use Cloud Code to delete player entries from all leaderboards as a part of a clean-up when deleting a player's account.

    I've found the web API docs but I'm hoping to do it via Cloud Code so it's cleaner / easier.

    I'm basing my code from the Leadboards with Cloud Code docs but I can't find any other API docs for unity-
    services/leaderboards-1.1
    so I'm not sure what methods are available to me.

    I want to do something like this

    Code (JavaScript):
    1. const { LeaderboardsApi } = require("@unity-services/leaderboards-1.1");
    2.  
    3. module.exports = async ({ params, context, logger }) => {
    4.   const { projectId } = context;
    5.   const { playerId } = params;
    6.   const leaderboardsApi = new LeaderboardsApi(context);
    7.  
    8.   await leaderboardsApi.deletePlayerScoreAcrossAllLeaderboards(playerId);
    9.   return { message: "ok" };
    10. };
    but obviously
    deletePlayerScoreAcrossAllLeaderboards
    isn't a valid method.
     
  2. EmilF_Unity

    EmilF_Unity

    Unity Technologies

    Joined:
    Jun 10, 2022
    Posts:
    18
    Hi Brogan89,

    the functionality in question is not available as part of the Cloud Code Leaderboards SDK, but you can call the API endpoint directly using Axios as documented here. Keeping in mind that as an admin endpoint it has lower rate limits than the player endpoints, but hopefully for your use-case of deleting player's accounts that will be fine.
     
    Brogan89 likes this.
  3. Brogan89

    Brogan89

    Joined:
    Jul 10, 2014
    Posts:
    244

    Hey, cool thanks for the suggestion. I got most of the way there.
    I'm getting auth issues though and I'm not sure why. I'm using
    serverToken
    , and the service account has "Leaderboards Admin" assigned to it.

    The Cloud Code I'm using is


    Code (JavaScript):
    1. const axios = require("axios-0.21");
    2.  
    3. module.exports = async ({ params, context, logger }) => {
    4.  
    5.   logger.debug(context);
    6.  
    7.   const { projectId, environmentId, accessToken, serviceToken } = context;
    8.   const { playerId } = params;
    9.  
    10.   let config = {
    11.     headers: {
    12.       Authorization: `Basic ${serviceToken}`
    13.     }
    14.   };
    15.  
    16.   let url = `https://services.api.unity.com/leaderboards/v1/projects/${projectId}/environments/${environmentId}/leaderboards/scores/players/${playerId}/purge`;
    17.   let result = await axios.delete(url, config);
    18.   return result.data;
    19. };
    And the response is (I've removed some IDs)


    Code (JavaScript):
    1. Invocation Error
    2. ------------------------------
    3. Error: Request failed with status code 401
    4.  
    5. {
    6.   "message": "Request failed with status code 401",
    7.   "name": "Error",
    8.   "request": {
    9.     "headers": {
    10.       "Accept": "application/json, text/plain, */*",
    11.       "Authorization": "Basic <TOKEN>",
    12.       "User-Agent": "axios/0.21.4"
    13.     },
    14.     "method": "delete",
    15.     "url": "https://services.api.unity.com/leaderboards/v1/projects/<PROJ_ID>/environments/<ENV_ID>/leaderboards/scores/players/KuT0GYspN7sxOACPhkQFuniMTMaX/purge"
    16.   },
    17.   "response": {
    18.     "code": 51,
    19.     "detail": "Authentication Failed",
    20.     "requestId": "f38bfcd8-ced9-4485-8447-e6a2a3ed7c14",
    21.     "status": 401,
    22.     "title": "Unauthorized",
    23.     "type": "https://services.docs.unity.com/docs/errors#51"
    24.   }
    25. }
    Not sure how I'm using the auth token wrong.
     
  4. EmilF_Unity

    EmilF_Unity

    Unity Technologies

    Joined:
    Jun 10, 2022
    Posts:
    18
    Hi Brogan89,

    unfortunately the built-in Cloud Code auth tokens will not work with admin endpoints like that, apologies for not clarifying earlier. To call admin endpoints like the one in question from Cloud Code we will need to use Service Account authentication as documented here.

    Service Account auth from within Cloud Code will involve the following steps:
    1. Create a Service Account
    2. Give it the "Leaderboards Admin" project role
    3. Create a key for the Service Account and make a note of the key ID and secret
    4. From within the Cloud Code script, pass in the Service Account credentials and use them with Basic auth in the request to Leaderboards instead of the Cloud Code service token
    The following is your script with the addition of the token exchange mechanism. Alex has provided an example below where the Service Account key ID and secret are passed in as script parameters "saKeyId" and "saSecret" respectively, along with the player ID to be purged (though that can also be the player ID from the Cloud Code context).

    Note that it is using the Axios
    auth
    config option which will automatically base64-encode and format the credentials as required for basic auth. Alternatively those can be formatted manually as outlined in the Service Account docs.

    Hope this helps!
     
    Last edited: May 30, 2023
  5. AlexGalbraithCF

    AlexGalbraithCF

    Joined:
    Aug 27, 2021
    Posts:
    8
    Looks like the leaderboard functions use basic auth. Here is a working script:
    Code (JavaScript):
    1. const axios = require("axios-0.21");
    2. module.exports = async ({ params, context, logger }) => {
    3.   logger.debug(context);
    4.   const { playerId, projectId, environmentId, accessToken, serviceToken } = context;
    5.   const { saKeyId, saSecret, playerIDToRemove } = params;
    6.   let url = `https://services.api.unity.com/leaderboards/v1/projects/${projectId}/environments/${environmentId}/leaderboards/scores/players/${playerIDToRemove}/purge`;
    7.  
    8.   let result = await axios({
    9.     method: 'DELETE',
    10.     url: url,
    11.     auth: {
    12.       username: saKeyId,
    13.       password: saSecret
    14.     },
    15.     headers: {
    16.       'Content-Type': 'application/json',
    17.     }
    18.   });
    19.   return result.data;
    20. };
     
    Last edited: May 30, 2023
    Brogan89 likes this.
  6. EmilF_Unity

    EmilF_Unity

    Unity Technologies

    Joined:
    Jun 10, 2022
    Posts:
    18
    Hi Alex,

    thank for spotting that, I was looking at the wrong gateway when putting that together (endpoints on
    leaderboards.services.api.unity.com/v1
    vs
    services.api.unity.com/leaderboards/v1
    ). The use of the token exchange is indeed unnecessary for this use case and Service Account credentials can be used directly. My apologies for any confusion, and I've updated my post to reference your example for any other users coming to this thread.
     
    Brogan89 likes this.
  7. Brogan89

    Brogan89

    Joined:
    Jul 10, 2014
    Posts:
    244
    Worked a treat! Thanks