sfContext::getInstance()->getUser() not working in createQuery from validator
Now: resolved - no reproducible anymore
For some specific application security, I have the following createQuery function on a table, ie you can only access the table record if you have the "Administrator" credential or if you are the user that is stored in the MembershipDelegate relation.
class OrganisationTable extends Doctrine_Table
function createQuery($alias = ''){
if (!$alias){
$alias = 'o';
}
$query = parent::createQuery($alias);
try {
$user = sfContext::getInstance()->getUser();
}catch(Exception $e){
if ($e->getMessage() == 'The "default" context does not exist.'){
return $query;
}else{
throw $e;
}
}
if ($user->hasCredential('Administrator')){
//all good
}else{
$userId = $user->getAttribute('userId');
print "<!--testaa ".print_r($user->getCredentials(),1).'-->';
$query->
leftJoin("$alias.MembershipDelegate mdelsec")->
addWhere ("mdelsec.joomla_user_id=$userId");
}
return $query;
}
This seems to work fine at all levels, however there is a choice validator for which the $user object seems to come back empty
/**
* Person form base class.
*
*/
...
abstract class BasePersonForm extends BaseFormDoctrine
{
public function setup()
{
$this->setWidgets(array(
...
'organisation_id' => new sfWidgetFormDoctrineChoice(array('model' => $this->getRelatedModelName('Organisation'), 'add_empty' => true)),
class PersonForm extends BasePersonForm{
public function configure(){
$this->widgetSchema['organisation_id']->setOption('renderer_class', 'sfWidgetFormDoctrineJQueryAutocompleter');
$this->widgetSchema['organisation_id']->setOption('renderer_options', array(
'model' => 'Organisation',
'url' => NZGBCTools::makeUriJoomlaCompatible(
sfContext::getInstance()->getController()->genUrl('organisation/jsonList'))
));
$this->validatorSchema['organisation_id']->setOption('required',false);
is there any other way to get the user object in the model?
This approach to row level security may not be MVC by-the-book, but is IMO safer and superior than implementing the same security concepts in the actions:
- It can be used with out of the box admin-generator modules
- It 开发者_如何学运维is much harder to forget to implement it somewhere
- It may at times not require any credentials, only Super Admin access
I'm not aware of another way to get the session user in the models (I don't think there is one), but if you're able to, you ought to pass the user object down to the models.
I think you are missing something here, you have mixed the MVC layers quite a lot. My suggestion is to make the Model independent from the Controller (delegate to the Controller the Context-specific situations), and validation should be done by the Controller also ( there should be an action that receives the request , binds the form and validates it. There is where you have to definy anithing thats context speficif). Here is what i would do:
The OrganisationTable class should have 2 methods: createQueryForAdministrator , and createQueryForMembershipDelegate . Each one does the things it should do, and now you should change the Controller (the action that handles it) and do something like:
public function executeAction(sfWebRequest $request) { if ($this->getUser()->hasCredential('administrator')) { //call the administrator method } else { //call the other method } }
The action that instances the Form should also check the user credentials and do something like:
If ($user->hasCredential("administrator")) { sfContext::getInstance()->getConfiguration()->loadHelper("Url"); $form->getValidator("organization_id")->setOption("url",url_for("@action")); [..] } else { [..] }
Check the url helper reference, you can do thinks like loading helpers on actions etc and you could also create your own helpers too. Hope this helps!
EDITED: Check this post about sfContext class and alternatives
It now appears that this question was a fluke as I can't reproduce the problem after fixing other issues around the user authentication.
精彩评论