rbac authorization check in Yii doesn't work (Getting unknown property: app\models\Post::createdBy) - yii

I looked at the documentation for rbac in Yii and thought I understood how it worked until I actually tried it.
This is the rule for checking whether the author of the post is trying to get the authorization for an action:
class AuthorRule extends Rule
{
public $name = 'isAuthor';
/**
* #param string|integer $user the user ID.
* #param Item $item the role or permission that this rule is associated with
* #param array $params parameters passed to ManagerInterface::checkAccess().
* #return boolean a value indicating whether the rule permits the role or permission it is associated with.
*/
public function execute($user, $item, $params)
{
return isset($params['model']) ? $params['model']->createdBy == $user : false;
}
}
This is how I am trying to use the rule and Yii's rbac:
public function actionUpdate($id)
{
$model = $this->findModel($id);
if (\Yii::$app->user->can('update', ['model' => $model])) {
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
}
However, I get this when I try to edit a Post:
Getting unknown property: app\models\Post::createdBy
So I thought I had to replace createdBy with userId which is a column in the table Post and I am getting a blank page meaning it doesn't work. So I am trying to guess what $user is.
I also tried:
return isset($params['model']) ? $params['model']->userId == $user->id : false;
and I am getting: Trying to get property of non-object.
What should I do to make it work? The doc seemed to suggest you just had to plug the conditional inside the controller action to make it work, but it doesn't seem to be the case at all.
var dump:
object(app\models\Post)[75]
private '_attributes' (yii\db\BaseActiveRecord) =>
array (size=6)
'id' => int 1
'userId' => int 1
'title' => string 'test' (length=4)
'content' => string 'lol' (length=3)
'dateCreated' => null
'dateUpdated' => null
private '_oldAttributes' (yii\db\BaseActiveRecord) =>
array (size=6)
'id' => int 1
'userId' => int 1
'title' => string 'test' (length=4)
'content' => string 'lol' (length=3)
'dateCreated' => null
'dateUpdated' => null
private '_related' (yii\db\BaseActiveRecord) =>
array (size=0)
empty
private '_errors' (yii\base\Model) => null
private '_validators' (yii\base\Model) => null
private '_scenario' (yii\base\Model) => string 'default' (length=7)
private '_events' (yii\base\Component) =>
array (size=0)
empty
private '_behaviors' (yii\base\Component) =>
array (size=0)
empty
null

The first error says, that you don't have a createdBy property in your Post model. Do you?
The second error is about trying to get a property of non-object variable. Could you show var_dump($params['model']); var_dump($user); before the return?

Related

Object of class Faker\UniqueGenerator could not be converted to string

I am using laravel 9. I am trying to generate some fake users to boost my db using factoreis and seeders.
When i try to seed my db i get this error
Object of class Faker\UniqueGenerator could not be converted to string
at D:\PROJECTS\LARAVEL\todo-list\vendor\laravel\framework\src\Illuminate\Database\Connection.php:665
661▕ $value,
662▕ match (true) {
663▕ is_int($value) => PDO::PARAM_INT,
664▕ is_resource($value) => PDO::PARAM_LOB,
➜ 665▕ default => PDO::PARAM_STR
666▕ },
667▕ );
668▕ }
669▕ }
1 D:\PROJECTS\LARAVEL\todo-list\vendor\laravel\framework\src\Illuminate\Database\Connection.php:665
PDOStatement::bindValue(Object(Faker\UniqueGenerator))
2 D:\PROJECTS\LARAVEL\todo-list\vendor\laravel\framework\src\Illuminate\Database\Connection.php:540
Illuminate\Database\Connection::bindValues(Object(PDOStatement))
this my UserFactory
class UserFactory extends Factory
{
/**
* Define the model's default state.
*
* #return array<string, mixed>
*/
public function definition()
{
return [
'name' => fake()->name(),
'username' => fake()->unique(),
'company' => fake()->sentence(),
'position' => fake()->sentence(),
'bio' => fake()->realText($maxNbChars = 100),
'picture' => fake()->imageUrl(90, 90),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => Hash::make('password'), // password
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*
* #return static
*/
public function unverified()
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}
After looking arround for a while I found that fake()->unique() does not return a string. So I tried to convert it to string but It also gives me a error saying Unknown format "toString" in Faker\Generator.php:731
[Problem solved]
I just had to edit my UserFactory username to this
'username' => fake()->unique()->text(16),

Laravel 5.6 - creation user not working

my application used to working well with registration user but now it dont.
here a portion of my model User
protected $fillable = [
'prenom', 'nom', 'email','photo_path','password',
];
here my validation function :
protected function validator(array $data)
{
return Validator::make($data, [
'prenom' => 'required|string|max:255',
'nom' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'photo_path' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:10000',
'password' => 'required|string|min:6|confirmed',
]);
}
here my create function :
protected function create(array $data)
{
dd($data);
$photoInput = request('photo_path');
$userPhotoPath='users';
$storagePhotoPath = Storage::disk('images')->put($userPhotoPath, $photoInput);
return User::create([
'prenom' => $data['prenom'],
'nom' => $data['nom'],
'email' => $data['email'],
'photo_path' => $storagePhotoPath,
'password' => Hash::make($data['password']),
]);
}
- POST request working ( return 302 ) but return back with input value
- Auth Route are declared in web.php
- Validation working well
but the php interpretor didnt get inside create function...
i just see in debugbar that information :
The given data was invalid./home/e7250/Laravel/ManageMyWorkLife/vendor/laravel/framework/src/Illuminate/Validation/Validator.php#306Illuminate\Validation\ValidationException
public function validate()
{
if ($this->fails()) {
throw new ValidationException($this);
}
$data = collect($this->getData())
but my validation working because i have error message near my InputTexte.
so i dont understand that error message ...
Do you have any clue ?
Well, you need to remove the dd(); function before you run something. Other wise it will end the execution of all other operations.
Check if your User Model has a constructor, if so remove it and check if the problem still accours. This fixed it for me.

Symfony 3.3 CraueFormFlowBundle Request_stack is empty

my first question to this site is a little difficult to describe.
I am quite new to Symfony, startet with 3.2 and updated recently to 3.3.5 (not sure if relevant for the problem).
I tried to use CraueFormFlowBundle (multistep form bundle) but cannot get it to work.
The problem is that trying to access the flow results in an exception:
Error: Call to a member function getCurrentRequest() on null
Symfony\Component\Debug\Exception\ FatalErrorException
in vendor/craue/formflow-bundle/Form/FormFlow.php (line 191)
Line 191 shows: $currentRequest = $this->requestStack->getCurrentRequest();
Modifying the FormFlow.php with dump line shows that $this->requestStack is null.
I have not enough knowledge about this bundle to know where to start looking for the problem.
The flow definition is based on the location example:
namespace EngineeringBundle\Form;
use Craue\FormFlowBundle\Form\FormFlow;
use Craue\FormFlowBundle\Form\FormFlowInterface;
class SelectExaminationFlow extends FormFlow
{
/**
* {#inheritDoc}
*/
protected function loadStepsConfig()
{
dump("loadStepsConfig");
return array(
array(
'label' => 'engineering.discipline',
'form_type' => new SelectExaminationStep1Form(),
),
array(
'label' => 'engineering.date',
'form_type' => new SelectExaminationStep2Form(),
'skip' => function($estimatedCurrentStepNumber, FormFlowInterface $flow) {
return $estimatedCurrentStepNumber > 1 && !$flow->getFormData()->canHaveRegion();
},
),
array(
'label' => 'confirmation',
),
);
}
The form definition is also quite simple and works without problems:
class SelectExaminationStep1Form extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
dump("buildForm");
$builder
->add('id', HiddenType::class)
->add('discipline', EntityType::class, array(
'class' => 'EngineeringBundle:Discipline',
'choice_label' => 'disciplineName',
'label' => 'engineering.discipline.label'
)
);
}
public function getName() {
return $this->getBlockPrefix();
}
public function getBlockPrefix() {
return 'createEngineeringStep1';
}
}
services.yml:
EngineeringBundle\Form\SelectExaminationFlow:
parent: craue.form.flow
autowire: false
autoconfigure: false
public: true
engineering.form_flow:
alias: EngineeringBundle\Form\SelectExaminationFlow
public: true
Controller:
/**
* #Route("create", name="engineering_create")
*/
public function createAction()
{
return $this->processFlow(new ExaminationDate(), $this->get('engineering.form_flow'));
}
Thanks in advance
Sebastian
I was having the same problem, resolved it by adding a constructor to vendor/craue/formflow-bundle/Form/FormFlow.php with the following content:
public function __construct(RequestStack $requestStack, FormFactoryInterface $formFactory, DataManagerInterface $dataManager, EventDispatcherInterface $eventDispatcher) {
$this->formFactory = $formFactory;
$this->requestStack = $requestStack;
$this->dataManager = $dataManager;
$this->eventDispatcher = $eventDispatcher;
}
Make sure to place it after all setter-methods. Problem seems to be related to a symfony update.

Saving a Doctrine 2 Entity that contains an ObjectSelect element using Zend Form

I was following along with the Doctrine Hydrator tutorial, but I am having issues saving when my fieldset contains an ObjectSelect. I'm using ORM mapping on my entities. Basically I have a Role entity with id and name. I also have a User entity with id, name and role (ManyToOne). I also have my getters and setters. My setRole() method passes the Role entity as a parameter.
/** #param Role $role */
public function setRole(\Application\Entity\Role $role) {
$this->role = $role;
}
I setup a UserFieldset with a Doctrine Hydrator.
$this->setHydrator(new DoctrineHydrator($objectManager, 'Application\Entity\User'))
->setObject(new User());
The object select for the Role
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'role',
'options' => array(
'label' => 'Role',
'object_manager' => $objectManager,
'target_class' => 'Application\Entity\Role',
'property' => 'name'
)
));
I then setup a UserForm that sets the DoctrineHydrator and adds the UserFieldset.
My controller action
public function addUserAction() {
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$form = new UserForm($objectManager);
$user = new User();
$form->bind($user);
if ($this->request->isPost()) {
$form->setData($this->request->getPost());
if ($form->isValid()) {
$objectManager->persist($user);
$objectManager->flush();
}
}
return array('form' => $form);
}
What seems to be happening is that the ID of the role is passed to setRole rather than an object. As a workaround I've modified my action to:
if ($form->isValid()) {
$objectManager->persist($user);
$data = $this->request->getPost();
$role = $objectManager->find('Application\Entity\Role', $data->user['role']);
$user->setRole($role);
$objectManager->flush();
}
It seems as if this additional step should not be required, but I am not sure if I need to modify my setRole or if I also need to bind a Role entity to the form. This is obviously a simplified example, but my actual forms have many associations that will be tedious to have to code in the controller like this.
UPDATE:
Debug information about post and form.
var_dump($form->getData());
var_dump($this->request->getPost());
Output
object(Application\Entity\User)[395]
protected 'id' => int 6
protected 'name' => string 'Jane Doe' (length=8)
protected 'role' => null
object(Zend\Stdlib\Parameters)[146]
public 'user' =>
array (size=3)
'id' => string '' (length=0)
'name' => string 'Jane Doe' (length=8)
'role' => string '3' (length=1)
public 'submit' => string 'Add User' (length=8)
At long last I got it working. The issue was that I needed to add the role to my input filter on the fieldset
public function getInputFilterSpecification() {
return array(
'name' => array('required' => true),
'role' => array('required' => true)
)
}
... and my validation group on my form.
$this->setValidationGroup(array(
'User' => array(
'name',
'role'
)
));
Now to save the user in my action it is simply
if ($form->isValid()) {
$objectManager->persist($user);
$objectManager->flush();
}

