Account Plugin #

The Account Plugin can be used to add custom behavior during the account lifecycle. The following are methods to manage account data:

MethodDescription
onAccountCreateCalled before an account has been created.
onAccountCreatedCalled after account creation.
onAccountLoginCalled after an account has signed in.
onAccountUpdateCalled when account information has changed.
onAccountDeleteCalled before an account is deleted.
onAccountDeletedCalled after account deletion.

Flow overview #

In this section we’ll demonstrate the Account Plugin’s flow by going through an example use case. Consider a scenario where a player creates an account for an early development game.

Account creation #

on Account Create

When a player attempts to log in, authenticateOrCreate is called. There are two possible scenarios after confirming the player’s identity with the third party provider:

  • If the player does not have an existing account, onAccountCreate is called and the returned account information is stored in the accounts database. After successful account creation, onAccountCreated is called. Then onAccountLogin is called.
  • If the player does have an existing Pragma Account, only onAccountLogin is called.
onAccountCreate must return a PragmaAccount object to write an account to the database. If this function throws an exception or nothing is returned, then an account will not be made.
Example: Display name length requirements

The player does not meet name requirements (minimum character length) and account creation is prevented by throwing an exception. Once the requirements are met, an account is successfully created.

override suspend fun onAccountCreate(
    idProviderAccount: IdProviderAccount
  ): PragmaAccount {
        if (idProviderAccount.displayName.length < 3) {
              throw PragmaException(
                  PragmaError.AccountService_Unauthorized,
                  "The display name is too short."
              )
        }
        if (idProviderAccount.displayName.length > 32) {
              throw PragmaException(
                  PragmaError.AccountService_Unauthorized,
                  "The display name is too long."
              )
        }
    return PragmaAccount(idProviderAccount.displayName)
}
Example: Automatically adding players to a playtest

The player creates an account and is automatically added to the beta access group so that they are allowed into the game during the testing time window.

override suspend fun onAccountCreated(pragmaAccount: PragmaAccount) {
    val betaAccessGroupId = UUID.fromString("6a7f81ec-42d2-4874-9a8e-092dd79c2627")
    pragmaAccount.addGroup(betaAccessGroupId)
}

Account login #

on Account Login

After a player has been authenticated, onAccountLogin is called. The player’s account information is sent as a parameter.

Example: Denying player login based on a tag

Player A successfully logs into the game.

Player B who has a tag on their account for suspicious activity is denied login by throwing an exception.

override suspend fun onAccountLogin(pragmaAccount: PragmaAccount) {
    if (pragmaAccount.getTags().any { it.tag == "suspicious-activity" }) {
        throw PragmaException(
            PragmaError.AccountService_Unauthorized,
            "This account is flagged for suspicious activity."
        )
    }
}

Account update #

on Account Update

When there is a request to update a player’s account information, onAccountUpdate is called. Here you can add custom logic to filter display names or reject certain display names.

Example: Limiting display name length

Player A requests for a name change. Their new name meets requirements and their account information is updated to reflect the name change.

Player B requests for a name change. Their new name exceeds the 32 character limit so their name is truncated.

override suspend fun onAccountUpdate(pragmaAccount: PragmaAccount) {
    if (pragmaAccount.getDisplayName().length > 32) {
        pragmaAccount.setDisplayName(pragmaAccount.getDisplayName().substring(0, 32))
    }
}

Account deletion #

on Account Deletion

When an operator deletes an account, onAccountDelete is called. Pragma Engine removes all standard account information. You’ll need to remove any additional account data you have stored. After successful account deletion, onAccountDeleted is called.

Deleting additional custom data

The player requests for their account to be deleted. This method can be used to define the logic to remove the player from the game’s custom leaderboard, any groups or guilds they were in, and all accompanying PII.

