FOSElasticaBundle - JMSSerializerBundle exclusion strategies not functioning on FOSUserBundle User entity - symfony

I'm using the FOSElasticaBundle with the orm persistence driver and the JMSSerializerBundle serializer.
My users are managed by the FOSUserBundle and I'm trying to index these but exclude some fields such as password.
The JMSSerializerBundle exclusion policies such as #ExclusionPolicy("all") #Expose #Exclude are are not having any affect when added to my User entity, which extends FOS\UserBundle\Model\User. However these strategies work as expected on my other entities.
How do I stop fields such as 'salt' and 'password' from being added to the Elasticsearch index?

As a workaround I'm using the 'query_builder_method' FOSElasticaBundle configuration setting to call a method that creates a queryBuilder, which uses DQL Partial Object Syntax to only select the fields that I want to be indexed.
Here's some helpful links:
DQL Partial Object Syntax:
http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html#partial-object-syntax
Use a Custom Doctrine Query Builder:
https://github.com/FriendsOfSymfony/FOSElasticaBundle#use-a-custom-doctrine-query-builder

This is a know thing with Serializer and annotations. You have to define the exclusion strategy also on the parent (=FOS UserBundle) model.
I have solved it with additional yaml configuration:
This is my config:
jms_serializer:
metadata:
directories:
- { path: %kernel.root_dir%/Resources/serializer/FOS, namespace_prefix: 'FOS\UserBundle' }
And within that folder I have for example a User.Model.yml with this content:
FOS\UserBundle\Model\User:
exclusion_policy: ALL
properties:
email:
expose: true

Related

Api-Platform with multiple data sources, how to map entity with Doctrine OR ElasticSearch

Api-Platform: v2.5.6, Symfony: v4.4.11
I am building an API with multiple DataSource. For now, one from Postgres, another from ElasticSearch.
For example, I have an Organization entity from postgres and a Stats entity from ElasticSearch.
If ElasticSearch service isn't reachable, I would like the /organizations route to be ok because they don't need ElasticSearch to work.
For now I get "No alive nodes found in your cluster" because it tries to communicate with the "/_cat/indices/organization" route of ElasticSearch.
This dives me to a questions, if it tries everytime to communicate to both ElasticSearch and Postgres, whatever the entity.
How to prevent this, for example can I say that an entity is mapped with a DataSource and not another ?
Or maybe at least set a priority ?
My app/config/packages/api_platform.yaml
api_platform:
allow_plain_identifiers: true
title: HeyAPI Documentation
version: 2.0.0
formats:
jsonld: ['application/ld+json']
json: ['application/json']
graphql: ['application/graphql'] #https://graphql.org/learn/serving-over-http/#post-request
mapping:
paths:
- '%kernel.project_dir%/config/api_platform'
patch_formats:
json: ['application/merge-patch+json']
elasticsearch:
hosts: ['%env(ELASTICSEARCH_URL)%']
swagger:
versions: [3]
api_keys:
Bearer:
name: Authorization
type: header

Symfony and API Platform: custom URL for default implementation of CRUD operations

I am trying to set up an API. I would like to use the default implementation of CRUD operations for GET requests and override the operations for POST, PUT and DELETE. That works actually very well already.
But my problem now is, that I would like to change the URL of the default implementation, so it fits to the URLs of my custom operations.
My Code looks something like that:
#ApiResource(
itemOperations={
"get",
"put"={
"path"="/my/very/important/URL/{id}",
"schemes"={"https"},
}
}
)
And I would now like to make the GET operation available through /my/very/important/URL too, without implementing the GET operation.
I found a workaround for what I actually wanted to do: adding a route prefix at the entity.
* #ApiResource(
* routePrefix="/my/very/important/URL"
* )
But unfortunately I can still not prevent API Platform from using the plural of my entity name as URL.
If I have an entity Publication, than API Platform exposes my API with the URL /my/very/important/URL/publications. I still don't know how to fix that.
According to the API Platform documentation:
"The URL, the method and the default status code (among other options) can be configured per operation. In the next example, both GET and POST operations are registered with custom URLs. Those will override the URLs generated by default. In addition to that, we require the id parameter in the URL of the GET operation to be an integer, and we configure the status code generated after successful POST request to be 301:"
https://api-platform.com/docs/core/operations/#configuring-operations
Here we have the example:
# api/config/api_platform/resources.yaml
App\Entity\Book:
collectionOperations:
post:
path: '/grimoire'
status: 301
itemOperations:
get:
method: 'GET'
path: '/grimoire/{id}'
requirements:
id: '\d+'
defaults:
color: 'brown'
host: '{subdomain}.api-platform.com'
schemes: ['https']
options:
my_option: 'my_option_value'
I hope it helps.

Payum Paypal Rest config_path

