tags:

views:

1124

answers:

4

I am using SF 1.2.9 to build a website. I want to use the admin generator to provide admin functionality for the object models I have used (specifically LIST, edit and delete).

I have read the Symfony docs (Chapter 14), but unless, I am very much mistaken, all examples I have come accross so far, seems to be written for a single user environment only. Meaning that the list of records returned to the user is essentially, ALL the records in that table. In a multiuser environment, this is irresposible at best, and potentially, a security threat. It is a necessary requirement to restrict the list of records returned to a user to only those that they own (i.e. created).

Suppose I have a table with (YML) schema like this:

foobar_dongle:
    id:          ~
    title:       varchar(255)
    info:        longvarchar
    owner_id:   ~
    created_at:  ~

where owner id is a FK into a user table.

Assume I generate an admin module like this:

symfony propel:generate-admin backend FoobarDongle --module=dongle

Question: How do I modify the list of records returned to a user in the LIST part of the code generated by the admin generator? As I mentioned above, currently, (i.e. out of the box), the admin generator presents the user (rather naively, I feel), with the ENTIRE set of records for the model being administered. I need to be able to restrict that list somehow, so that I can only return records owned by that user.

This is what I am trying to find out how to do.

I would be most grateful to anyone who can show me how I can restrict the list of records returned when using the admin generator for administration of an object model. Ideally, I would like to be able to specify a custom method that has all the custom 'filtering' logic - but so long as I can restrict the LIST of records a user can see (in admin), to only the records that he is the owner of, that is all I want to be able to do.

+1  A: 

You should use sfGuardPlugin to provide your login/user functionality - it includes user groups and permissions that can be assigned to users and/or groups.

Using security.yml you can then configure which permissions/credentials are required to access individual actions. IE: you can allow everyone to access the list/update/delete actions, but only people with the create permission to access the create page.

The docs for sfGuardPlugin are worth reading:

http://www.symfony-project.org/plugins/sfGuardPlugin

Plus this section from the jobeet tutorial covers sfGuard and also use of security.yml and credentials:

http://www.symfony-project.org/jobeet/1%5F2/Propel/en/13

And to round off, this page from the book is relevant too:

http://www.symfony-project.org/reference/1%5F2/en/08-Security (although not sure it covers anything that isn't in the page i linked from jobeet)

benlumley
Thanks Ben. The problem is that it is not merely a case of access. I want to be able to let a user see only what belongs to them. To put it another way (perhaps more succinctly):The admin generator is generating code which gets executed for the 'list' action. I want to know how to specify my own method here, so that I can control the list that is presented to the user. As it is (and in all the documentation I have seen so far), the user is returned the entire records of the database (for that model), which is simply unacceptable.
Stick it to THE MAN
Maybe, this is really what I should be asking in this question:How do I modify the list of records returned to a user in the 'list' part of the code generated by the admin generator?As I mentioned above, currently, (i.e. out of the box), the admin generator presents the user (rather naively, I feel), with the entire set of records for the model being administered.I need to be able to restrict that list somehow, so that I can only return records owned by that user. This is what I am trying to find out how to do.
Stick it to THE MAN
I have marked your answer as the accepted one. At the risk of repeating myself .... THANK YOU :)
Stick it to THE MAN
Eeek, posted comment in the wrong box. Too excited, need to calm down ...
Stick it to THE MAN
You should check out this recent tutorial:http://www.symfony-project.org/advent_calendar/3/enIt uses a custom routing class to achieve similar to what you are after. Could definitely be modified.
benlumley
Thanks for the link ben, I'll take a look at it.
Stick it to THE MAN
Looks like its for SF 1.3 and 1.4. I am on 1.2.9. Do you know if the link is still applicable in my case (i.e. fo sf 1.2.9)?
Stick it to THE MAN
Yes, it is still applicable to 1.2, the routing hasn't changed that much.
benlumley
Thanks for the clarific\tion. I'll start reading the docs now..
Stick it to THE MAN
+2  A: 

