Links

Extending the Platform

This guide provides a quick overview of how to add to and extend the platform, using the example of adding a limitation to Beam claims on a default installation of the Platform Beam package.
Throughout the platform we have provided several places where you can hook in your own code to extend and customize the platform without having to fork and modify the core codebase. One such example is the addition of an adhocRules static property in the Beam Mutation base class. This property allows you to attach custom rules to the Beam mutations in order to provide some additional checks or limitations.
In this example we will add a new ValidationRule to the ClaimBeamMutation which will limit the number of claims a user can make based on their IP address and account. So a user will only be able to claim a Beam once per IP address or wallet account they are using.
As part of the Beam claim process we automatically store the IP address and wallet account that was used to make a claim in the database, because of this we can add a simple custom rule to check that IP addresses and wallet accounts used to make claims don't already exist in the database for a Beam.
To start off we create a standard Laravel ValidationRule (https://laravel.com/docs/10.x/validation#custom-validation-rules). We then add in the code that makes a query to the beam_claims table to see if the user's IP address or wallet account has already been stored for the Beam that are claiming. If it has we fail the validation test and return an error message. By adding this check as a validation rule in the input data of the ClaimBeam mutation itself, we can reject the claim early, before the GraphQL resolver has even run and the claim doesn't progress beyond this initial check.
<?php
namespace App\Rules;
use Closure;
use Enjin\Platform\Beam\Models\BeamClaim;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Arr;
class ClaimBeamPerUser implements DataAwareRule, ValidationRule
{
/**
* All the data under validation.
*
* @var array
*/
protected array $data = [];
/**
* Get the validation error message.
*
* @return string
*/
public function message(): string
{
return 'You have reached the maximum number of times you can claim this Beam.';
}
/**
* Set the data under validation.
*
* @param array $data
*
* @return $this
*/
public function setData($data): static
{
$this->data = $data;
return $this;
}
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$code = Arr::get($this->data, 'code');
$cap = 1;
if (BeamClaim::hasCode($code)
->where(
fn ($builder) => $builder
->where('wallet_public_key', $value)
->orWhere('ip_address', request()->getClientIp())
)
->count() >= $cap) {
$fail($this->message());
}
}
}
In the above code we are using a hard coded $cap of 1, this could be set via an ENV variable if you need it to be customizable without creating new builds.
Once you have created the validation rule you can assign it to the ClaimBeamMutation by adding it to its adhocRules array in the boot() method of your app's AppServiceProvider class. The following will ensure the rule is run against the account field that was supplied and its data will be passed to the validation rule for checking:
public function boot()
{
ClaimBeamMutation::$adhocRules = ['account' => [new ClaimBeamPerUser()]];
}
This is a simple example of how you can add rules to make additional checks without having to fork and change the core code of the Beam package. You could also include further checks if simply checking the user's IP address and wallet account isn't enough for your needs.
© 2023 Enjin Pte. Ltd.