I am trying to implement paypal-rest payment with the payum bundle in symfony (3.1.4).
I need to get PayPal Plus running in my Symfony App.
Therefore I read this article
https://github.com/Payum/Payum/blob/master/docs/paypal/rest/get-it-started.md
Now - I can't figure out what the 'config_path' parameter is ment to be set to and what exactly has to be provides at this config_path.
Symfony states
'The config_path fields are required.'
My payum config looks like this atm
payum:
security:
token_storage:
AppBundle\Entity\PaymentToken: { doctrine: orm }
storages:
AppBundle\Entity\Payment: { doctrine: orm }
gateways:
paypal_express_payment:
factory: paypal_express_checkout
username: "%ppe_uname%"
password: "%ppe_pw%"
signature: "%ppe_signature%"
sandbox: false
paypal_rest_payment:
factory: paypal_rest
client_id: "%ppr_cid%"
client_secret: "%ppr_sec%"
sandbox: true
The paypal_express_payment part works fine.
If I add just a random config-path like 'my_config.txt' Symfony states
Request GetHumanStatus{model: ArrayObject} is not supported. Make sure the gateway supports the requests and there is an action which supports this request (The method returns true). There may be a bug, so look for a related issue on the issue tracker.
So - where and what is the config_path ment to be?
Any help or hints for more documentation that can lead into the right direction is very welcome.
It's meant to be sdk_config.ini from PayPal-PHP-SDK
gateways:
paypal_rest:
factory: paypal_rest
client_id: '%paypal_rest.client_id%'
client_secret: '%paypal_rest.client_secret%'
config_path: '%kernel.root_dir%/config/sdk_config.ini'
UPDATE: I don't think that Doctrine ORM storage is supported by Payum PaypalRest plugin.
PaypalRest\Action\CaptureAction requires the model (Payment) to be inherited from PayPal\Api\Payment and then it uses its create and execute methods for payment capture. I don't think it's a good idea to extend from PayPal\Api\Payment in the Doctrine entity.
I was able to eliminate this error by using Payum\Paypal\Rest\Model\PaymentDetails as a payment and filesystem as a storage:
payum:
storages:
Payum\Paypal\Rest\Model\PaymentDetails:
filesystem:
storage_dir: %kernel.root_dir%/Resources/payments
id_property: idStorage
Try to set it to default value like this:
paypal_rest_payment:
factory: paypal_rest
client_id: "%ppr_cid%"
client_secret: "%ppr_sec%"
sandbox: true
config_path: ~

JMSSerializerBundle complex generated value

I need implement RESTful API for my site on symfony 2, so i use FOSRestBundle + JMSSerializerBundle
I have such serializer yml for my entity:
Acme\DemoBundle\Entity\Product:
exclusion_policy: ALL
accessor_order: custom
custom_accessor_order: [id, title]
properties:
id:
expose: true
title:
expose: true
virtual_properties:
getMainPhoto:
serialized_name: photo
The problem is that getMainPhoto return me url to full sized image. I want preprocess this url before sending response to api client where i can generate new url to resized version of such image. I already have service in sf2 which can do this job:
$resized_url = $someService->generateResizedUrl($item->getMainPhoto(), 640, 480);
But i don't know how can i use this service with JMSSerializer. Maybe there is some callbacks for FOSRestBundle\JMSSerializerBundle just before it send response?
Have a look at the documentation. There are is a number of events and/or annotations you can use to hook into the serialization process.
You can exclude the original url, and then add the resized url using http://jmsyst.com/libs/serializer/master/event_system#serializer-post-serialize event.
You have to write a listener that listen when "Product" instances are serialized.

Can I define a new connection / Entity manager within a Bundle configuration?

I am trying to define a Bundle that helps to index some data (from an Entity) within a sqlite fts table, in order to do some full-text search.
I know I can define alternate connection and Entity Manager using the app config file (like shown in the cookbook), but I was wondering if it was possible to do so within the bundle configuration - by defining, for example, a service with the doctrine service injected, so that it can instantiate a new connection.
Sqlite is not mandatory, it can be any database type (supported by doctrine).
Thanks in advance for your help.
I would suggest looking at FOSUserBundle for how they handle multiple persistence layers (ORM, Couch, MongoDB). You would essentially be doing the same thing. It's just a matter of loading different configurations depending on the driver specified in app/config/config.yml.
As far as i know it it not possible. Also database connections should be managed centralized in app/config.yml.
I would suggest to define the connection there and add a configuration option to you bundle where you can specify wich connection to use for the indexing stuff.
# app/config.yml
doctrine:
dbal:
default_connection: default
connections:
default:
dbname: database
host: localhost
user: user
password: secret
driver: pdo_mysql
my_data_index:
dbname: database
driver: pdo_sqlite
# configuration option of you bundle
acme_indexer:
connection: my_data_index
Then in your bundle you can read this config option and obtain the connection/entity manager and inject it into your indexing service.
Edit:
You can for sure create a custom connection programaticly in your bundle
$params = array(
'driver' =>'pdo_sqlite',
....
);
$factory = $container->get('doctrine.dbal.connection_factory')
$connection = $factory->createConnection($params);
But as i said before it is bad practice because you would evade the symfony standart way of defining database connections.

Resources