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.
Last modified 2mo ago