laravel-acl icon indicating copy to clipboard operation
laravel-acl copied to clipboard

How to use the blade extensions?

Open kaju74 opened this issue 10 years ago • 15 comments
trafficstars

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.

kaju74 avatar Aug 25 '15 12:08 kaju74

@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 avatar Aug 25 '15 18:08 kodeine

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

kodeine avatar Sep 01 '15 14:09 kodeine

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

thespacebean avatar Oct 01 '15 10:10 thespacebean

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

kodeine avatar Oct 01 '15 14:10 kodeine

Hi, i have the same issue as kaju74.

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

kristofvandam avatar Oct 11 '15 16:10 kristofvandam

Same here.

CptMeatball avatar Oct 12 '15 13:10 CptMeatball

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

thanks

kodeine avatar Jan 31 '16 18:01 kodeine

@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

andreiculda avatar Feb 04 '16 09:02 andreiculda

@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);
        });
    }

kodeine avatar Feb 04 '16 16:02 kodeine

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.

andreiculda avatar Feb 05 '16 10:02 andreiculda

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

kodeine avatar Feb 06 '16 01:02 kodeine

@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?

andreiculda avatar Feb 06 '16 12:02 andreiculda

@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.

kodeine avatar Feb 06 '16 16:02 kodeine

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 ...

andreiculda avatar Feb 06 '16 17:02 andreiculda

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.

techguydev avatar Jun 07 '18 15:06 techguydev