1. Go to this page and download the library: Download jot/hf-shield library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
jot / hf-shield example snippets
return [
'token_format' => 'JWT', // token format. By default, JWT
'private_key' => '', // path or content of the private key
'public_key' => '', // path or content of the public key
'encryption_key' => '', // string for data encryption
'token_days' => 'P1D', // token validity in PHP DateTimeInterval format
'refresh_token_days' => 'P1M', // refresh token validity in PHP DateTimeInterval format
'revoke_user_old_tokens' => true, // enables trigger that revokes previous user/client tokens
];
#[Scope(allow: 'service:resource:permission')]
public function myAction(string $id): PsrResponseInterface {
// ...
}
#[Middleware(middleware: BearerStragegy::class)]
declare(strict_types=1);
use Hyperf\Context\ApplicationContext;
use Jot\HfElastic\Migration;
use Jot\HfElastic\Migration\Mapping;
return new class(ApplicationContext::getContainer()) extends Migration {
public const INDEX_NAME = 'my_awesome_index';
public bool $addPrefix = true;
public function up(): void
{
$index = new Mapping(name: self::INDEX_NAME, dynamic: 'strict');
$index->keyword('id');
$index->keyword('name')->normalizer('normalizer_ascii_lower');
$index->alias('my_awesome_index_id')->path('id');
$index->defaults();
$index->settings(
[
'index' => [
'number_of_shards' => 1,
'number_of_replicas' => 0,
],
'analysis' => [
'normalizer' => [
'normalizer_ascii_lower' => [
'type' => 'custom',
'char_filter' => [
],
'filter' => [
0 => 'asciifolding',
1 => 'lowercase',
],
],
],
],
]
);
$this->create($index);
}
public function down(): void
{
$this->delete(self::INDEX_NAME);
}
};
declare(strict_types=1);
use Hyperf\Context\ApplicationContext;
use Jot\HfElastic\Migration;
use Jot\HfElastic\Migration\Mapping;
use Jot\HfElastic\Migration\ElasticType\NestedType;
use Jot\HfElastic\Migration\ElasticType\ObjectType;
return new class(ApplicationContext::getContainer()) extends Migration {
public const INDEX_NAME = 'my_users';
public bool $addPrefix = true;
public function up(): void
{
$index = new Mapping(name: self::INDEX_NAME, dynamic: 'strict');
$index->addField('keyword', 'id');
$index->addField('keyword', 'name');
$index->addField('keyword', 'email');
$index->addField('long', 'age');
$index->addField('double', 'salary');
$index->addField('boolean', 'active');
$address = new ObjectType('address');
$address->addField('keyword', 'line1');
$address->addField('keyword', 'line2');
$address->addField('keyword', 'city');
$address->addField('keyword', 'state');
$address->addField('keyword', 'country');
$index->object($address);
$last_attempt_logins = new NestedType('last_attempt_logins');
$last_attempt_logins->addField('date', 'datetime');
$last_attempt_logins->addField('ip', 'ip_address');
$last_attempt_logins->addField('keyword', 'user_agent');
$last_attempt_logins->addField('keyword', 'status');
$last_attempt_logins->addField('keyword', 'error');
$index->nested($last_attempt_logins);
$index->alias('my_user_id')->path('id');
$index->defaults();
$index->settings(
[
'index' => [
'number_of_shards' => 1,
'number_of_replicas' => 0,
],
'analysis' => [
'normalizer' => [
'normalizer_ascii_lower' => [
'type' => 'custom',
'char_filter' => [
],
'filter' => [
0 => 'asciifolding',
1 => 'lowercase',
],
],
],
],
]
);
$this->create($index);
}
public function down(): void
{
$this->delete(self::INDEX_NAME);
}
};
declare(strict_types=1);
namespace App\Controller\V2;
use App\Service\MyUserService;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\RateLimit\Annotation\RateLimit;
use Hyperf\Swagger\Annotation as SA;
use Jot\HfShield\Annotation\Scope;
use Jot\HfShield\Middleware\SessionStrategy;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
#[SA\HyperfServer('http')]
#[SA\Tag(
name: 'MyUser',
description: 'Endpoints related to my_users management'
)]
#[SA\Schema(
schema: 'admin.error.response',
te const RESPONSE_SCHEMA_CONTENT = '#/components/schemas/app.entity.my_user.my_user';
private const RESPONSE_SCHEMA_ERROR = '#/components/schemas/admin.error.response';
#[Inject]
protected MyUserService $service;
#[SA\Get(
path: self::REQUEST_PATH,
description: 'Retrieve a list of my_users with optional pagination and filters.',
summary: 'Get MyUsers List',
security: [['shieldBearerAuth' => ['admin:my_user:list']]],
tags: ['MyUser'],
parameters: [
new SA\Parameter(
name: self::QUERY_PAGE_NUMBER,
description: self::DESCRIPTION_PAGE_NUMBER,
in: 'query',
e: 'array',
items: new SA\Items(ref: self::RESPONSE_SCHEMA_CONTENT)
),
new SA\Property(
property: 'result',
type: 'string',
example: 'success'
),
new SA\Property(
property: 'error',
type: 'string',
example: null,
nullable: true
),
],
type: 'object'
)
),
new SA\Response(
response: 400,
description: self::DESCRIPTION_BAD_REQUEST,
content: new SA\JsonContent(ref: self::RESPONSE_SCHEMA_ERROR)
),
new SA\Response(
response: 401,
description: self::DESCRIPTION_UNAUTHORIZED_ACCESS,
content: new SA\JsonContent(ref: self::RESPONSE_SCHEMA_ERROR)
),
new SA\Response(
response: 403,
description: self::DESCRIPTION_FORBIDDEN_ACCESS,
content: new SA\JsonContent(ref: self::RESPONSE_SCHEMA_ERROR)
),
new SA\Response(
response: 500,
description: self::DESCRIPTION_APPLICATION_ERROR,
content: new SA\JsonContent(ref: self::RESPONSE_SCHEMA_ERROR)
),
]
)]
#[RateLimit(create: 1, capacity: 10)]
#[Scope(allow: 'admin:my_user:list')]
#[Middleware(middleware: SessionStrategy::class)]
public function getMyUserList(): PsrResponseInterface
{
$result = $this->service->paginate($this->request->query());
if ($result['result'] === 'error') {
return $this->response->withStatus(400)->json($result);
}
return $this->response
->withHeader('Access-Control-Allow-Origin', '*')
->json($result);
}
#[SA\Get(
path: self::REQUEST_PATH_ID,
description: 'Retrieve the details of a specific my_users identified by ID.',
summary: 'Get MyUser Data',
security: [['shieldBearerAuth' => ['admin:my_user:view']]],
tags: ['MyUser'],
parameters: [
new SA\Parameter(
name: 'id',
description: self::DESCRIPTION_PARAMETER_ID,
in: 'path',
CESS,
content: new SA\JsonContent(ref: self::RESPONSE_SCHEMA_ERROR)
),
new SA\Response(
response: 500,
description: self::DESCRIPTION_APPLICATION_ERROR,
content: new SA\JsonContent(ref: self::RESPONSE_SCHEMA_ERROR)
),
]
)]
#[RateLimit(create: 1, capacity: 5)]
#[Scope(allow: 'admin:my_user:create')]
#[Middleware(middleware: SessionStrategy::class)]
public function createMyUser(): PsrResponseInterface
{
$result = $this->service->create($this->request->all());
return $this->response->withStatus(201)->json($result);
}
#[SA\Put(
path: self::REQUEST_PATH_ID,
description: 'Update the details of an existing my_users.',
summary: 'Update an existing MyUser',
security: [['shieldBearerAuth' => ['admin:my_user:update']]],
requestBody: new SA\RequestBody(
MyUser(string $id): PsrResponseInterface
{
$result = $this->service->delete($id);
return $this->response->json($result);
}
#[SA\Head(
path: self::REQUEST_PATH_ID,
description: 'Check if a valid my_users exists by its unique identifier.',
summary: 'Check my_users',
security: [['shieldBearerAuth' => ['admin:my_user:verify']]],
tags: ['MyUser'],
parameters: [
new SA\Parameter(
name: 'id',
description: 'Unique identifier of the my_users',
in: 'path',