Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
moroneyio authored Apr 19, 2022
0 parents commit 0ee0d00
Show file tree
Hide file tree
Showing 21 changed files with 1,056 additions and 0 deletions.
30 changes: 30 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "itsmejoshua/novaspatiepermissions",
"description": "A Laravel Nova tool.",
"keywords": [
"laravel",
"nova"
],
"license": "MIT",
"require": {
"php": "^8.0",
"spatie/laravel-permission": "^5.5"
},
"autoload": {
"psr-4": {
"Itsmejoshua\\Novaspatiepermissions\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Itsmejoshua\\Novaspatiepermissions\\ToolServiceProvider"
]
}
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true
}
33 changes: 33 additions & 0 deletions mix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const mix = require('laravel-mix')
const webpack = require('webpack')
const path = require('path')

class NovaExtension {
name() {
return 'nova-extension'
}

register(name) {
this.name = name
}

webpackConfig(webpackConfig) {
webpackConfig.externals = {
vue: 'Vue',
}

webpackConfig.resolve.alias = {
...(webpackConfig.resolve.alias || {}),
'laravel-nova': path.join(
__dirname,
'../../vendor/laravel/nova/resources/js/mixins/packages.js'
),
}

webpackConfig.output = {
uniqueName: this.name,
}
}
}

mix.extend('nova', new NovaExtension())
19 changes: 19 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"prod": "npm run production",
"production": "mix --production"
},
"devDependencies": {
"@vue/compiler-sfc": "^3.2.22",
"laravel-mix": "^6.0.41",
"postcss": "^8.3.11",
"vue-loader": "^16.8.3"
},
"dependencies": {}
}
153 changes: 153 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# A Laravel Nova tool for the Spatie Permission package

