Symfony 4 and DoctrineEncryptBundle - Where define yaml configuration? - php

I am trying to encrypt data for a medical application that's how i found DoctrineEncryptBundle (https://packagist.org/packages/michaeldegroot/doctrine-encrypt-bundle)
I am still a rookie with symfony 4 and the documentation give the method for what seems to be previous Symfony version.
I already downloaded the bundle (composer require michaeldegroot/doctrine-encrypt-bundle)
For step 2 : "Enable the database encryption bundle"What is explain in document vs what I did in SF4
Which seems correct.
Then, there is no config.yml in SF4 and I don't know where to define the configuration (encryptor class and the path to the key file).
This yaml =>
ambta_doctrine_encrypt:
encryptor_class: Halite # or Defuse
secret_directory_path: '%kernel.project_dir%' # Path where to store the keyfiles
The documentation : https://github.com/michaeldegroot/DoctrineEncryptBundle/blob/master/Resources/doc/configuration.md
My files
Entity Patient (which i want to encrypt)
`
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Ambta\DoctrineEncryptBundle\Configuration\Encrypted;
/**
* #ORM\Entity
* #ORM\Entity(repositoryClass="App\Repository\PatientRepository")
* #ORM\Table(name="patient")
*/
class Patient {
/**
* #var string
* #Encrypted
* #ORM\Column(type="string")
*/
private $nom;`
The controller :
public function ajouterPatient(Request $request)
{
$patient = new Patient();
$form = $this->createForm(PatientType::class, $patient);
if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) {
$em = $this->getDoctrine()->getManager();
$patient->setNomsAffichage($patient->getNom()." ".$patient->getPrenom());
$patient->setActif(true);
$em->persist($patient);
$em->flush();
return $this->redirectToRoute('menu_patients');
}
return $this->render('Patients/ajouterPatient.html.twig', array(
'form' => $form->createView(),
));
}
I guess i should define something in service.yml like a link with the bundle but i don't know how.
Any help would be greatly appreciated.

I know this is an old question but for the people who still want to know where to define the configuration yaml file in Symfony 4 for this bundle, here is the answer I got it working with.
In the file config/bundles.php
Add at the end this line to define the Ambta Symfony bundle:
return [
...
Ambta\DoctrineEncryptBundle\AmbtaDoctrineEncryptBundle::class => ['all' => true]
];
Create a new yaml file in: config/packages/orm_services.yaml
Here you can put the configuration. For example:
ambta_doctrine_encrypt:
encryptor_class: Halite
secret_directory_path: '%kernel.project_dir%'

Related

Route Error: Symfony 4 No route found for "GET /blog"

I am having this error:
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: No route
found for "GET /blog" (from "http://localhost:8000/produits")
I added the annotation #Route in the method in my controller (like I saw in other website):
/**
* #Route("/blog", name="article.index")
* #return Response
* */
public function index():Response
{
return $this->render("blog/article.html.twig", [
"current_menu" => 'articles'
]);
}
I tried to add methods={"GET","HEAD"} in #Route but I have the same error
How do I solve this problem?
This one worked for me (adding / to the end of route path):
/**
* #Route("/blog/", name="article.index")
* #return Response
* */
public function index():Response
{
return $this->render("blog/article.html.twig", [
"current_menu" => 'articles'
]);
}
You will also at least need use Symfony\Component\Routing\Annotation\Route; at the start of the file (among the other 'use' lines), Some framework setup for Route annotations could also need to be enabled. Also, how does blog/article.html.twig refer to the route or path?
A freshly installed Symfony 4 instance will need composer require doctrine/annotations package, unless its already been installed by some other package.
https://symfony.com/doc/current/routing.html#creating-routes has more details.

Laravel Storage::extend not working

