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

问题描述 投票:0回答:1

Laravel 10 应用程序,带有 Jetstream/Inertia/Vue 3。

我使用laravel-spatie-permissions-vue来处理用户权限和角色,分配ok。目前我正在使用默认的 Jetstream 视图,因此当用户登录仪表板时会显示,我将其放在 Components/Welcome.vue 上:

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

出于测试目的,有两个角色:管理员和用户,也有一些权限,但由于它们都有相同的问题,所以我们只保留角色。 问题是,第一次登录时,以用户为例,没有显示任何内容,这是错误的。如果刷新页面,“是用户”。将会出现,正如它应该出现的那样。然后,如果您注销并使用管理员身份登录,则“是用户”。将显示(不正确),但如果刷新页面“是管理员”。将显示(正确)。 我在开发中使用 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
  • 将特征添加到用户模型(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']"

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

php laravel vuejs3 vue-component inertiajs
1个回答
1
投票

首先您需要知道:您在
window.Laravel
文件中分配的
window.vueSpatiePermissions
app.blade.php
变量是在创建 vue 应用程序时分配的。因此,更改 vue 应用程序上浏览器中的路由或通过 api 进行 loginlogout 不会更改你的 `app.blade.php` 视图或不会重新加载。

那么解决方案是什么?我为自己的应用程序做了什么?

首先,我使用这个[https://github.com/ahmedsaoud31/laravel-permission-to-vuejs][1]做了这些:

在**用户**模型中:
use LaravelPermissionToVueJS;

app.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 请求来重定向页面,从而重新加载页面。

这是一个不必要且不专业的解决方案。除此之外,我将在下面解释您可以再次执行的解决方案。

我的

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

由于我没有时间,所以无法详述。如果您还有疑问,请写为评论。

© www.soinside.com 2019 - 2024. All rights reserved.