override suspend fun onAccountDelete(pragmaAccount: PragmaAccount) {
    val leaderboardGameShardId = UUID.fromString(
        "9c9efd2e-a7bd-4374-85b2-4a37d48db7b8"
    )
    val socialIdentity = pragmaAccount.getSocialIdentity() ?: return
    val playerGameIdentity = socialIdentity
        .gameIdentities
        .firstOrNull { it.gameShardId == leaderboardGameShardId }
        ?: return
    val result = service.requestRpc(
        LeaderboardRpc.DeletePlayerDataServiceV1Request.newBuilder()
            .setPlayerId(playerGameIdentity.pragmaPlayerId.toFixed128())
            .build(),
        LeaderboardRpc.DeletePlayerDataServiceV1Response::class)
    // ...
}
Example: Transfer guild ownership
Player A who was a guild leader has deleted their account. This method can be used to define logic to transfer custom guild ownership rights to another player.

Create an account #

The onAccountCreate function is called after account authentication, but before creation of a Pragma Social account. When onAccountCreate returns a PragmaAccount object, an account is created. Account creation can be prevented by throwing an exception.

The IdProviderAccount data class contains unique account information from an identity provider:

PropertyTypeDescription
idProviderAccountRPC.IdProviderenum type of the identity provider (STEAM, DISCORD). See Identity Providers for more information.
accountIdStringUser ID from the identity provider.
displayNameStringPlayer’s registered account name from the identity provider.
discriminatorStringSuffix to distinguish a player’s account with the same display name (Cerberus#0000, Cerberus#0001).

Update a player’s display name #

Players can update their display name by calling the AccountRpc.UpdateDisplayNameV1Request Player endpoint; the default Account Plugin prevents players from modifying their display name.

For more information on how players can edit their display name, see the Social Player Portal page.

We recommend adding custom logic to restrict when players can update their display name. To prevent players from editing their display name entirely, throw the PragmaException from your custom Account Plugin.

override suspend fun updateDisplayName(
    requestedDisplayName: String,
    pragmaAccount: PragmaAccount
) {
    pragmaAccount.setDisplayName(requestedDisplayName)
    
    throw PragmaException(
        PragmaError.AccountService_DisplayNameUpdateNotAllowed,
        "Display name updating is not allowed"
    )
}
Only the Player endpoint calls the AccountPlugin.updateDisplayName method; the Operator, Partner, and Service endpoints do not call updateDisplayName.

View display name last updated timestamp #

One restriction that can be set is how often a player can update their display name. To view when the player’s display name was last updated call pragmaAccount.getDisplayNameLastUpdated().

Pragma Account object #

The PragmaAccount is a mutable object that represents the current state of the player’s account information. Any changes made on the PragmaAccount object are saved.

All get requests are lazy loaded.
MethodDescription
getSocialIdentityRetrieves all account information. This includes data on account ID, display name, list of game identities, and identity providers.
getDisplayNameRetrieves the player’s registered account name.
getBansRetrieves a list of previously revoked and currently active bans associated with the player’s account.
getTagsRetrieves all player tags associated with the player’s Pragma Account.
getGroupsRetrieves all player groups associated with the player’s Pragma Account.
setDisplayNameSet a new display name for the player’s Pragma Account.
addTagAdd a tag to the player’s Pragma Account.
addGroupAdds a player to a group by the group’s unique ID.
removeTagRemove a tag from the player’s Pragma Account by the tag’s unique ID.
removeGroupRemove a player from a group by the group’s unique ID.

Create a custom Account Plugin #

To build off existing Account Plugin features, you’ll need to do the following:

  1. Implement the Account Plugin
  2. Configure your Account Plugin

Implement the Account Plugin #

To build your custom Account Plugin, you’ll need to implement the AccountPlugin interface:

class DemoAccountPlugin(
  val service: Service, 
  val contentDataNodeService: ContentDataNodeService
) : AccountPlugin {}

Configure the Account Plugin #

To enable your custom Account Plugin, you’ll need to add this config in your yaml:

social:
  pluginConfigs:
    AccountService.accountPlugin:
      class: "demo.account.DemoAccountPlugin"