I can't figure out where I'm going wrong, with this. I've followed the Laravel docs by installing spatie/flysystem-dropbox via composer copied the DropboxServiceProvider from the Laravel Docs, added the service provided to the config\app.php, ran composer dump autoload but yet I am still getting the following error message:
PHP error: Undefined index: driver in /***/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemManager.php on line 112
Here is the service provider:
<?php
namespace App\Providers;
use Storage;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Illuminate\Support\ServiceProvider;
use Spatie\FlysystemDropbox\DropboxAdapter;
class DropboxServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* #return void
*/
public function boot()
{
Storage::extend('dropbox', function ($app, $config) {
$client = new DropboxClient(
$config['authorizationToken']
);
return new Filesystem(new DropboxAdapter($client));
});
}
/**
* Register bindings in the container.
*
* #return void
*/
public function register()
{
//
}
}
And here's my config/app/php:
...
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\DropboxServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
...
Finally, here's my config/filesystems.php:
'dropbox'=>[
'authorizationToken'=>env('DROPBOX_ACCESS_TOKEN')
],
Turns out that I was missing the driver value in the config/filesystems/php so it should have been this:
'dropbox'=>[
'driver' => 'dropbox', <=== THIS WAS MISSING
'authorizationToken'=>env('DROPBOX_TOKEN')
],
One good Pacakge avilable for extend storage using dropbox:
detail documentation : https://github.com/GrahamCampbell/Laravel-Dropbox
steps for use this package :
1 : composer require graham-campbell/dropbox in your cmd window
2 : after this you have to register service provider for laravel dropbox,
go to config/app.php
and add 'GrahamCampbell\Dropbox\DropboxServiceProvider' this in provider array
and 'Dropbox' => 'GrahamCampbell\Dropbox\Facades\Dropbox' this to aliases array
3: now you have to publish pacakge so 'php artisan vendor:publish' run this in your cmd
- this will create dropbox.php file in your config in this file you have to add your credentials
4: here you have two option for connection you can use it according to your choice.
usage :
simple example :
use GrahamCampbell\Dropbox\Facades\Dropbox;
// you can alias this in config/app.php if you like
Dropbox::createFolder('Folder_Name');
// we're done here - how easy was that, it just works!
Dropbox::delete('Folder_Name');
// this example is simple, and there are far more methods available

How to regenerate routes cache when the configuration changes in Symfony 2

I'm currently writing a custom route loader in Symfony 2 that will generate routes based on some configuration options defined in the main config file. The problem is that Symfony caches routes generated by custom routes loaders. Is there a way for me to update the cache when that config file changes?
I defined a configuration like this in app/config/config.yml
admin:
entities:
- BlogBundle\Entity\Post
- BlogBundle\Entity\Comment
My route loader read the config file and generates some routes based on the entities. Now the problem is that once those routes are generated and cached by Symfony I can't change them unless I manually call php app/console cache:clear. What I mean is if I add an entity to the config:
admin:
entities:
- BlogBundle\Entity\Post
- BlogBundle\Entity\Comment
- TrainingBundle\Entity\Training
I will have to manually clear the cache again with php app/console cache:clear in order to create and cache the new routes. I want the routes cache to be invalidated if I change the config, so that a new request to the server will force the regeneration of the routes.
Option 1
If your custom loader class can gain access to the kernel or the container (via DI), you could call the console cache clear command from that class.
E.g.
namespace AppBundle\MyLoader;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\HttpFoundation\Response;
class MyLoader
{
private $kernel;
public function __construct($kernel)
{
$this->kernel = $kernel;
}
public function myFunction()
{
$application = new Application($this->kernel);
$application->setAutoExit(false);
$input = new ArrayInput(array(
'command' => 'cache:clear',
'--env' => 'prod',
));
// You can use NullOutput() if you don't need the output
$output = new BufferedOutput();
$application->run($input, $output);
// return the output, don't use if you used NullOutput()
$content = $output->fetch();
// return new Response(""), if you used NullOutput()
return new Response($content);
}
}
Ref: Call a Command from a Controller
Disclaimer before someone points it out; Injection the kernel/conatiner is not considered "best pratice", but can be a solution.
Option 2
You could also write you own console command that extends Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand that just calls the clear cache command.
Ref ; Call Command from Another
Option 3
This answer also gives you another option

Prevent Sessions For Routes in Laravel (Custom on-demand session handling)

