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 Engine 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: Player A creates an account

Player A 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: Player A is automatically added to the playtest

Player A 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: Player A logs in

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: Player A requests an operator to update their account name

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.

Example: Player A requests for account deletion

Player A requests for their account to be deleted. This method can be used to define the logic to remove Player A 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 is unique account information from an identity provider:

PropertyTypeDescription
idProviderAccountRPC.IdProviderThe type of the identity provider (Steam, Epic, unsafe). See Identity Providers for more information.
accountIdStringUser ID from the identity provider.
displayNameStringThe player’s registered account name from the identity provider.
discriminatorStringUnique digits added to the end of usernames to identify the player’s account.

Update a player’s display name #

The AccountRpc.UpdateDisplayNameV1Request endpoint can be used for players to update their display name. The default Account Plugin prevents players from modifying their display name.

To enable players to edit their display name, do not throw the PragmaException from your custom Account Plugin. We recommend adding custom logic to restrict when players can update their display name.

override suspend fun updateDisplayName(
    requestedDisplayName: String,
    pragmaAccount: PragmaAccount
) {
    pragmaAccount.setDisplayName(requestedDisplayName)
    
    throw PragmaException(
        PragmaError.AccountService_DisplayNameUpdateNotAllowed,
        "Display name updating is not allowed"
    )
}
For more information on how players can edit their display name, see the Social Player Portal page.

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
getSocialIdentityRetrieve all account information. This includes data on account ID, display name, list of game identities, and identity providers.
getDisplayNameRetrieve the player’s registered account name.
getTagsRetrieve all player tags associated with the player’s account.
getGroupsRetrieve all player groups associated with the player’s account.
setDisplayNameSet a new display name for the player’s Pragma account.
addTagAdd a tag to the player’s account.
addGroupAdds a player to a group by the group’s unique ID.
removeTagRemove a tag from the player’s 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"