Laravel Authorization for Eloquent collection - laravel-5.1

How to apply laravel Gate (http://laravel.com/docs/5.1/authorization) for an eloquent collection.
It works for single item like below
$post = Post::findOrFail($id);
if ($user->cannot('view-post', $post)) {
abort(403);
}
But not working for a collection. Is it possible to filter the collection using Gate and return a collection?
$posts = Post::all();

I have the same question. Maybe some like this:
$post->filter(function($value,$key){
if(\Gate::allows('view-post',$value)){
return $val;
}
});
but there must be a better solution.
Related links:
https://laravel.com/docs/5.2/collections#method-filter
https://laravel.com/docs/5.2/authorization

Related

BreezeJs Navigation Property Count

I've just started to use BreezeJS and think it is superb. It's saved me so much backend 'plumbing' code which was why I investigated it in the first place. One of the things I would like to be able to do is display a list of some accounts and a count of their contacts. At the moment I am using the code below, the Contacts field is a navigation property in EF6. The issue with this code is that I am downloading all of the contacts for each account (thousands of them) when really all I need is the count. Ideally I'd like my select statement to be something like this '.select('AccountID,AccountName, Contacts.Count()')' but I don't think OData/BreezeJS supports this. Thinking out loud maybe the solution is to create another WebService method called something like AccountsWithContactCounts and return a custom class but Ideally I'd like to avoid this if it is possible to do in the breezejs client.
Welcome any thoughts, apologies if this is a basic question.
breeze.EntityQuery.from('Accounts')
.where(pred)
.select('AccountID,AccountName, Contacts')
.orderBy(orderbyClause(orderBy, orderByReverse))
.skip(currentPage * pageItems)
.take(pageItems)
.noTracking()
.using(breezemanager).execute()
.then(function (response) {
console.log(response.results.length + ' entities retrieved');
$scope.items = response.results;
})
.catch(function (error) {
console.log(error.message);
})
.finally(function () {
});
And my breeze service looks like this:
[HttpGet]
public IQueryable<Account> Accounts()
{
return _contextProvider.Context.Accounts;
}
As Steve confirmed the answer was to create a new method on the Breeze controller
[HttpGet]
public IQueryable<object> AccountsSummary()
{
return from t in _contextProvider.Context.Accounts
select
new
{
t.AccountID,
t.AccountName,
ContactsCount = t.Contacts.Count()
};
}

BreezeJS - Using expand

I am querying the server to get an entity with expand
function _loadIncidents() {
var deffered = Q.defer(),
queryObj = new breeze.EntityQuery().from('Incidents').expand(['Deployments', 'IncidentComments', 'DTasks', 'ExtendedProperties', 'IncidentEvents']);
dataRepository.fetchEntitiesByQuery(queryObj, true).then(function (incidents) {
var query = breeze.EntityQuery.from("DTasks"),
incidentIds = dataRepository.getEntitiesByQuerySync(query);
deffered.resolve();
}, function(err) {
deffered.reject(err);
});
return deffered.promise;
};
I am getting the results and all is fine, how ever when I query breeze cache to get the entities - I am getting empty collection. So when using expand does the expanded entities are added to the cache?
Yes the related entities identified in the expand should be in cache ... if the query is "correct" and the server interpreted your request as you intended.
Look at the payload of the response from the first request. Are the related entities present? If not, perhaps the query was not well received on the server. As a general rule, you want to make sure the data are coming over the wire before wondering whether Breeze is doing the right thing with those data.
I do find myself wondering about the spelling of the items in your expand list. They are all in PascalCase. Are they these the names of navigation properties of the Incident type? Or are they the names of the related EntityTypes? They need to be former (nav property names), not the latter.
I Had problem with the navigation property - as I am not using OData webapi not using EF , there is problem with the navigation properties so for the current time i just wrote
Object.defineProperty(this, 'Deployments', {
get: function () {
return (this.entityAspect && this.entityAspect.entityManager) ?
this.entityAspect.entityManager.executeQueryLocally(new breeze.EntityQuery("Deployments").
where('IncidentID', 'eq', this.IncidentID)) :
[];
},
set: function (value) { //used only when loading incidents from the server
if (!value.results) {
return;
}
var i = 0,
dataRepository = require('sharedServices/dataRepository');
for (i; i < value.results.length; i++) {
dataRepository.addUnchangedEntity('Deployment', value.results[i]);
}
},
enumerable: true
});

Does Grails Filter `actionExclude` work with method-based routing?

I have a method-based route like:
name base: "/" {
controller="api"
action=[GET: "welcome", POST: "post"]
}
And I'd like to apply a filter to handle authorization, e.g.
class RequestFilters {
def filters = {
authorizeRequest(controller: 'api', actionExclude: 'welcome') {
before = {
log.debug("Applying authorization filter.")
}
}
}
}
But when I apply this in practice, the filter runs on all requests (even GET requests, which should use the welcome method and thus should not trigger this filter.)
When I inspect the code running the in the filter, I see that params.action is set to the Map from my routing file, rather than to "welcome". Not sure if this is related to the issue.
My current workaround (which feels very wrong) is to add the following to my filter's body:
if(params.action[request.method] == 'welcome'){
return true
}
The short question is: does Grails support this combination of method-based routing + action-name-based filtering? If so, how? If not, what are some reasonable alternatives for restructuring this logic?
Thanks!
You need to use the filter as below:
class RequestFilters {
def filters = {
authorizeRequest(controller:'api', action:'*', actionExclude:'welcome'){
before = {
log.debug("Applying authorization filter.")
return true
}
}
}
}
Apply the filter to all actions of the controller but "welcome". :)
If there is no other welcome action in the other controllers then, you would not need the controller specified in the filter as well.
authorizeRequest(action:'*', actionExclude:'welcome'){...}

