I implementend my own security voter for my symfony (2.6.1) based project. I did so following this blog entry: http://symfony.com/blog/new-in-symfony-2-6-simpler-security-voters and this documentation: http://symfony.com/doc/current/cookbook/security/voters_data_permission.html
My problem now is, that the method "isGranted" of my voter never gets called.
My voter class looks like this:
namespace AppBundle\SecurityVoter;
use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
use Symfony\Component\Security\Core\User\UserInterface;
class FolderVoter extends AbstractVoter
{
const EDIT = 'edit';
protected function getSupportedClasses()
{
return array('\MyApp\Entity\Folder');
}
protected function getSupportedAttributes()
{
return array(self::EDIT);
}
protected function isGranted($attribute, $folder, $user = null)
{
if (!$user instanceof UserInterface) {
return false;
}
if ($folder->getUserId() == $user->getId()) {
return true;
}
return false;
}
}
The class is configured in the services.yml in the following way:
security.access.folder_voter:
class: AppBundle\SecurityVoter\FolderVoter
public: false
tags:
- { name: security.voter }
I'm using the method 'is_granted' from within a twig template. What did i miss to implement or what did i do wrong that it is not working ?
I just found the solution myself. It was pretty easy. But nasty in some way as well.
Insted of this:
protected function getSupportedClasses()
{
return array('\MyApp\Entity\Folder');
}
I had to declare the class name like this. So without the leading backslash:
protected function getSupportedClasses()
{
return array('MyApp\Entity\Folder');
}
Maybe this could be improved on the security voter implementation in general :-)
Related
I get tutorial from here : https://laravel-excel.maatwebsite.nl/docs/3.0/export/basics
<?php
...
use App\Exports\ItemsDetailsExport;
class ItemController extends Controller
{
...
public function exportToExcel(ItemsDetailsExport $exporter, $id)
{
//dd($id); I get the result
return $exporter->download('Summary Detail.xlsx');
}
}
My export like this :
<?php
namespace App\Exports;
use App\Repositories\Backend\ItemDetailRepository;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\Exportable;
use Illuminate\Support\Facades\Input;
class ItemsDetailsExport implements FromCollection
{
use Exportable;
protected $itemDetailRepository;
public function __construct(ItemDetailRepository $itemDetailRepository)
{
$this->itemDetailRepository = $itemDetailRepository;
}
public function collection()
{
$test = Input::get('id');
dd('yeah', $test);
}
}
I want to pass id parameter to export file. I try like that, but I don't get the id. The id is null
How can I solve this problem?
For passing data from controller to laravel excel function we can pass and use data like below
For example, we have to pass data year like 2019 we will pass like below
in controller
Excel::download(new UsersExport(2019), 'users.xlsx');
In laravel import file
class UsersExport implements FromCollection {
private $year;
public function __construct(int $year)
{
$this->year = $year;
}
public function collection()
{
return Users::whereYear('created_at', $this->year)->get();
}
}
you can refer all following official documentation link
https://docs.laravel-excel.com/3.1/architecture/objects.html#plain-old-php-object
Unfortunately you can't use normal dependency injection when you have a specific parameter. This is what you can do though:
class ItemsDetailsExport implements FromCollection
{
use Exportable;
protected $itemDetailRepository;
protected $id;
public function __construct(ItemDetailRepository $itemDetailRepository, $id)
{
$this->itemDetailRepository = $itemDetailRepository;
$this->id = $id;
}
public function collection()
{
$test = $this->id;
dd('yeah', $test);
}
}
Now the problem is that the container doesn't know how to resolve $id however there are two ways around this.
Manual passing of $id:
public function exportToExcel($id)
{
$exporter = app()->makeWith(ItemsDetailsExport::class, compact('id'));
return $exporter->download('Summary Detail.xlsx');
}
Route injection:
Define your route as:
Route::get('/path/to/export/{itemExport}', 'ItemController#exportToExcel');
In your RouteServiceProvider.php:
public function boot() {
parent::boot();
//Bindings
Route::bind('itemExport', function ($id) { //itemExport must match the {itemExport} name in the route definition
return app()->makeWith(ItemsDetailsExport::class, compact('id'));
});
}
Then your route method is simplified as:
public function exportToExcel(ItemsDetailsExport $itemExport)
{
//It will be injected based on the parameter you pass to the route
return $itemExport->download('Summary Detail.xlsx');
}
I am creating a rule set engine that looks kinda like a unit test framework.
[RuleSet(ContextA)]
public class RuleSet1
{
[Rule(TargetingA)]
public Conclusion Rule1(SubjectA subject)
{ Create conclusion }
[Rule(TargetingA)]
public Conclusion Rule2(SubjectA subject)
{ Create conclusion }
[Rule(TargetingB)]
public Conclusion Rule3(SubjectB subject)
{ Create conclusion }
}
[RuleSet(ContextB)]
public class RuleSet2
{
[Rule(TargetingB)]
public Conclusion Rule1(SubjectB subject)
{ Create conclusion }
[Rule(TargetingA)]
public Conclusion Rule2(SubjectA subject)
{ Create conclusion }
[Rule(TargetingB)]
public Conclusion Rule3(SubjectB subject)
{ Create conclusion }
}
public class Conclusion()
{
// Errorcode, Description and such
}
// contexts and targeting info are enums.
The goal is to create an extensible ruleset that doesn't alter the API from consumer POV while having good separation-of-concerns within the code files. Again: like a unit test framework.
I am trying to create a library of these that expose the following API
public static class RuleEngine
{
public static IEnumerable<IRuleSet> RuleSets(contextFlags contexts)
{
{
return from type in Assembly.GetExecutingAssembly().GetTypes()
let attribute =
type.GetCustomAttributes(typeof (RuleSetAttribute), true)
.OfType<RuleSetAttribute>()
.FirstOrDefault()
where attribute != null
select ?? I don't know how to convert the individual methods to Func's.
}
}
}
internal interface IRuleset
{
IEnumerable<Func<SubjectA, Conclusion>> SubjectARules { get; }
IEnumerable<Func<SubjectB, Conclusion>> SubjectBRules { get; }
}
...which allows consumers to simply use like this (using foreach instead of LINQ for readability in this example)
foreach (var ruleset in RuleEgine.RuleSets(context))
{
foreach (var rule in ruleset.SubjectARules)
{
var conclusion = rule(myContextA);
//handle the conclusion
}
}
Also, it would be very helpful if you could tell me how to get rid of "TargetingA" and "TargetingB" as RuleAttribute parameters and instead use reflection to inspect the parameter type of the decorated method directly. All the while maintaining the same simple external API.
You can use Delegate.CreateDelegate and the GetParameters method to do what you want.
public class RuleSet : IRuleSet
{
public IEnumerable<Func<SubjectA, Conclusion>> SubjectARules { get; set; }
public IEnumerable<Func<SubjectB, Conclusion>> SubjectBRules { get; set; }
}
public static class RuleEngine
{
public static IEnumerable<IRuleSet> RuleSets() // removed contexts parameter for brevity
{
var result = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetCustomAttributes(typeof(RuleSetAttribute), true).Any()
let m = t.GetMethods().Where(m => m.GetCustomAttributes(typeof(RuleAttribute)).Any()).ToArray()
select new RuleSet
{
SubjectARules = CreateFuncs<SubjectA>(m).ToList(),
SubjectBRules = CreateFuncs<SubjectB>(m).ToList()
};
return result;
}
}
// no error checking for brevity
// TODO: use better variable names
public static IEnumerable<Func<T, Conclusion>> CreateFuncs<T>(MethodInfo[] m)
{
return from x in m
where x.GetParameters()[0].ParameterType == typeof(T)
select (Func<T, Conclusion>)Delegate.CreateDelegate(typeof(Func<T, Conclusion>), null, x);
}
Then you can use it like this:
var sa = new SubjectA();
foreach (var ruleset in RuleEngine.RuleSets())
{
foreach (var rule in ruleset.SubjectARules)
{
var conclusion = rule(sa);
// do something with conclusion
}
}
In your LINQ query you headed straight for RuleSetAttribute, and so lost other information. If you break the query in several lines of code you can get methods from the type with GetMethods(), and then you can call GetCustomAttribute<RuleAttribute>().
I have defined my controller but I would like to secure ALL of them like below :
// In my Controller Class
public function chooseDateAction()
{
if($this->get('MY.roles_features')
->isGranted($this->container->get('request')->get('_route')))
{
// Do something
}
else
{
throw new AccessDeniedException();
}
return array( );
}
I had to design my own 'isGranted' function because roles are dynamic. BTW the function is working properly !
So my question is do I have to repeat the isGranted function in all of my Controllers or I can put it somewhere to reduce the code redundancy.
I know I have to place isGranted in some top level layer of my security, But the question is how and where ?
Try writing a base controller, which will check upon construction, if isGranted method passes, else throws exception. e.g.:
<?php
namespace Acme\DolanBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
class BaseController extends Controller
{
public function __construct()
{
if(!$this->get('MY.roles_features')
->isGranted($this->container->get('request')->get('_route')))
{
throw new AccessDeniedException('Gooby pls');
}
}
}
Then just extend the BaseController in your other controllers.
I'm trying to design an application following Misko Heverys insights. It's an interesting experiment and a challenge. Currently I'm struggling with my ViewHelper implementation.
The ViewHelper decouples the model from the view. In my implementation it wraps the model and provides the API for the view to use. I'm using PHP, but I hope the implementation is readable for everyone:
class PostViewHelper {
private $postModel;
public function __construct(PostModel $postModel) {
$this->postModel = $postModel;
}
public function title() {
return $this->postModel->getTitle();
}
}
In my template (view) file this could be called like this:
<h1><?php echo $this->post->title(); ?></h1>
So far so good. The problem I have is when I want to attach a filter to the ViewHelpers. I want to have plugins that filter the output of the title() call. The method would become like this:
public function title() {
return $this->filter($this->postModel->getTitle());
}
I need to get observers in there, or an EventHandler, or whatever service (in what I see as a newable, so it needs to be passed in through the stack). How can I do this following the principles of Misko Hevery? I know how I can do this without it. I'm interested in how for I can take it and currently I don't see a solution. ViewHelper could be an injectable too, but then getting the model in there is the problem.
I didn't find the blog post you referenced very interesting or insightful.
What you are describing seems more like a Decorator than anything to do with dependency injection. Dependency injection is how you construct your object graphs, not their state once constructed.
That said, I'd suggest taking your Decorator pattern and running with it.
interface PostInterface
{
public function title();
}
class PostModel implements PostInterface
{
public function title()
{
return $this->title;
}
}
class PostViewHelper implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->post->title();
}
}
class PostFilter implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->filter($this->post->title());
}
protected function filter($str)
{
return "FILTERED:$str";
}
}
You'd simply use whatever DI framework you have to build this object graph like so:
$post = new PostFilter(new PostViewHelper($model)));
I often use this approach when building complex nested objects.
One problem you might run into is defining "too many" functions in your PostInterface. It can be a pain to have to implement these in every decorator class. I take advantage of the PHP magic functions to get around this.
interface PostInterface
{
/**
* Minimal interface. This is the accessor
* for the unique ID of this Post.
*/
public function getId();
}
class SomeDecoratedPost implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->_post = $post;
}
public function getId()
{
return $this->_post->getId();
}
/**
* The following magic functions proxy all
* calls back to the decorated Post
*/
public function __call($name, $arguments)
{
return call_user_func_array(array($this->_post, $name), $arguments);
}
public function __get($name)
{
return $this->_post->get($name);
}
public function __set($name, $value)
{
$this->_post->__set($name, $value);
}
public function __isset($name)
{
return $this->_post->__isset($name);
}
public function __unset($name)
{
$this->_post->__unset($name);
}
}
With this type of decorator in use, I can selectively override whatever method I need to provide the decorated functionality. Anything I don't override is passed back to the underlying object. Multiple decorations can occur all while maintaining the interface of the underlying object.
I am new to Subsonic, and it seems that I cant find out a natural way to do CRUD operations using the LINQ template classes. I guess in ActiveRecord, you could:
Product p = new Product();
p.ProductCode = "xxx";
p.Add();
Using the LINQTemplate generated classes however, how can I do the same thing? I can only use something like this below to insert a product object:
db.Insert.Into<UnleashedSaaS.PRODUCT>(prod => prod.Code, prod => prod.Description).Values("Product1", "Product1 Desc").Execute();
Who could kindly give me some hints? I'd really appreciate it.
All the CRUD happens in SubSonicRepository, which you can derive from. For example, I would have a class like this:
public class ProductRepository : SubSonicRepository<Product> {
public ProductRepository() : base(new NorthwindDB()) { }
// need this here because base doesn't expose the DB class that I know of
protected NorthwindDB _db;
protected NorthwindDB DB {
get {
if (_db == null) _db = new NorthwindDB();
return _db;
}
}
public void Save(Product product) {
if (product.ProductId == 0) {
Add(product); // Add is part of SubSonicRepository
} else {
Update(product);
}
}
public void Delete(Product product) { ... }
public List<Product> ListAll() {
var products = from p in DB.Products
select p;
return products.ToList();
}
public Product GetById(int id) {
return DB.GetByKey(id);
}
}
And so on. It's nice because you can consolidate all your data access methods in one place. If you have Sprocs, they're generated as methods on DB as well.
When I get time I'm going to work on adding a Save method to SubSonicRepository directly so you don't have to do the check yourself to see which method (Add or Update) to call.
I have modified the Classes.tt file to include:
public partial class <#=tbl.ClassName#>Repository : SubSonicRepository<<#=tbl.ClassName#>>
{
public <#=tbl.ClassName#>Repository() : base(new <#=DatabaseName#>DB()) { }
}
Insert that bunch of lines between
<# foreach(Table tbl in tables){#>
and
/// <summary>
right at the top, near the namespace declaration, in my file it can be inserted in line 18.
The last thing to do is to add another "using" statement, in line 10, the next line after System.Linq statement. Now it should look like:
using System.Linq;
using SubSonic.Repository;
That will generate a repository to give you access to basic functionality, but can be modified in another partial class.
Hope that helps.