[![License](https://poser.pugx.org/insenseanalytics/laravel-nova-permission/license)](https://packagist.org/packages/insenseanalytics/laravel-nova-permission)
[![Latest Stable Version](https://poser.pugx.org/insenseanalytics/laravel-nova-permission/v/stable)](https://packagist.org/packages/insenseanalytics/laravel-nova-permission)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/insenseanalytics/laravel-nova-permission/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/insenseanalytics/laravel-nova-permission/?branch=master)
[![Total Downloads](https://poser.pugx.org/insenseanalytics/laravel-nova-permission/downloads)](https://packagist.org/packages/insenseanalytics/laravel-nova-permission)

This [Nova](https://nova.laravel.com) tool lets you:
- manage roles and permissions on the Nova dashboard
- use permissions based authorization for Nova resources

## Screenshots
<img alt="screenshot of the backup tool" src="https://insenseanalytics.github.io/public-assets/laravel-nova-permission/nova-permission-screenshot.png" />

## Requirements & Dependencies
There are no PHP dependencies except the [Laravel Nova](https://nova.laravel.com) package and the [Spatie Permission](https://github.com/spatie/laravel-permission) package.

## Installation
You can install this tool into a Laravel app that uses [Nova](https://nova.laravel.com) via composer:

```bash
composer require insenseanalytics/laravel-nova-permission
```

Next, if you do not have package discovery enabled, you need to register the provider in the `config/app.php` file.
```php
'providers' => [
...,
Insenseanalytics\LaravelNovaPermission\NovaPermissionServiceProvider::class,
]
```

Next, you must register the tool with Nova. This is typically done in the `tools` method of the `NovaServiceProvider`.

```php
// in app/Providers/NovaServiceProvider.php

public function tools()
{
return [
// ...
\Insenseanalytics\LaravelNovaPermission\LaravelNovaPermission::make(),
];
}
```

Next, add `MorphToMany` fields to your `app/Nova/User` resource:

```php
use Laravel\Nova\Fields\MorphToMany;

public function fields(Request $request)
{
return [
// ...
MorphToMany::make('Roles', 'roles', \Insenseanalytics\LaravelNovaPermission\Role::class),
MorphToMany::make('Permissions', 'permissions', \Insenseanalytics\LaravelNovaPermission\Permission::class),
];
}
```

Finally, add the `ForgetCachedPermissions` class to your `config/nova.php` middleware like so:

```php
// in config/nova.php
'middleware' => [
'web',
Authenticate::class,
DispatchServingNovaEvent::class,
BootTools::class,
Authorize::class,
\Insenseanalytics\LaravelNovaPermission\ForgetCachedPermissions::class,
],
```

## Localization

You can use the artisan command line tool to publish localization files:

```php
php artisan vendor:publish --provider="Insenseanalytics\LaravelNovaPermission\NovaPermissionServiceProvider"
```

## Using Custom Role/Permission Resource Classes

If you want to use custom resource classes you can define them when you register a tool:

```php
// in app/Providers/NovaServiceProvider.php

public function tools()
{
return [
// ...
\Insenseanalytics\LaravelNovaPermission\LaravelNovaPermission::make()
->roleResource(CustomRole::class)
->permissionResource(CustomPermission::class),
];
}
```

## Permissions Based Authorization for Nova Resources
By default, Laravel Nova uses Policy based authorization for Nova resources. If you are using the Spatie Permission library, it is very likely that you would want to swap this out to permission based authorization without the need to define Authorization policies.

To do so, you can use the `PermissionsBasedAuthTrait` and define a `permissionsForAbilities` static array property in your Nova resource class like so:

```php
// in app/Nova/YourNovaResource.php

class YourNovaResource extends Resource
{
use \Insenseanalytics\LaravelNovaPermission\PermissionsBasedAuthTrait;

public static $permissionsForAbilities = [
'all' => 'manage products',
];
}
```

The example above means that all actions on this resource can be performed by users who have the "manage products" permission. You can also define separate permissions for each action like so:

```php
public static $permissionsForAbilities = [
'viewAny' => 'view products',
'view' => 'view products',
'create' => 'create products',
'update' => 'update products',
'delete' => 'delete products',
'restore' => 'restore products',
'forceDelete' => 'forceDelete products',
'addAttribute' => 'add product attributes',
'attachAttribute' => 'attach product attributes',
'detachAttribute' => 'detach product attributes',
];
```

### Relationships
To allow your users to specify a relationship on your model, you will need to add another permission on the Model.
For example, if your `Product` belongs to `User`, add the following permission on `app/Nova/User.php`. :

```php
public static $permissionsForAbilities = [
'addProduct' => 'add user on products'
];
```

## Contributing

Contributions are welcome and will be fully credited as long as you use PSR-2, explain the issue/feature that you want to solve/add and back your code up with tests. Happy coding!

## License

The MIT License (MIT). Please see [License File](LICENSE.txt) for more information.
1 change: 1 addition & 0 deletions resources/css/tool.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* Nova Tool CSS */
50 changes: 50 additions & 0 deletions resources/js/pages/Tool.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<template>
<div>
<Head title="Novaspatiepermissions" />

<Heading class="mb-6">Novaspatiepermissions</Heading>

<Card
class="flex flex-col items-center justify-center"
style="min-height: 300px"
>
<svg
class="spin fill-80 mb-6"
width="69"
height="72"
viewBox="0 0 23 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M20.12 20.455A12.184 12.184 0 0 1 11.5 24a12.18 12.18 0 0 1-9.333-4.319c4.772 3.933 11.88 3.687 16.36-.738a7.571 7.571 0 0 0 0-10.8c-3.018-2.982-7.912-2.982-10.931 0a3.245 3.245 0 0 0 0 4.628 3.342 3.342 0 0 0 4.685 0 1.114 1.114 0 0 1 1.561 0 1.082 1.082 0 0 1 0 1.543 5.57 5.57 0 0 1-7.808 0 5.408 5.408 0 0 1 0-7.714c3.881-3.834 10.174-3.834 14.055 0a9.734 9.734 0 0 1 .03 13.855zM4.472 5.057a7.571 7.571 0 0 0 0 10.8c3.018 2.982 7.912 2.982 10.931 0a3.245 3.245 0 0 0 0-4.628 3.342 3.342 0 0 0-4.685 0 1.114 1.114 0 0 1-1.561 0 1.082 1.082 0 0 1 0-1.543 5.57 5.57 0 0 1 7.808 0 5.408 5.408 0 0 1 0 7.714c-3.881 3.834-10.174 3.834-14.055 0a9.734 9.734 0 0 1-.015-13.87C5.096 1.35 8.138 0 11.5 0c3.75 0 7.105 1.68 9.333 4.319C16.06.386 8.953.632 4.473 5.057z"
fill-rule="evenodd"
/>
</svg>

<h1 class="dark:text-white text-4xl font-light mb-6">
We're in a black hole.
</h1>

<p class="dark:text-white text-lg opacity-70">
You can edit this tool's component at:
<code
class="ml-1 border border-gray-100 dark:border-gray-900 text-sm font-mono text-white bg-black rounded px-2 py-1"
>
/nova-components/Novaspatiepermissions/resources/js/components/Tool.vue
</code>
</p>
</Card>
</div>
</template>

<script>
export default {
mounted() {
//
},
}
</script>

<style>
/* Scoped Styles */
</style>
5 changes: 5 additions & 0 deletions resources/js/tool.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Tool from './pages/Tool'

Nova.booting((app, store) => {
Nova.inertia('Novaspatiepermissions', Tool)
})
14 changes: 14 additions & 0 deletions resources/lang/en/lang.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

return [
'sidebar_label' => 'Roles & Permissions',
'name' => 'Name',
'display_name' => 'Display Name',
'guard_name' => 'Guard Name',
'created_at' => 'Created at',
'updated_at' => 'Updated at',
'Roles' => 'Roles',
'Role' => 'Role',
'Permissions' => 'Permissions',
'Permission' => 'Permission',
];
19 changes: 19 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Tool API Routes
|--------------------------------------------------------------------------
|
| Here is where you may register API routes for your tool. These routes
| are loaded by the ServiceProvider of your tool. They are protected
| by your tool's "Authorize" middleware by default. Now, go build!
|
*/

// Route::get('/', function (Request $request) {
// //
// });
19 changes: 19 additions & 0 deletions routes/inertia.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

use Illuminate\Support\Facades\Route;
use Laravel\Nova\Http\Requests\NovaRequest;

/*
|--------------------------------------------------------------------------
| Tool Routes
|--------------------------------------------------------------------------
|
| Here is where you may register Inertia routes for your tool. These are
| loaded by the ServiceProvider of the tool. The routes are protected
| by your tool's "Authorize" middleware by default. Now - go build!
|
*/

Route::get('/', function (NovaRequest $request) {
return inertia('Novaspatiepermissions');
});
33 changes: 33 additions & 0 deletions src/ForgetCachedPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Itsmejoshua\Novaspatiepermissions;

use Laravel\Nova\Nova;
use Spatie\Permission\PermissionRegistrar;

class ForgetCachedPermissions
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return \Illuminate\Http\Response
*/
public function handle($request, $next)
{
$response = $next($request);

if ($request->is('nova-api/*/detach') ||
$request->is('nova-api/*/*/attach/*')) {
$permissionKey = (Nova::resourceForModel(app(PermissionRegistrar::class)->getPermissionClass()))::uriKey();

if ($request->viaRelationship === $permissionKey) {
app(PermissionRegistrar::class)->forgetCachedPermissions();
}
}

return $response;
}
}
Loading

0 comments on commit 0ee0d00

Please sign in to comment.