I am building APIs for my Android app using laravel and default session driver set to REDIS.
I found a good article here http://dor.ky/laravel-prevent-sessions-for-routes-via-a-filter/ which sort of serves the purpose.
However when ever I hit the url it also hits the redis and generates the key which is empty. Now I want avoid creating empty session keys in redis. Ideally it should not hit the redis How can I do that?
Can we customise sessios in a way so that sessions are generated only for specific routes (or disable for specific routes)?
I can explain more with specific use case, please let me know.
Its really easy using the middleware in Laravel 5, I needed any request with an API key not to have a session and I simply did :
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Session\Middleware\StartSession as BaseStartSession;
class StartSession extends BaseStartSession
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(\Request::has('api_key'))
{
\Config::set('session.driver', 'array');
}
return parent::handle($request, $next);
}
}
Also you will need to extend the SessionServiceProvider as follows:
<?php namespace App\Providers;
use Illuminate\Session\SessionServiceProvider as BaseSessionServiceProvider;
class SessionServiceProvider extends BaseSessionServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->registerSessionManager();
$this->registerSessionDriver();
$this->app->singleton('App\Http\Middleware\StartSession');
}
}
and place in your config/app.php under providers:
'App\Providers\SessionServiceProvider',
Also you must change it in your kernel file: App/Http/Kernel.php, in the $middlewareGroups section change the default entry, \Illuminate\Session\Middleware\StartSession::class, to your new class \App\Http\Middleware\StartSession::class,.
In Laravel 5, just don't use the StartSession, ShareErrorsFromSession, and VerifyCsrfToken middlewares.
In my application I've moved these three middlewares from the web group to a new stateful group, and then I have included this stateful group on routes which need to know about the session (in addition to web in all cases, in my app at least). The other routes belong to either the web or api groups.
Now when making requests to the routes which are not using the stateful middleware group session cookies are not sent back.
The simplest way to achieve this is to Make your own AppStartSession middleware that subclasses Illuminate\Session\Middleware\StartSession and the replace the class being used in kernel.php. The only method you need to override in your subclass is sessionConfigured() for which you can return false to disable the session or parent::sessionConfigured() to allow it.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Session\Middleware\StartSession;
class AppStartSession extends StartSession
{
protected function sessionConfigured(){
if(!\Request::has('api_key')){
return false;
}else{
return parent::sessionConfigured();
}
}
}
kernel.php (see *** comment for where the change is done)
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
// *** Replace start session class
// \Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\AppStartSession::class,
// *** Also comment these ones that depend on there always being a session.
//\Illuminate\View\Middleware\ShareErrorsFromSession::class,
//\App\Http\Middleware\VerifyCsrfToken::class,
];
/**
* The application's route middleware.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
];
}
Don't fight the framework, embrace it!
Since Laravel 5.2, when middleware groups were introduced, you may disable session for certain routes by defining them outside of the "web" middleware group (which includes the StartSession middleware responsible for session handling). As on latest 5.2.x versions the whole default routes.php file is wrapped with "web" middleware group, you need to make some modification in app/Providers/RouteServiceProvider.php file, as described here.
There appears to be a way to accomplish this using a session reject callback.
Relevant sources...
https://github.com/laravel/framework/blob/4.2/src/Illuminate/Foundation/Application.php#L655
https://github.com/laravel/framework/blob/4.2/src/Illuminate/Foundation/Application.php#L660
https://github.com/laravel/framework/blob/4.2/src/Illuminate/Session/Middleware.php#L60
https://github.com/laravel/framework/blob/4.2/src/Illuminate/Session/Middleware.php#L97
I can't find many references to this around the web, but reading more through the source it appears that if the session reject callback returns a truthy value, the session will be forced to use an array driver for the request rather than whatever is configured. Your callback also gets the current request injected so you can do some logic based on the request parameters.
I've only tested this on a local Laravel 4.2 install but it seems to work. You just need to bind a function to session.reject.
First, create a SessionRejectServiceProvider (or something like that)
<?php
use \Illuminate\Support\ServiceProvider;
class SessionRejectServiceProvider extends ServiceProvider {
public function register()
{
$me = $this;
$this->app->bind('session.reject', function($app)use($me){
return function($request)use($me){
return call_user_func_array(array($me, 'reject'), array($request));
};
});
}
// Put the guts of whatever you want to do in here, in this case I've
// disabled sessions for every request that is an Ajax request, you
// could do something else like check the path against a list and
// selectively return true if there's a match.
protected function reject($request)
{
return $request->ajax();
}
}
Then add it to your providers in your app/config/app.php
<?php
return array(
// ... other stuff
'providers' => array(
// ... existing stuff...
'SessionRejectServiceProvider',
),
);
Edit / More Info
The net result is that the reject() method is called on every request to your application, before the session is started. If your reject() method returns true, sessions will be set to the array driver and basically do nothing. You can find a lot of useful info the $request parameter to determine this, here's the API reference for the request object in 4.2.
http://laravel.com/api/4.2/Illuminate/Http/Request.html
I've been trying to accomplish a similar feature.
Our API is stateless except for 1 route - the version 1 cart.
I ended up with setting 'driver' in the app/config/session.php like this ...
'driver' => 'v1/cart' === Request::getDecodedPath() ? 'native' : 'array',
Nothing magic. Initially we though of using a before filter, but that wasn't happening early enough.
It seems a simple way to do things, but I may be missing something.
Putting the switch in the config seems an easy place for other developers to see what the driver is whereas putting it in a service provider is so tucked out of the way, without knowing what service providers are installed and what they interact with, it would be far harder to debug.
Anyway. Hope this is of some use.
As pointed out below ... DO NOT CACHE YOUR CONFIG IF IT IS DYNAMIC.
Which does lead to it being of limited use. As soon as we no longer need to support v1/cart, we will be dropping this route and then be back on a static config.
Laravel default have two routes group called web and api, the api routes group default without session.
So, we can write any route role to routes/api.php, will not use session default.
If not want to use the api prefix url, we can modify app\Providers\RouteServiceProvider add a new group like this:
Route::middleware('api')
->namespace($this->namespace)
->group(base_path('routes/static.php'));
Now you can place any routes into routes/static.php file will not to use session.
Hope helpful.
Laravel 5x
In the App\Providers\RouteServiceProvider file, just copy the mapApiRoutes() method to a new method called mapStaticRoutes(), remove the prefix('api') call, and add "routes/static.php" (you will need to create this file). This will use the same stateless "api" middleware and not have an /api prefix assigned to the routes.
protected function mapStaticRoutes()
{
Route::middleware('api')
->namespace($this->namespace)
->group(base_path('routes/static.php'));
}
Just update the "map()" method to call "$this->mapStaticRoutes();" so that it knows of your new file. And any route added there should now be stateless and it wasn't much work.....
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
// Static Routes (stateless, no /api prefix)
$this->mapStaticRoutes();
}
static.php
// Health Check / Status Route (No Auth)
Route::get('/status', function() {
return response()->json([
'app' => 'My Awesome App',
'status' => 'OK'
]);
});

Symfony2: Routing priority

is there anyway to prioritize routes in Symfony2?
i'm using annotation it looks like this
Controllers
//TestController.php
/**
* #Route("/test")
*/
class TestController extends Controller
{
/**
* #Route("/a", name="test_a")
*/
.....
//DummyController.php
/**
* #Route("/")
*/
class DummyController extends Controller
{
/**
* #Route("/{varA}/{varB}", name="dummy_one")
*/
.....
Config
//routing.yml
acme_bundle:
resource: "#Acme/Controller"
type: annotation
Goal
URL , Actual , Goal
/test/a , DummyController , TestController //Wrong
/test/b , DummyController , DummyController //Good
How can i force TestController to be tested first ?
Thanks
from your example i can assume that your dummy and test controller are in the same bundle, if this is the case then you just lists the controllers in that bundle individually in your routing.yml. the order you list them is the order they will be checked.
acme_test:
resource: "#Acme/Controller/TestController.php"
type: annotation
acme_dummy:
resource: "#Acme/Controller/DummyController.php"
type: annotation
if they are in different bundles, just list the bundle with the test controller first.
see the symfony routing doc for details. http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/routing.html#activation
So Symfony will consume the controllers in an alphabetical order and will add the routes one by one.
there is no way up to add priority at the moment without using another bundle for that currently version 2.5
https://github.com/symfony-cmf/Routing is a great bundle if you are looking for advanced routing.
You don't need to reorder everything. Just overwrite the rules for DummyController at the desired ranking. You can do this by creating a route to the controller at the end of your routing.yml.
So in your routing.yml as the last lines you will add:
app_dummy:
ressource: "#YourBundle/Controller/DummyController.php
type: annotation
Adding an answer as it might help other users viewing this question. As of Symfony 5.1, a priority can be assigned to each route:
#[Route(path: '/', name: 'home')]
public function home(): Response
{
return $this->render('home.html.twig');
}
#[Route(path: '/about', name: 'about', priority: 10)]
public function about(): Response
{
return $this->render('about.html.twig');
}
In this case (it's just a dummy example), the about route with a priority of 10 will be evaluated before the home route, which has the default priority of 0.
Check out the feature introduction on the Symfony blog.

Categories