kodeine / laravel-acl

Light-weight role-based permissions system for Laravel 6+ built in Auth system.
MIT License
786 stars 215 forks source link

How to use the blade extensions? #86

Open kaju74 opened 9 years ago

kaju74 commented 9 years ago

Hi.

I'm not sure, how to use the acl blade extensions and I had to enable them manually? If i use something like:

@role('admin|moderator')
    // content allowed for admin's only
@endrole

...the template renders this as plain text. The @role attribute won't be processed.

kodeine commented 9 years ago

@kaju74 i will take a look on it and get back to you. What version of laravel are you trying to run the acl?

kodeine commented 9 years ago

@kaju74 are you on laravel-acl's master branch?

thespacebean commented 8 years ago

I'm having the same issue with laravel 5.0 and laravel-acl ~1.0@dev

kodeine commented 8 years ago

@thespacebean please try and use master branch and let me know if that works for you.

kristofvandam commented 8 years ago

Hi, i have the same issue as kaju74.

i updated to the master branch, but still the same problem.

CptMeatball commented 8 years ago

Same here.

kodeine commented 8 years ago

@CptMeatball @kristofvandam @thespacebean @kaju74 please try version ~1.0 and let me know .

thanks

andreiculda commented 8 years ago

@kodeine I tried with the latest version and role blade extension still does not work. I have this in my view and it does not work:

@role('admin')
     show some content
@endrole

but if I use permission template it works:

@permission('update.all_users')
     show some content
@endpermission

My guess it's that it has something to do with the is() function from HasRole.php. I have this controller in which the is() function also does not work:

public function roles(){
    $admin = Auth::user()->is('admin');
    if($admin) {
       return view('pages.roles.index');
    }
    return 'something else';      
}

In my case the auth user actually has admin role but the return is:

$admin = false

If I use the can() function then it works:

$admin = Auth::user()->can('update.all_users');

result:

$admin = true

Hope this gives you a clue on what is actually going on.

In other thoughts would this be possible to achieve in the current version and how:

@permission(!'update.all_users')
     show some content when the user does not have permission to update all_users
@endpermission

EDIT:

Well I found a solution for my last question (not sure how elegant or correct, but it works). In App\Providers\AppServiceProvider.php boot method I put a new blade directive:

public function boot()
    {
        Blade::directive('ifnotpermitted', function($expression) {
            return "<?php if (Auth::check() && !Auth::user()->can{$expression}) { ?>";
        });
        Blade::directive('endifnotpermitted', function($expression) {
            return "<?php } ?>";
        });
    }

and then in my view i call it like this:

@ifnotpermitted('update.all_users')
      <span class="has-error">You do not have permission to update this resource</span>
@endifnotpermitted
kodeine commented 8 years ago

@andreiculda

can you try this function on laravel 5.0

protected function registerBladeExtensions()
    {
        $blade = $this->app['view']->getEngineResolver()->resolve('blade')->getCompiler();
        $blade->extend(function ($view, $compiler) {
            $pattern = $compiler->createMatcher('role');
            return preg_replace($pattern, '<?php if (Auth::check() && Auth::user()->is$2): ?> ', $view);
        });

        $blade->extend(function ($view, $compiler) {
            $pattern = $compiler->createPlainMatcher('endrole');
            return preg_replace($pattern, '<?php endif; ?>', $view);
        });

        $blade->extend(function ($view, $compiler) {
            $pattern = $compiler->createMatcher('permission');
            return preg_replace($pattern, '<?php if (Auth::check() && Auth::user()->can$2): ?> ', $view);
        });

        $blade->extend(function ($view, $compiler) {
            $pattern = $compiler->createPlainMatcher('endpermission');
            return preg_replace($pattern, '<?php endif; ?>', $view);
        });
    }
andreiculda commented 8 years ago

Hi @kodeine. I currently do not have an open project on Laravel 5.0. I will try make time to make a new app and test your function in the upcoming days.

As for Laravel 5.1 and up this methods were removed.Upgrade to Laravel 5.1:

The createMatcher(), createOpenMatcher(), and createPlainMatcher() methods have been removed from the Blade compiler. Use the new directive method to create custom directives for Blade in Laravel 5.1. Consult the extending blade documentation for more information.

kodeine commented 8 years ago

@andreiculda i've pushed some changes for blade, it will support 5.0 and on wards now.

andreiculda commented 8 years ago

@kodeine I saw your changes but unfortunately (at least for me) this does not work (I made composer udate):

@role('admin')
    Admin button
@endrole

... and neither does this:

@if(Auth::user()->is('admin'))
    Admin button
@endif

This works:

@if(!Auth::user()->is('admin'))
    NonAdmin button
@endif

//and so does this:
@role(!'admin')
    NonAdmin button
@endrole

It's like my user doesn't have admin role assigned, but it does. Can anyone elso test it as well?

kodeine commented 8 years ago

@andreiculda hmm its weird, works fine for me. Can you please paste me your model and code so i can take a look and replicate the code locally and try.

andreiculda commented 8 years ago

Ok so here is my User model:

<?php

namespace App;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Kodeine\Acl\Traits\HasRole;

class User extends Model implements AuthenticatableContract,
                                    AuthorizableContract,
                                    CanResetPasswordContract
{
    use Authenticatable, Authorizable, CanResetPassword, HasRole {
        HasRole::can insteadof Authorizable;
    }

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['username', 'email', 'password', 'password_confirmation', 'language', 'address_id', 'details_id'];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = ['password', 'remember_token'];

    /**
     * @return array
     */
    public function getTableColumns() {
        return $this->getConnection()->getSchemaBuilder()->getColumnListing($this->getTable());
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function details(){

        return $this->hasOne('App\UserDetail', 'user_id');

    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function address(){

        return $this->hasOne('App\UserAddress', 'user_id');

    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function photos(){

        return $this->hasMany('App\UserPhoto', 'user_id');

    }
}

An the controler:

<?php

namespace App\Http\Controllers\Users;

use App\User;
use App\UserAddress;
use App\UserDetail;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Response;
use Exception;
use Validator;
use JavaScript;
use Yajra\Datatables\Datatables;

class UsersController extends Controller{

    /**
     * @return $this
     */
    public function index() {

        $admin = Auth::user()->is('admin'); //this is false

        $users = User::orderBy('id', 'desc')->get();

        return view('pages.users.index')

            ->with([

                'users'      => $users,

            ]);

    }

}

and the blade usage:

@role('admin')

    <div class="btn-group btn-group-devided" data-toggle="buttons">
        <a href="#" class="btn btn-info" data-toggle="modal" data-target="#newUser" id="openNewUserModal">
            <i class="fa fa-plus"></i>
            {{trans('users.add_new_user')}}
        </a>
    </div>

    @include('pages.users.partials.new_user_modal')

@endrole

Please let me know if you need something else ...

techguydev commented 6 years ago

Hello all,

I was having the same problem, I'm using Laravel 5.5.4 and after testing everything I found I have been making some test and finally it is working properly, this is what I did:

I changed @role('admin') for:

@if(Auth::check() && Auth::user()->isRole('admin')) And refreshed the page, after that I changed it back to @role('admin') and it is now working nicely.

I guess it has something to do with cache.

I hope this helps someone.