laravel-spatie-permissions-vue权限和角色需要刷新页面以显示当前值

xv8emn3q  于 2023-03-19  发布在  其他
关注(0)|答案(1)|浏览(156)

Laravel 10应用程序,与Jetstream/惯性/Vue 3.
我使用laravel-spatie-permissions-vue来处理用户权限和角色,这些权限和角色都分配得很好。目前我使用默认的Jetstream视图,所以当用户登录到 Jmeter 板时, Jmeter 板会显示这些信息,我将其放在Components/Welcome.vue上:

<div v-if="is('administrator')">is administrator.</div>
<div v-if="is('user')">is user.</div>

出于测试的目的,有两个角色,管理员和用户,也有一些权限,但这两个角色都有同样的问题,让我们只使用角色。问题是,当你第一次登录时,让我们使用用户,什么都不显示,这是错误的。如果你刷新页面,“is user.”将出现,这是应该的。然后,如果你注销并使用管理员登录,将显示“is user.”(不正确),但如果刷新页面,将显示“is administrator.”(正确)。我在开发中使用valet和"npm run dev“时得到的行为与部署到apache服务器并执行”npm run build“时得到的行为相同。
我按照https://github.com/geowrgetudor/laravel-spatie-permissions-vue的所有说明操作。
我已经找了两天了,但是我没有发现任何人有同样的问题,我想我犯了一个愚蠢的错误。我认为这个问题应该与app.blade.php部分有关,也许它与缓存有关,但是没有发现任何类似的问题,所以在这一点上没有线索。
我尝试的内容(仅相关步骤):

laravel new application
composer require laravel/jetstream
php artisan jetstream:install inertia
npm i @vitejs/plugin-vue
npm install -D tailwindcss postcss autoprefixer
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
composer require geowrgetudor/laravel-spatie-permissions-vue
  • 将trait添加到用户模型(User.php):
use SpatiePermissionVue\Traits\RolesPermissionsToVue;

class User extends Authenticatable
{
    // ...
    use RolesPermissionsToVue;
}
  • (app.js)导入并使用laravel-spatie-permissions-vue插件到app.js文件中:
import RolesPermissionsToVue from "../../vendor/geowrgetudor/laravel-spatie-permissions-vue/src/js";

// createInertiaApp, right after '.use(ZiggyVue, Ziggy)':
            .use(RolesPermissionsToVue)
  • (app.blade.php)将Spatie角色和权限传递给app.blade.php中名为vueSpatiePermissions的全局变量:
<script type="text/javascript">
  window.vueSpatiePermissions = {!! auth()->check() ? auth()->user()->getRolesPermissionsAsJson() : 0 !!}
</script>

在Components/Welcome.vue上添加了以下内容:

<div v-if="is('administrator')">is administrator.</div>
<div v-if="is('user')">is user.</div>

我还以为用户登录后会显示“是管理员"或”是用户“,而不必刷新页面。
用户已正确分配角色和权限,可以在HandleInertiaRequests的share()函数中添加以下代码进行检查:

$permissions = Auth::check() ? Auth::user()->permissions->pluck('name') : "";
        $roles = Auth::check() ? Auth::user()->roles->pluck('name') : "";
        return array_merge(parent::share($request), [
            'auth.user.permissions' => $permissions,
            'auth.user.roles' => $roles
        ]);

然后在视图中添加{{ $page.props.auth.user.roles }}或{{ $page.props.auth.user.permissions }},所以这不是问题。
任何帮助都将不胜感激。谢谢。
最后,由于cengsemihsahin的回应,我改变了我的处理方式,最终我转到了How to Add Roles and Permission to Laravel Fortify + Inertia + vue?,在那里我使用了Viduranga的方法,因为这样就不需要laravel-apatie-permissions-vue或laravel-permission-to-vuejs,只需要在HandleInertiaRequests中更改share()函数(这是我的):