If you only want to restrict the returned objects in one or two modules, do this:

Go to the actions.class.php file of your module. There should be no methods by default and the class should inherit from autoModuleNameActions you. Insert the following method:

protected function buildQuery()
{
   $query = parent::buildQuery();
   // do what ever you like with the query like
   $query->andWhere('user_id = ?', $this->getUser()->getId());
   return $query;
}

But this becomes unhandy if you do it for more modules. In this case I would advice to create a new admin generator theme.

And if you want to make the query depending on some custom parameter in the admin generator config file, then you have to extend this file. But is not just done with adding a new parameter. You can read this article how to do this.

If you want to know more about the auto generated classes, have a look at this class: cache/[app]/[env]/modules/auto[ModuleName]/actions/actions.class.php.


Edit after comments:

I think you looked at the wrong class. Look here: cache/[app]/[env]/modules/auto[ModuleName]/actions/actions.class.php.

I set up a Propel project to check it and the method that is interesting for you is:

protected function buildCriteria()
{
  if (is_null($this->filters))
  {
    $this->filters = $this->configuration->getFilterForm($this->getFilters());
  }

  $criteria = $this->filters->buildCriteria($this->getFilters());

  $this->addSortCriteria($criteria);

  $event = $this->dispatcher->filter(new sfEvent($this, 'admin.build_criteria'), $criteria);
  $criteria = $event->getReturnValue();

  return $criteria;
}

I also posted the whole content of this class to pastebin. It is a lot, the function is in line 245. Even if you don't find this class, you should be able to override this method like this:

protected function buildCriteria()
{
  $criteria = parent::buildCriteria();
  // do something with it
  return $criteria;
}

I don't know about these criteria objects, so I can't help you with that but I hope the other things help you.

Felix Kling
I think we are getting warmer ... I will investigate this (i.e. try to implement what you suggest), and return with feedback later. Thanks
Stick it to THE MAN
This may already be in the links you mentioned above, if so, please accept my apologies. I would like to know if it is possible to extend the generated functionality with some custom methods. I mean for example, the standard functionality is CRUD, but will it be possibly to add other 'actions' (other than 'new', 'edit', 'delete' etc), which are then displayed in the generated admin module?. Many thanks in advance for your help.
Stick it to THE MAN
Hi Felix, the buildQuery() looks suspiciously like a Doctrine method. I am using Propel as my ORM (should probably have mentioned it earlier). Does your advice re buildQuery() still hold?
Stick it to THE MAN
Yes you can add actions that are shown for example in the actions column of the list view. This is described here: http://www.symfony-project.org/book/1_0/14-Generators#chapter_14_sub_adding_interactions
Felix Kling
Hi Felix, I took a look at the auto generated classes, and they unfortunately, do not bear ANY relationship to what you posted above. I cant paste code in a comment, so I have pasted it here instead: http://pastebin.com/me068fd2. There must be a way to do this ...
Stick it to THE MAN
Deleted my last comment and put it into my answer.... ;)
Felix Kling
Hi Felix, all I can say is THANK YOU, THANK YOU and THANK YOU again. Thank you for taking the time to carry out the invesigation you conducted above, on my behalf. I am more grateful than you can imagine. I think I should be able to carry on from here. I am a big fan of StackOverflow now. (I was not sure I would get an answer, since there appear to be very few Symfonians on here). Thank you once again for your help. Much appreciated.
Stick it to THE MAN
I have marked your answer as the accepted one. At the risk of repeating myself .... THANK YOU :)
Stick it to THE MAN
Well, I am glad that I was able to help you. You are welcome :)
Felix Kling
A: 

Can this be used for filtering queries on the front-end as well? Incase of a multi-tenant app, I wish to filter all queries on the tenant_ID = $user->getTenantID() method. Is that possible?

Prasad
A: 

Works ok for doctrine! Another good question is How to not let edit a record from another user?

josx