Can a Ninject binding be based on a URL/route value?

I have a single controller that I want to use for CRUD operations on two different entities which implement the same interface. I'd like for Ninject to give it a different repository based on a query string value in the URL (or maybe a different URL, routed to the same controller). Is this possible? How can I do it?
That's usually a design smell but you could define the binding like this:
kernel.Bind<IRepo>().ToMethod(ctx =>
{
var a = HttpContext.Current.Request["a"];
if (a == "b")
{
return new RepoA();
}
return new RepoB();
}).InRequestScope();
The following worked for me, Getting A Specific value from a route
kernel.Bind<IRepo>().ToMethod(ctx =>
{
var a = HttpContext.Current.Request.RequestContext.RouteData.Values["RouteDateValue"]
if (a != null)
{
return new RepoA(a);
}
return new RepoB();
})

How to get Symfony session variable in model?

How can I pass session variable in symfony model without using sfContext::getInstance()?
The recommended way is called dependency injection, and works like this: you create a setUser() method in your model file, that saves the given parameter to a private property:
class Foo {
private $_user;
public function setUser(myUser $user) {
$this->_user = $user;
}
// ... later:
public function save(Doctrine_Connection $conn = null) {
// use $this->_user to whatever you need
}
}
This looks clumsy, because it is. But without you answering the question what are you trying to do? I cannot give an alternative.
Recommended articles:
What is Dependency Injection? - a post series on Fabien Potencier's blog
Dependency Injection - the design patter in detail on wikipedia
Session variables should be stored as user's attributes.
// in an action:
$this->getUser()->setAttribute('current_order_id', $order_id);
See how to get it back.
// later on, in another action, you can get it as:
$order_id = $this->getUser()->getAttribute('current_order_id', false);
if($order_id!==false)
{
// save to DB
} else {
$this->getUser()->setFlash('error', 'Please selected an order before you can do stuff.');
// redirect and warn the user to selected an order
$this->redirect('orders');
}

Resources