public function share(Request $request): array
    {
        $permissions = Auth::check() ? Auth::user()->permissions->mapWithKeys(function($pr){ return [$pr['name'] => true]; }) : [];
        $roles = Auth::check() ? Auth::user()->roles->mapWithKeys(function($pr){ return [$pr['name'] => true]; }) : [];
        return array_merge(parent::share($request), [
            'auth.user.permissions' => $permissions,
            'auth.user.roles' => $roles
        ]);
    }

那么你可以在你的视图中使用它:

v-if="$page.props.auth.user.roles['administrator']"

我认为这个解决方案比我在项目中使用的解决方案更好。

w1jd8yoj

w1jd8yoj1#

首先你需要知道:你在app.blade.php文件中分配的window.Laravelwindow.vueSpatiePermissions变量是在你的vue应用程序创建时分配的,所以,在你的vue应用程序的浏览器中改变路由或者通过API进行loginlogout不会改变你的app.blade.php视图或者不重新加载。
那么,解决方案是什么?我为自己的应用程序做了哪些工作?
首先,我使用这个[https://github.com/ahmedsaoud31/laravel-permission-to-vuejs][1]:
用户模型中:

use LaravelPermissionToVueJS;

应用程序.blade.php中

<script type="text/javascript">
    window.Laravel = {
        csrfToken: "{{ csrf_token() }}",
        jsPermissions: {!! auth()->check() ? auth()->user()->jsPermissions() : 0 !!}
    };
</script>

main.js中(创建应用程序时)

import App from './App.vue';
import LaravelPermissionToVueJS from 'laravel-permission-to-vuejs';
const app = createApp(App);
app.use(LaravelPermissionToVueJS);
app.mount('#app');

在我的解决方案中(在我自己的应用程序中),通过在浏览器上每次执行loginlogout操作时提供HTTP请求,在重定向页面时重新加载页面。
这是一个不必要的和不专业的解决方案。除此之外,我会解释解决方案,你可以做一遍下面一点。
My login.vue(以最短为例)

<form class="d-none" method="post" action="/auth/login">
    <input type="hidden" name="_token" :value="csrf">
    <input type="hidden" name="username" :value="user.username">
    <input type="hidden" name="password" :value="user.password">
    <button ref="submitLoginForm" class="d-none"></button>
</form>
<form class="text-start" @submit="login">
    <div class="form">
        <div id="username-field" class="field-wrapper input">
            <input type="text" name="username" class="form-control"
                required v-model="user.username"
                placeholder="username" />
        </div>
        <div id="password-field" class="field-wrapper input mb-2">
            <input
                :type="show_password ? 'text' : 'password'"
                v-model="user.password"
                name="password"
                class="form-control"
                required
                placeholder="passphrase"
            />
        </div>
        <button type="submit" class="btn btn-primary">login</button>
    </div>
</form>

<script>
export default {
    data() {
        return {
            csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
            user: {
                username: '',
                password: '',
                remember: false,
            }
        }
    },
    methods: {
        login(e) {
            e.preventDefault();
            store.dispatch('login', this.user);
            this.$refs.submitLoginForm.click();
        }
    }
}
</script>

您可以使用composition API,也可以引用defineExpose并提交表单。
然后页面会自动刷新,并在API和web端都提供登录。我这样做是有原因的,具体到我自己的应用程序。

这是我的例子。那么如何做到这一点而不重新加载呢?

登录并将用户信息分配给存储区或其他地方的变量后,即可将该用户的权限分配给“window.Laravel.jsPermissions.permissions”变量。
基本上,在不刷新页面的情况下为每个登录-注销用户更改此变量的值将解决您的问题。
另外,假设有人(例如,从管理面板)更改了用户的角色或权限,您可以在此时触发或广播事件。
在这种情况下,您可以发送权限并将其分配给所捕获视图中的“window.Laravel.jsPermissions.permissions”变量。示例(带Pusher

window.Echo.private('permissions').listen('.user_permissions_changed', (e) => {
    console.log(e);
    window.Laravel.jsPermissions.permissions = e.user_permissions;
});

由于时间关系,我不能详细介绍。如果你还有问题,请写评论。

相关问题