I installed the voyager admin successfully from here
On my client page, I created a custom registration which is derived from auth. I can register the user successfully.
After I installed the voyager admin, I added a new user on client's registration form. Then, when i tried to access the http://localhost:8000/admin and then error occurred as seen on the image.
Below is the image of the line 53:
And below is the entire code of VoyagerUse.php
<?php
namespace TCG\Voyager\Traits;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use TCG\Voyager\Facades\Voyager;
use TCG\Voyager\Models\Role;
/**
* #property \Illuminate\Database\Eloquent\Collection roles
*/
trait VoyagerUser
{
public function role()
{
return $this->belongsTo(Voyager::modelClass('Role'));
}
/**
* Check if User has a Role(s) associated.
*
* #param string|array $name The role to check.
*
* #return bool
*/
public function hasRole($name)
{
if (!$this->relationLoaded('role')) {
$this->load('role');
}
return in_array($this->role->name, (is_array($name) ? $name : [$name]));
}
public function setRole($name)
{
$role = Voyager::model('Role')->where('name', '=', $name)->first();
if ($role) {
$this->role()->associate($role);
$this->save();
}
return $this;
}
public function hasPermission($name)
{
if (!$this->relationLoaded('role')) {
$this->load('role');
}
if (!$this->role->relationLoaded('permissions')) {
$this->role->load('permissions');
}
return in_array($name, $this->role->permissions->pluck('key')->toArray());
}
public function hasPermissionOrFail($name)
{
if (!$this->hasPermission($name)) {
throw new UnauthorizedHttpException(null);
}
return true;
}
public function hasPermissionOrAbort($name, $statusCode = 403)
{
if (!$this->hasPermission($name)) {
return abort($statusCode);
}
return true;
}
}
As mentioned in the VoyagerUser in line 53 :
if(!$this->role->relationLoaded('permissions')){ ...
The role here is considered as a relation not a field :)
and the error
Call to a member function relationLoaded() on string
means that you have the role as attribute in the User Model
So all you have to do is rename the role attribute to something else and everything will work perfectly ;)
You should simply change the name of your attribute named role because Voyager add a relation named role as well
Related
I created one policy inside create function i am checking weather this user can able to create records and i am registering the Model and policy in the AthServiceProvider.php after that i am checking inside the controller by using $this->authorize('create') it's failing always even the user is valid,can you please help me how to resolve this issue
Error:- This Action is unathorized
restaurentContoller.php
class RestaurentsController extends Controller
{
protected $repository;
public function __construct(RestaurentRepository $repository){
$this->repository = $repository;
}
public function postRestaurent(RestaurentRequest $request){
$data = $request->all();
$data['admin_id'] = $this->getAccountId($request);
$this->authorize('create');
$rest = $this->repository->create($data);
return response()->json(fractal($rest,new RestuarentTransformer));
}
}
RestaurentPolicy.php
public function create(User $user)
{
return ($user->admin_id=1) ? true : false;
}
api.php
Route::post('/postRest',[RestaurentsController::class,'postRestaurent'])->middleware(['CheckAdmin']);
If you use Request Classes you have to change authorize method return false to true
class RestaurentStoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return false;
}
}
at the moment i do a tutorial called "roles and permissions in laravel" from codecourse.com.
In part 4 of the tutorial i have the problem i get everytime the result true.
If i ask for the permission "edit posts" it should show me true, if i ask for the permission "delete posts" it should show me false.
I checked the database relationship, but there is no relationship between the user and the permission "delete posts".
Only if i ask for a permission that not exist like "blabla" (i mean not exist in the database) i got false.
I believe he is only checking is there a permission with this name and not checking have the user the permission.
web.php
Route::get('/', function (\illuminate\Http\Request $request) {
$user = $request->user();
dump($user->can("delete posts"));});
HasPermissionTrait.php
trait HasPermissionsTrait {
public function hasRole(...$roles)
{
foreach ($roles as $role) {
if ($this->roles->contains('name', $role)) {
return true;
}
}
return false;
}
public function hasPermissionTo($permission) {
//Check has permission through role
return $this->hasPermission($permission);
}
protected function hasPermission($permission) {
return (bool) $this->permissions->where('name', $permission->name);
}
public function roles() {
return $this->belongsToMany(Role::class, 'users_roles');
}
public function permissions() {
return $this->belongsToMany(Permission::class, 'users_permissions');
}
PermissionsServiceProvider.php
public function boot()
{
Permission::get()->map(function ($permission) {
Gate::define($permission->name, function ($user) use ($permission) {
return $user->hasPermissionTo($permission);
});
});
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
you can watch my full code here -> https://github.com/RahmanG/joko
On this image you can see the Auth. There is no permission "delete posts". But you can see the Gate is giving true.
https://imgur.com/a/gf923
Thank you for supporting
i got already the answer. Thank you to tykus from laracasts.com
tykus:
Looks like your trait might have a mistake:
protected function hasPermission($permission) {
return (boolean) $this->permissions->where('name', $permission->name);
}
$this->permissions->where('name', $permission->name) returns a Builder instance, and an object cast to a boolean always is true.
You probably need to return a count or first - something that would be falsey if there was no permission, e.g.
protected function hasPermission($permission) {
return (boolean) $this->permissions->where('name', $permission->name)->count();
}
This is my User model:
/**
* The settings that belong to the user.
*/
public function settings()
{
return $this->hasMany(Setting_user::class);
}
/**
* Get user's avatar.
*/
public function avatar()
{
$avatar = $this->settings()->where('id',1);
if(count($this->settings()->where('id',1)) == 0 )
{
return "default-avatar.jpg";
}
return $this->settings()->where('id',1);
}
In my view I am accessing the value like that:
Auth::user()->avatar
When the user has an avatar everything is fine. But when is empty the method avatar() returns a string and I get the following error:
Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation (View: C:\xampp\htdocs\laravel\laravel-paper-dashboard\resources\views\dashboard\user-profile.blade.php)
You may want to use an Eloquent Accessor instead.
public function getAvatarAttribute() {
$avatar = $this->settings()->where('id',1)->first(); // Changed this to return the first record
if(! $avatar)
{
return "default-avatar.jpg";
}
// You will need to change this to the correct name of the field in the Setting_user model.
return $avatar->the_correct_key;
}
This will allow you to then call Auth::user()->avatar in your templates.
Otherwise Eloquent thinks you're trying to get a relationship.
I just recently downloaded yii2 advanced template and create new model in frontend module that extend User in "common/models" like this
class UsUser extends User
{
}
class SignupForm extends Model
{
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if ($this->validate()) {
$user = new UsUser();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->save();
return $user;
}
return null;
}
When I signup, there is no error and simply get redirected to main page but no data is inserted into db. I do not use public attribute in my model (either User or UsUser) as specified by Tal V. in here (Yii2 active record model not saving data . So only #property annotation in UsUser.
Maybe I am doing it wrong or is there something else to be aware of, could somebody help pointing it out? Many Thanks.
class SignupForm extends Model
{
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if ($this->validate())
{
$user = new UsUser();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
//IF UsUser MODEL IS VALID THEN SAVE DATA
if ($user->validate())
{
$user->save(false);
return $user;
}
//IF UsUser MODEL IS NOT VALID THEN PRINT THE ERRORS.SO YOU CAN CHECK WHAT ARE THE ERRORS IN MODEL
else
{
echo "<pre>";
print_r($user->getErrors());
echo "</pre>";
}
}
}
}
I'm testing silex, mongodb and Form validation. And I run into a validation issue when using MongoDB ODM and a before middelware , wether it is security related or not.
I'm given a document and have added an Unique constraint on a field of the document.
If the document is not requested before the validation actually executes, everything works fine.
Let's say I have a before middleware that requests the document before the controller with validation is executed. In that case the unique constraint does not work properly and displays an error message saying This value is already used. But it should not since the value used is unique to the object that is validated.
To sum up, the issue is, when validating a document with an Unique Constraint on a field, if the document is requested through the document manager (with no modification performed on the document) before the validation code is actually executed, it seems the Unique constraint does not work properly.
I'm going to set up a test case but in the mean time, here is an example of how I set up the validation on the document; if anybody has come across the issue please let me know.
namespace Document;
//use Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique as MongoDBUnique;
use Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Mapping\ClassMetadata;
/**
* #ODM\Document(collection="blog_post")
*/
class Post
{
/**
* #ODM\Id
*
*/
protected $id;
/**
* #ODM\String
* #ODM\UniqueIndex
*/
protected $title;
/**
* #ODM\String
*/
protected $body;
/**
* #ODM\Date
*/
protected $createdAt;
/**
* #ODM\ReferenceOne(targetDocument="Document\User",cascade="update,merge",inversedBy="posts")
*/
protected $user;
function __construct() {
}
public function getTitle() {
return $this->title;
}
public function setTitle($title) {
$this->title = $title;
}
public function getBody() {
return $this->body;
}
public function setBody($body) {
$this->body = $body;
}
public function getCreatedAt() {
return $this->createdAt;
}
public function setCreatedAt($createdAt) {
$this->createdAt = $createdAt;
}
public function getId() {
return $this->id;
}
function getUser() {
return $this->user;
}
function setUser(User $user) {
$this->user = $user;
$this->user->addPost($this);
}
function __toString() {
return $this->title;
}
static function loadValidatorMetadata(ClassMetadata $metadatas) {
$metadatas->addPropertyConstraint("body", new Length(array('min'=>10,'max'=>1000)));
$metadatas->addPropertyConstraint("title", new Length(array('min'=>5,'max'=>255)));
$metadatas->addConstraint(new Unique(array('fields' => 'title')));
}
}
The app is in this Github repository. (work in progress):
Edit 1: An example of a before middleware that would trigger the erratic behavior of the Unique Constraint (in demo/mongoddb/blog/app/Config.php file in the repo linked) :
$app['must_be_post_owner'] = $app->protect(function(Request $req)use($app) {
$postId = $req->attributes->get('id');
$user = $app['security']->getToken()->getUser();
$post = $app['odm.dm']->getRepository('Document\Post')->findOneBy(array('id' => $postId));
if ($post->getUser() !== $user) {
$app['logger']->alert("Access denied for user $user to post with id $postId ");
$app->abort(500, 'You cant access this resource !');
}
}
);
Edit 2: I tried to debug the Symfony/Doctrine-Bridge UniqueEntityValidator class with XDebug but I get socket errors every time there is a MongoDB related function executed during step debugging.