hirschen / rest
Requires
- php: ^7.1.0
- ext-json: *
- friendsofsymfony/rest-bundle: ^2.5
- friendsofsymfony/user-bundle: ~2.1
- gesdinet/jwt-refresh-token-bundle: 0.8.1
- incenteev/composer-parameter-handler: ^2.1
- jms/serializer-bundle: ^2.4
- lexik/jwt-authentication-bundle: ^2.4
- sensio/framework-extra-bundle: ^5.4
- symfony/console: 4.3.*
- symfony/dotenv: 4.3.*
- symfony/flex: ^1.3.1
- symfony/monolog-bundle: ^3.1.0
- symfony/polyfill-apcu: ^1.0
This package is not auto-updated.
Last update: 2025-03-11 18:22:19 UTC
README
This package provides functionality for Authentification(JWT), Serialization, Validation, Parameter Conversion etc. Additionally several constants, helper-classes and services are defined to support building a standardized Rest API. Exceptions are catched via a listener and serialized into a json response.
Configure Symfony Bundle
https://symfony.com/doc/current/bundles/best_practices.html
Learn more about Friends of Symfony
FOS User
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.rst
FOS REST
https://symfony.com/doc/current/bundles/FOSRestBundle/index.html
Learn more about Lexik (JWT Management)
https://github.com/markitosgv/JWTRefreshTokenBundle
Installation
composer require hirschen/rest
Add bundle to bundles.php
<?php
return [
...
Hirschen\Rest\HirschenRestBundle::class => ['all' => true],
...
];
Create private and public key and reference them in your .env
###> lexik/jwt-authentication-bundle ###
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
JWT_PASSPHRASE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Add refresh route to routes.yml
gesdinet_jwt_refresh_token:
path: /api/auth/refresh
controller: gesdinet.jwtrefreshtoken::refresh
Add Hirschen/Rest serialization service to services.yml
Hirschen\Rest\Service\ParamConverter\SerializerService:
autowire: false
public: true
arguments:
- "@fos_rest.serializer"
- "@fos_rest.validator"
- "validationErrors"
- "@doctrine_mongodb.odm.document_manager"
- '@Hirschen\Rest\Service\User\UserService'
In config/packages
In gesdinet_jwt_refresh_token.yaml
gesdinet_jwt_refresh_token:
user_provider: fos_user.user_provider.username_email
object_manager: doctrine_mongodb.odm.document_manager
ttl_update: true
manager_type: mongodb
In lexik_jwt_authentication.yaml (Link env vars)
lexik_jwt_authentication:
secret_key: '%env(resolve:JWT_SECRET_KEY)%' # required for token creation
public_key: '%env(resolve:JWT_PUBLIC_KEY)%' # required for token verification
pass_phrase: '%env(resolve:JWT_PASSPHRASE)%' # required for token creation, usage of an environment variable is recommended
token_ttl: 5184000 # 60 days
user_identity_field: email
In the security.yaml
- Add Encoders and Providers
- Add guard for routes that need to be guarded
- Add Login Route
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
...
...
api:
pattern: ^/api
stateless: true
provider: fos_userbundle
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
...
...
login:
pattern: ^/api/login
stateless: true
anonymous: true
logout: true
provider: fos_userbundle
form_login:
check_path: /api/login
success_handler: user.authentication_success_handler
failure_handler: lexik_jwt_authentication.handler.authentication_failure
require_previous_session: false
username_parameter: email
password_parameter: password
Add exception controller in fos_rest.yaml
# Read the documentation: https://symfony.com/doc/master/bundles/FOSRestBundle/index.html
fos_rest:
body_listener: true
body_converter:
enabled: true
validate: true
validation_errors_argument: validationErrors
format_listener:
rules:
- { path: '^/', priorities: ['json'], fallback_format: json, prefer_extension: false }
param_fetcher_listener: true
exception:
enabled: true
exception_controller: 'Hirschen\Rest\Controller\ExceptionController::showAction'
view:
view_response_listener: 'force'
formats:
json: true
Validated Serialization and Paramconversion
Summary (How does it work)
- Json request is serialized into a PHP object
- The object is validated https://symfony.com/doc/current/validation.html#constraint-configuration
- If the object is an Document (ODM) and a primary key is set (id in most cases) proceed to 4. otherwise skip to 5.
- Fetch existing document from DB and sync it with given input. Pass the fetched (updated) document to 5.
- Add object to the arguments of the controller action
Following Annotations triggers the functionality above
use Hirschen\Rest\Annotation\Parameter;
...
class UserController extends BaseController
{
/**
* @Rest\Post("/create", name="admin_user_create")
* @Parameter("user", {"Group 1","Group 2"})
*/
public function x(User $user...): Response
...
The first argument of the Parameter Annotation is required in order to map it to the arguments of the controller function. In this case, "user" is mapped to $user. The second argument is a string array containing the Groups necessary to determine the scope of the serialization and validation done by this package. By type-hinting the argument in the controller action the serializer recognizes the object type.
When the controller action starts, the json is already serialized and validated ($user). If $user is a new document, it is ready to be persisted. If it is an exisiting document, the old document was already fetched, updated and set to $user.
By tagging the atrributes of the objects or documents with groups, the Parameter Annotation can determine the right scope for serialization and custom validation.
/**
* @Assert\NotBlank(groups={"Group 2", "Group 3"})
* @Groups({"Group 1","Group 2", "Group 3","Group 4" })
* @Serializer\Type("string")
*/
protected $attribute;