Different name fields user table?

I have a form with 2 fields (username, password) and a mysql table with those 2 same fields (username, password), and I authentication system working properly :)
But, I can not make it work if my table fields have different names, for example: (my_user, my_pass).
If you just change the username field on the other also works for me, that gives me problems is the password field.
My config auth.php
'driver' => 'eloquent'
Update
Already found the solution in my controller, the password name can not change.
Before (WRONG):
What I've done in first place was wrong
$userdata = array(
'my_user' => Input::get('my_user'),
'my_pass' => Input::get('my_pass')
);
it should be
$userdata = array(
'my_user' => Input::get('my_user'),
'password' => Input::get('my_pass')
);
You can define you own username and password field in the auth.php inside the config folder.
return array(
'driver' => 'eloquent',
'username' => 'my_user',
'password' => 'my_pass',
'model' => 'User',
'table' => 'users',
);
I hope this can be of some help.
I ran into this same problem. You need to extend your model:
// User.php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $fillable = array('name','passwd','email','status','timezone','language','notify');
protected $hidden = array('passwd');
protected $table = "users_t";
protected $primaryKey = "uid";
public static $rules = array(
'name' => 'required',
'passwd' => 'required',
'email' => 'required'
);
public function getAuthIdentifier() {
return $this->getKey();
}
public function getAuthPassword() {
return $this->passwd;
}
public function getReminderEmail() {
return $this->email;
}
public static function validate($data) {
return Validator::make($data,static::$rules);
}
}
You need to implements this methods too:
public function getRememberToken(){
}
public function setRememberToken($value){
}
public function getRememberTokenName(){
}