Я нахожусь в процессе интеграции Laravel Permission API с интерфейсом Vue.JS. Я использую библиотеку https://github.com/spatie/laravel-permission для Laravel Permission. Я не понимаю, как я могу проверить разрешение во внешнем интерфейсе Vue JS (в лезвии Laravel я использую @Can для проверки разрешения).






Я буквально работаю над тем же самым. Я думаю о добавлении настраиваемая директива Vue, который будет проверять массив Laravel.permissions.
Это может быть даже так просто, как
Vue.directive('can', function (el, binding) {
return Laravel.permissions.indexOf(binding) !== -1;
})
Я не тестировал этот код. Просто мозговой штурм здесь.
<button v-can = "editStuff">You can edit this thing</button>
Я могу удерживать разрешения таким образом:
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
'userId' => Auth::user()->id,
'permissions' => Auth::user()->permissions()->pluck('name')->toArray()
]); ?>
Как получить массив разрешений laravel во vue js?
Думаю, вы бы просто использовали <script type = "text/javascript"> window.Laravel = { permissions: Json.parse('@json(\Auth::user()->permissions)') };</script> где-нибудь в шаблоне лезвия (скорее всего, layout.blade.php).
Я думаю, вы захотите настроить конечную точку, которую вы можете запустить из внешнего интерфейса vue, которая вернет вам разрешения пользователя, в противном случае, в приведенном выше примере, что не позволяет пользователю редактировать свои разрешения и получать доступ к все.
@wheelmaker это не имеет значения, поскольку все, что требует разрешения, все равно будет находиться за конечной точкой, это только для макета внешнего интерфейса
это безопасный способ использования?
Вместо этого я сделаю вызов ajax для проверки разрешений, что-то вроде этого, но, конечно, вам нужно изменить его, чтобы удовлетворить ваши потребности.
Маршруты:
Route::get('/permission/{permissionName}', 'PermissionController@check');
Контроллер:
function check($permissionName) {
if (! Auth::user()->hasPermissionTo($permissionName)) {
abort(403);
}
return response('', 204);
}
Vue: (если вы хотите сделать это синхронно), это простой пример (глобальный миксин Vue), вы можете превратить его в директиву или компонент Vue.
Vue.mixin("can", (permissionName) => {
let hasAccess;
axios.get(`/permission/${permissionName}`)
.then(()=> {
hasAccess = true;
}
.catch(()=> {
hasAccess = false;
};
return hasAccess;
});
И затем каждый раз, когда вы хотите проверить разрешение, вы можете просто сделать
<el-input v-if = "can('write-stuff')"> </el-input>
Представьте, что у вас на странице 100 кнопок. И вы заходите на страницу ... Бум 100 аксиомов получают запросы. Я считаю это плохой практикой.
@IvanDavletshin Это правда, но в этом случае вы должны просто поместить v-if в общий div, содержащий эти 100 кнопок
Но это работает, только если v-if одинаковы для всех кнопок. И это можно как-то кэшировать, чтобы иметь возможность размещать кнопки, а не только в одном div. Но что, если способность должна отличаться от кнопки к кнопке. Сейчас я внедряю канканоподобную интеграцию в Laravel и Vue. Так что у них обоих будут одинаковые правила. Мне это кажется более правильным.
Привет, Шуйи, как скрыть элемент, если к нему нет доступа?
Это не сработает, поскольку запрос на получение является асинхронной операцией. Возврат hasAccess просто вернет undefined. Если вы используете async / await в миксине, он просто вернет Promise вместо разрешения.
Просто наткнулся на эту проблему и хотел бы поделиться тем, что нашел и реализовал.
public function getAllPermissionsAttribute() {
$permissions = [];
foreach (Permission::all() as $permission) {
if (Auth::user()->can($permission->name)) {
$permissions[] = $permission->name;
}
}
return $permissions;
}
<script type = "text/javascript">
@auth
window.Permissions = {!! json_encode(Auth::user()->allPermissions, true) !!};
@else
window.Permissions = [];
@endauth
</script>
Vue.directive('can', function (el, binding, vnode) {
if (Permissions.indexOf(binding.value) !== -1){
return vnode.elm.hidden = false;
}else{
return vnode.elm.hidden = true;
}
})
Здесь вы проверяете, находится ли разрешение, которое вы предоставили для директивы, в массиве разрешений из laravel. Если он найден, он скроет элемент else show, эта функция похожа на v-if.
<button type = "button" v-can = "'add_items'"></button>
Это решение от это, но вместо миксина я использую директиву. Понял идею директивы из комментария @Ismoil Shifoev выше.
Вы можете использовать этот формат в Vuejs для Laravel Permission:
<div v-if = "can('edit post')">
<!-- Edit post form -->
</div>
<div v-if = "is('super-admin')">
<!-- Show admin tools -->
</div>
добавьте функцию в модель пользователя, чтобы получить все права и роли пользователей, например:
class User extends Authenticatable
{
// ...
public function jsPermissions()
{
return json_encode([
'roles' => $this->getRoleNames(),
'permissions' => $this->getAllPermissions()->pluck('name'),
]);
}
}
передать эти данные в JavaScript в заголовке HTML:
<script type = "text/javascript">
window.Laravel = {
csrfToken: "{{ csrf_token() }}",
jsPermissions: {!! auth()->check()?auth()->user()->jsPermissions():null !!}
}
</script>
в файле app.js добавьте глобальную функцию Vuejs может для проверки прав пользователей и функцию является для проверки ролей пользователей:
Vue.prototype.can = function(value){
return window.Laravel.jsPermissions.permissions.includes(value);
}
Vue.prototype.is = function(value){
return window.Laravel.jsPermissions.roles.includes(value);
}
Я бы выбрал раствор Ральфа. Но я считаю, что лучше использую. Эта функция для получения разрешений.
public function getAllPermissionsAttribute() {
return Auth::user()->getAllPermissions()->pluck('name');
}
Просто немного чище, и поскольку я предпочитаю использовать роли вместо определенных разрешений для каждого пользователя, это решение также должно работать.
Я тоже столкнулся с той же проблемой.