├── resources ├── views │ ├── layouts │ │ ├── partials │ │ │ ├── header.blade.php │ │ │ ├── topbar.blade.php │ │ │ ├── sidebar.blade.php │ │ │ └── footer.blade.php │ │ ├── master.blade.php │ │ └── app.blade.php │ ├── permissions │ │ ├── doc.blade.php │ │ └── index.blade.php │ └── users │ │ └── index.blade.php └── assets │ ├── dashboard │ ├── css │ │ ├── custom.css │ │ └── sweetalert2.min.css │ ├── js │ │ ├── admin.min.js │ │ └── custom.js │ └── vendor │ │ ├── datatables │ │ ├── dataTables.bootstrap4.min.js │ │ └── dataTables.bootstrap4.min.css │ │ └── jquery-easing │ │ └── jquery.easing.min.js │ ├── sass │ ├── app.scss │ └── _variables.scss │ ├── js │ ├── components │ │ ├── Menu.vue │ │ ├── ExampleComponent.vue │ │ ├── NestedRawDraggableMenu.vue │ │ ├── DraggableMenu.vue │ │ ├── NestedDraggableMenu.vue │ │ └── Users.vue │ ├── app.js │ └── bootstrap.js │ └── lang │ └── en │ ├── pagination.php │ ├── auth.php │ ├── passwords.php │ └── validation.php ├── .gitattributes ├── src ├── PermissionGenarator.php ├── Contracts │ ├── User.php │ ├── Role.php │ └── Permission.php ├── Permission.php ├── Facades │ └── Permission.php ├── Http │ ├── Controllers │ │ ├── Controller.php │ │ ├── UserController.php │ │ └── PermissionController.php │ └── Middleware │ │ └── RoleMiddleware.php ├── Models │ ├── Permission.php │ ├── Role.php │ └── User.php ├── Commands │ ├── PublishPermissionViews.php │ ├── PublishPermissionResources.php │ ├── InstallPermissionDemo.php │ └── InstallPermission.php ├── Helpers │ └── helpers.php ├── Traits │ ├── HasRoles.php │ └── HasPermissions.php └── PermissionServiceProvider.php ├── mix-manifest.json ├── routes ├── permission.php └── demo.php ├── webpack.mix.js ├── config └── permission.php ├── database ├── seeds │ ├── UsersSeeder.php │ ├── PermissionDatabaseSeeder.php │ ├── RolesSeeder.php │ └── PermissionsSeeder.php └── migrations │ ├── 2018_05_26_041218_create_roles_table.php │ ├── 2019_03_15_095532_create_permissions_table.php │ ├── 2018_05_26_041708_create_role_users_table.php │ └── 2019_03_15_095857_create_permission_role_table.php ├── LICENSE ├── composer.json ├── package.json └── README.md /resources/views/layouts/partials/header.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.php linguist-language=PHP 2 | *.js linguist-language=PHP -------------------------------------------------------------------------------- /resources/assets/dashboard/css/custom.css: -------------------------------------------------------------------------------- 1 | .permission-list { 2 | list-style: none; 3 | padding: 0px; 4 | margin: 0px; 5 | } -------------------------------------------------------------------------------- /src/PermissionGenarator.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /src/Permission.php: -------------------------------------------------------------------------------- 1 | 2 |

Menu Lists

3 | 4 | 5 | 6 | 14 | -------------------------------------------------------------------------------- /routes/permission.php: -------------------------------------------------------------------------------- 1 | config('permission.controller_namespace')],function(){ 4 | // Asset 5 | Route::get('/asset', 'PermissionController@assets')->name('permission.asset'); 6 | // Test 7 | Route::get('/laravel-permission', 'PermissionController@doc')->name('permission.doc'); 8 | }); 9 | -------------------------------------------------------------------------------- /src/Facades/Permission.php: -------------------------------------------------------------------------------- 1 | 8 |
9 |
Welcome To Laravel Permission
10 |
11 |
12 |

Sorry! There is no Doc at this moment. we will add it soon. Thanks

13 |
14 | 15 | @endsection 16 | 17 | @section('scripts') 18 | 19 | @endsection -------------------------------------------------------------------------------- /resources/assets/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | 14 | mix.js('resources/assets/js/app.js', 'resources/assets/dashboard/js') 15 | .sass('resources/assets/sass/app.scss', 'resources/assets/dashboard/css'); 16 | -------------------------------------------------------------------------------- /resources/assets/js/components/ExampleComponent.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | -------------------------------------------------------------------------------- /src/Models/Permission.php: -------------------------------------------------------------------------------- 1 | belongsToMany(Role::class,'permission_role','permission_id','role_id'); 21 | } 22 | } -------------------------------------------------------------------------------- /resources/assets/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /config/permission.php: -------------------------------------------------------------------------------- 1 | '/admin', 5 | 'namespace' => '\CodexShaper\Permission', 6 | 'controller_namespace' => '\CodexShaper\Permission\Http\Controllers', 7 | 'models' => [ 8 | 'permission' => CodexShaper\Permission\Models\Permission::class, 9 | 'role' => CodexShaper\Permission\Models\Role::class, 10 | ], 11 | 'table_names' => [ 12 | 'roles' => 'roles', 13 | 'role_users' => 'role_users', 14 | 'permissions' => 'permissions', 15 | 'permission_role' => 'permission_role', 16 | ], 17 | 'resources_path' => 'vendor/codexshaper/laravel-permission/resources/assets/', 18 | 'views' => 'vendor/codexshaper/laravel-permission/resources/views', 19 | 20 | ]; -------------------------------------------------------------------------------- /resources/assets/js/components/NestedRawDraggableMenu.vue: -------------------------------------------------------------------------------- 1 | 7 | 27 | 32 | -------------------------------------------------------------------------------- /database/seeds/UsersSeeder.php: -------------------------------------------------------------------------------- 1 | name = "Admin"; 19 | $user->email = "admin@admin.com"; 20 | $user->password = Hash::make("123456789"); 21 | $user->save(); 22 | $user->assignRoles('admin,manager,user'); 23 | // $admin->role()->updateExistingPivot($admin_role, ['created_at'=>now(),'updated_at'=>now()]); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /resources/assets/js/components/DraggableMenu.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 31 | 32 | -------------------------------------------------------------------------------- /src/Commands/PublishPermissionViews.php: -------------------------------------------------------------------------------- 1 | info('Publishing Views'); 27 | $this->call('vendor:publish', ['--provider' => PermissionServiceProvider::class, '--tag' => ['permission.views']]); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Helpers/helpers.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('slug'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('roles'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Commands/PublishPermissionResources.php: -------------------------------------------------------------------------------- 1 | info('Publishing resources'); 28 | $this->call('vendor:publish', ['--provider' => PermissionServiceProvider::class, '--tag' => ['permission.resources']]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2019_03_15_095532_create_permissions_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('slug'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('permissions'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Models/Role.php: -------------------------------------------------------------------------------- 1 | belongsToMany(Permission::class,'permission_role','role_id','permission_id'); 22 | } 23 | 24 | public function users(){ 25 | return $this->belongsToMany(User::class,'role_users','role_id','user_id'); 26 | } 27 | } -------------------------------------------------------------------------------- /database/migrations/2018_05_26_041708_create_role_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('role_id'); 19 | $table->integer('user_id'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('role_users'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2019_03_15_095857_create_permission_role_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('permission_id'); 19 | $table->integer('role_id'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('permission_role'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /resources/assets/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Passwords must be at least eight characters and match the confirmation.', 17 | 'reset' => 'Your password has been reset!', 18 | 'sent' => 'We have e-mailed your password reset link!', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that e-mail address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /database/seeds/PermissionDatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | seedersPath.$class.'.php'; 23 | if ( file_exists( $file ) && !class_exists($class)) { 24 | require_once $file; 25 | } 26 | with(new $class())->run(); 27 | } 28 | 29 | // $this->call(PermissionsSeeder::class); 30 | // $this->call(RolesSeeder::class); 31 | // $this->call(UsersSeeder::class); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Models/User.php: -------------------------------------------------------------------------------- 1 | 'datetime', 38 | ]; 39 | 40 | } -------------------------------------------------------------------------------- /resources/views/users/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('permission::layouts.app') 2 | 3 | @section('styles') 4 | 5 | 6 | 7 | @endsection 8 | @section('content') 9 | 10 | 11 | 12 | @endsection 13 | 14 | @section('scripts') 15 | 16 | 17 | 18 | 19 | 20 | 21 | @endsection -------------------------------------------------------------------------------- /resources/assets/dashboard/js/admin.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - SB Admin 2 v4.0.6 (https://startbootstrap.com/template-overviews/sb-admin-2) 3 | * Copyright 2013-2019 Start Bootstrap 4 | * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap-sb-admin-2/blob/master/LICENSE) 5 | */ 6 | 7 | !function(t){"use strict";t("#sidebarToggle, #sidebarToggleTop").on("click",function(o){t("body").toggleClass("sidebar-toggled"),t(".sidebar").toggleClass("toggled"),t(".sidebar").hasClass("toggled")&&t(".sidebar .collapse").collapse("hide")}),t(window).resize(function(){t(window).width()<768&&t(".sidebar .collapse").collapse("hide")}),t("body.fixed-nav .sidebar").on("mousewheel DOMMouseScroll wheel",function(o){if(768 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | @role('admin') 16 | 21 | 26 | @endrole 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "npm run development -- --watch", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "axios": "^0.19", 14 | "bootstrap": "^4.1.0", 15 | "cross-env": "^5.1", 16 | "jquery": "^3.2", 17 | "laravel-mix": "^4.0.7", 18 | "lodash": "^4.17.13", 19 | "popper.js": "^1.12", 20 | "resolve-url-loader": "^2.3.1", 21 | "sass": "^1.15.2", 22 | "sass-loader": "^7.1.0", 23 | "vue": "^2.5.17", 24 | "vue-template-compiler": "^2.6.10" 25 | }, 26 | "dependencies": { 27 | "sweetalert2": "^8.16.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resources/assets/js/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * First we will load all of this project's JavaScript dependencies which 3 | * includes Vue and other libraries. It is a great starting point when 4 | * building robust, powerful web applications using Vue and Laravel. 5 | */ 6 | require('./bootstrap'); 7 | window.Swal = require('sweetalert2'); 8 | 9 | window.Vue = require('vue'); 10 | 11 | /** 12 | * The following block of code may be used to automatically register your 13 | * Vue components. It will recursively scan this directory for the Vue 14 | * components and automatically register them with their "basename". 15 | * 16 | * Eg. ./components/ExampleComponent.vue -> 17 | */ 18 | 19 | // const files = require.context('./', true, /\.vue$/i); 20 | // files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default)); 21 | 22 | Vue.component('example-component', require('./components/ExampleComponent.vue').default); 23 | Vue.component('users-table', require('./components/Users.vue').default); 24 | 25 | /** 26 | * Next, we will create a fresh Vue application instance and attach it to 27 | * the page. Then, you may begin adding components to this application 28 | * or customize the JavaScript scaffolding to fit your unique needs. 29 | */ 30 | 31 | const app = new Vue({ 32 | el: '#wrapper', 33 | }); -------------------------------------------------------------------------------- /src/Traits/HasRoles.php: -------------------------------------------------------------------------------- 1 | roles as $role) { 15 | if ($role->slug == $permission) { 16 | return true; 17 | } 18 | } 19 | 20 | return false; 21 | } 22 | 23 | public function assignRoles( $roles, $separators = ',.|' ) { 24 | if( is_string( $roles ) ) { 25 | $pattern = '/['.$separators.']/'; 26 | $roles = str_spliter($roles, $pattern); 27 | } 28 | 29 | foreach ($roles as $role) { 30 | $this->roles()->attach( 31 | $this->getRole($role), 32 | [ 33 | 'created_at'=>now(), 34 | 'updated_at'=>now() 35 | ]); 36 | } 37 | } 38 | 39 | public function syncRoles( array $ids ) 40 | { 41 | return $this->roles()->sync($ids); 42 | } 43 | 44 | public function revokeRoles( array $ids = [] ) 45 | { 46 | if( empty( $ids ) ) { 47 | return $this->roles()->detach(); 48 | } 49 | return $this->roles()->detach($ids); 50 | } 51 | } -------------------------------------------------------------------------------- /database/seeds/RolesSeeder.php: -------------------------------------------------------------------------------- 1 | 'Super Admin', 20 | 'slug' => 'admin', 21 | 'created_at' => now(), 22 | 'updated_at' => now(), 23 | ]); 24 | $admin->assignPermissions([ 25 | 'browse', 26 | 'read', 27 | 'edit', 28 | 'add', 29 | 'delete' 30 | ]); 31 | 32 | $manager = Role::create([ 33 | 34 | 'name' => 'Manager', 35 | 'slug' => 'manager', 36 | 'created_at' => now(), 37 | 'updated_at' => now(), 38 | ])->assignPermissions([ 39 | 'browse', 40 | 'read', 41 | 'edit', 42 | 'add', 43 | ]); 44 | 45 | $user = Role::create([ 46 | 47 | 'name' => 'User', 48 | 'slug' => 'user', 49 | 'created_at' => now(), 50 | 'updated_at' => now(), 51 | ])->assignPermissions([ 52 | 'browse', 53 | 'read', 54 | ]); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /resources/assets/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | 3 | /** 4 | * We'll load jQuery and the Bootstrap jQuery plugin which provides support 5 | * for JavaScript based Bootstrap features such as modals and tabs. This 6 | * code may be modified to fit the specific needs of your application. 7 | */ 8 | 9 | try { 10 | window.Popper = require('popper.js').default; 11 | window.$ = window.jQuery = require('jquery') 12 | require('bootstrap'); 13 | } catch (e) {} 14 | 15 | /** 16 | * We'll load the axios HTTP library which allows us to easily issue requests 17 | * to our Laravel back-end. This library automatically handles sending the 18 | * CSRF token as a header based on the value of the "XSRF" token cookie. 19 | */ 20 | 21 | window.axios = require('axios'); 22 | 23 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 24 | 25 | /** 26 | * Echo exposes an expressive API for subscribing to channels and listening 27 | * for events that are broadcast by Laravel. Echo and event broadcasting 28 | * allows your team to easily build robust real-time web applications. 29 | */ 30 | 31 | // import Echo from 'laravel-echo'; 32 | 33 | // window.Pusher = require('pusher-js'); 34 | 35 | // window.Echo = new Echo({ 36 | // broadcaster: 'pusher', 37 | // key: process.env.MIX_PUSHER_APP_KEY, 38 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER, 39 | // encrypted: true 40 | // }); 41 | -------------------------------------------------------------------------------- /database/seeds/PermissionsSeeder.php: -------------------------------------------------------------------------------- 1 | 'Browse', 18 | 'slug' => slug('browse'), 19 | 'created_at' => now(), 20 | 'updated_at' => now(), 21 | ]); 22 | 23 | Permission::create([ 24 | 25 | 'name' => 'Read', 26 | 'slug' => slug('read'), 27 | 'created_at' => now(), 28 | 'updated_at' => now(), 29 | ]); 30 | 31 | Permission::create([ 32 | 33 | 'name' => 'Edit', 34 | 'slug' => slug('edit'), 35 | 'created_at' => now(), 36 | 'updated_at' => now(), 37 | ]); 38 | 39 | Permission::create([ 40 | 41 | 'name' => 'Add', 42 | 'slug' => slug('add'), 43 | 'created_at' => now(), 44 | 'updated_at' => now(), 45 | ]); 46 | 47 | Permission::create([ 48 | 49 | 'name' => 'Delete', 50 | 'slug' => slug('delete'), 51 | 'created_at' => now(), 52 | 'updated_at' => now(), 53 | ]); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /routes/demo.php: -------------------------------------------------------------------------------- 1 | /* Demo Routes */ 2 | Route::group(['namespace' => config('permission.controller_namespace')],function(){ 3 | // Permissions 4 | Route::get('/permissions', 'PermissionController@index')->name('permissions.index'); 5 | 6 | // Users 7 | Route::get('/users', 'UserController@index')->name('users'); 8 | // Vue CRUD 9 | Route::get('/users/all', 'UserController@all')->name('users.all'); 10 | Route::get('/user/{id}', 'UserController@getUser')->name('user'); 11 | Route::post('/user/add', 'UserController@addUser')->name('user.add'); 12 | Route::put('/user/', 'UserController@updateUser')->name('user.update'); 13 | Route::delete('/user/{id}', 'UserController@deleteUser')->name('user.delete'); 14 | // Ajax 15 | Route::get('/roles/all', 'UserController@allRoles')->name('roles.all'); 16 | Route::post('/role/add', 'PermissionController@addRole')->name('role.add'); 17 | Route::get('/role/{id}', 'PermissionController@getRole')->name('role.get'); 18 | Route::put('/role', 'PermissionController@updateRole')->name('role.edit'); 19 | Route::delete('/role', 'PermissionController@deleteRole')->name('role.delete'); 20 | 21 | // Permission 22 | Route::post('/permission/add', 'PermissionController@addPermission')->name('permission.add'); 23 | Route::get('/permission/{id}', 'PermissionController@getPermission')->name('permission.get'); 24 | Route::put('/permission', 'PermissionController@updatePermission')->name('permission.edit'); 25 | Route::delete('/permission', 'PermissionController@deletePermission')->name('permission.delete'); 26 | }); -------------------------------------------------------------------------------- /src/Http/Middleware/RoleMiddleware.php: -------------------------------------------------------------------------------- 1 | hasRole($role)) { 46 | return $next($request); 47 | } 48 | } 49 | 50 | return abort(404); 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /src/Commands/InstallPermissionDemo.php: -------------------------------------------------------------------------------- 1 | info('Adding Demo Routes and resources'); 38 | $demo_routes = $this->routesPath.'demo.php'; 39 | $original_routes = $this->routesPath.'permission.php'; 40 | if( file_exists($original_routes) && file_exists( $demo_routes ) ) { 41 | $original_contents = $filesystem->get($original_routes); 42 | $demo_contents = $filesystem->get($demo_routes); 43 | if (false === strpos($original_contents, '/* Demo Routes */')) { 44 | $filesystem->append( 45 | $original_routes, 46 | "\n\n".$demo_contents."\n" 47 | ); 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /resources/views/layouts/master.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Permission 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | @yield('styles') 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 |
41 | 42 | 43 | 44 | @include('permission::layouts.partials.topbar') 45 | 46 | 47 | 48 | 49 | @yield('content') 50 | 51 | 52 | 53 |
54 | 55 | 56 | @include('permission::layouts.partials.footer') -------------------------------------------------------------------------------- /resources/views/layouts/app.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Permission 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | @yield('styles') 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | 34 | @include('permission::layouts.partials.sidebar') 35 | 36 | 37 | 38 |
39 | 40 | 41 |
42 | 43 | 44 | 45 | @include('permission::layouts.partials.topbar') 46 | 47 | 48 | 49 | 50 | @yield('content') 51 | 52 | 53 | 54 |
55 | 56 | 57 | @include('permission::layouts.partials.footer') -------------------------------------------------------------------------------- /resources/assets/dashboard/vendor/datatables/dataTables.bootstrap4.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | DataTables Bootstrap 4 integration 3 | ©2011-2017 SpryMedia Ltd - datatables.net/license 4 | */ 5 | (function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,d){a||(a=window);if(!d||!d.fn.dataTable)d=require("datatables.net")(a,d).$;return b(d,a,a.document)}:b(jQuery,window,document)})(function(b,a,d,m){var f=b.fn.dataTable;b.extend(!0,f.defaults,{dom:"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>", 6 | renderer:"bootstrap"});b.extend(f.ext.classes,{sWrapper:"dataTables_wrapper dt-bootstrap4",sFilterInput:"form-control form-control-sm",sLengthSelect:"custom-select custom-select-sm form-control form-control-sm",sProcessing:"dataTables_processing card",sPageButton:"paginate_button page-item"});f.ext.renderer.pageButton.bootstrap=function(a,h,r,s,j,n){var o=new f.Api(a),t=a.oClasses,k=a.oLanguage.oPaginate,u=a.oLanguage.oAria.paginate||{},e,g,p=0,q=function(d,f){var l,h,i,c,m=function(a){a.preventDefault(); 7 | !b(a.currentTarget).hasClass("disabled")&&o.page()!=a.data.action&&o.page(a.data.action).draw("page")};l=0;for(h=f.length;l", 8 | {"class":t.sPageButton+" "+g,id:0===r&&"string"===typeof c?a.sTableId+"_"+c:null}).append(b("",{href:"#","aria-controls":a.sTableId,"aria-label":u[c],"data-dt-idx":p,tabindex:a.iTabIndex,"class":"page-link"}).html(e)).appendTo(d),a.oApi._fnBindAction(i,{action:c},m),p++)}},i;try{i=b(h).find(d.activeElement).data("dt-idx")}catch(v){}q(b(h).empty().html('
    ').children("ul"),s);i!==m&&b(h).find("[data-dt-idx="+i+"]").focus()};return f}); 9 | -------------------------------------------------------------------------------- /resources/assets/js/components/NestedDraggableMenu.vue: -------------------------------------------------------------------------------- 1 | 11 | 28 | 77 | -------------------------------------------------------------------------------- /resources/views/layouts/partials/footer.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | 7 |
    8 |
    9 | 10 | 11 |
12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 60 | 61 | @yield('scripts') 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /resources/assets/dashboard/vendor/jquery-easing/jquery.easing.min.js: -------------------------------------------------------------------------------- 1 | (function(factory){if(typeof define==="function"&&define.amd){define(["jquery"],function($){return factory($)})}else if(typeof module==="object"&&typeof module.exports==="object"){exports=factory(require("jquery"))}else{factory(jQuery)}})(function($){$.easing.jswing=$.easing.swing;var pow=Math.pow,sqrt=Math.sqrt,sin=Math.sin,cos=Math.cos,PI=Math.PI,c1=1.70158,c2=c1*1.525,c3=c1+1,c4=2*PI/3,c5=2*PI/4.5;function bounceOut(x){var n1=7.5625,d1=2.75;if(x<1/d1){return n1*x*x}else if(x<2/d1){return n1*(x-=1.5/d1)*x+.75}else if(x<2.5/d1){return n1*(x-=2.25/d1)*x+.9375}else{return n1*(x-=2.625/d1)*x+.984375}}$.extend($.easing,{def:"easeOutQuad",swing:function(x){return $.easing[$.easing.def](x)},easeInQuad:function(x){return x*x},easeOutQuad:function(x){return 1-(1-x)*(1-x)},easeInOutQuad:function(x){return x<.5?2*x*x:1-pow(-2*x+2,2)/2},easeInCubic:function(x){return x*x*x},easeOutCubic:function(x){return 1-pow(1-x,3)},easeInOutCubic:function(x){return x<.5?4*x*x*x:1-pow(-2*x+2,3)/2},easeInQuart:function(x){return x*x*x*x},easeOutQuart:function(x){return 1-pow(1-x,4)},easeInOutQuart:function(x){return x<.5?8*x*x*x*x:1-pow(-2*x+2,4)/2},easeInQuint:function(x){return x*x*x*x*x},easeOutQuint:function(x){return 1-pow(1-x,5)},easeInOutQuint:function(x){return x<.5?16*x*x*x*x*x:1-pow(-2*x+2,5)/2},easeInSine:function(x){return 1-cos(x*PI/2)},easeOutSine:function(x){return sin(x*PI/2)},easeInOutSine:function(x){return-(cos(PI*x)-1)/2},easeInExpo:function(x){return x===0?0:pow(2,10*x-10)},easeOutExpo:function(x){return x===1?1:1-pow(2,-10*x)},easeInOutExpo:function(x){return x===0?0:x===1?1:x<.5?pow(2,20*x-10)/2:(2-pow(2,-20*x+10))/2},easeInCirc:function(x){return 1-sqrt(1-pow(x,2))},easeOutCirc:function(x){return sqrt(1-pow(x-1,2))},easeInOutCirc:function(x){return x<.5?(1-sqrt(1-pow(2*x,2)))/2:(sqrt(1-pow(-2*x+2,2))+1)/2},easeInElastic:function(x){return x===0?0:x===1?1:-pow(2,10*x-10)*sin((x*10-10.75)*c4)},easeOutElastic:function(x){return x===0?0:x===1?1:pow(2,-10*x)*sin((x*10-.75)*c4)+1},easeInOutElastic:function(x){return x===0?0:x===1?1:x<.5?-(pow(2,20*x-10)*sin((20*x-11.125)*c5))/2:pow(2,-20*x+10)*sin((20*x-11.125)*c5)/2+1},easeInBack:function(x){return c3*x*x*x-c1*x*x},easeOutBack:function(x){return 1+c3*pow(x-1,3)+c1*pow(x-1,2)},easeInOutBack:function(x){return x<.5?pow(2*x,2)*((c2+1)*2*x-c2)/2:(pow(2*x-2,2)*((c2+1)*(x*2-2)+c2)+2)/2},easeInBounce:function(x){return 1-bounceOut(1-x)},easeOutBounce:bounceOut,easeInOutBounce:function(x){return x<.5?(1-bounceOut(1-2*x))/2:(1+bounceOut(2*x-1))/2}})}); -------------------------------------------------------------------------------- /src/Traits/HasPermissions.php: -------------------------------------------------------------------------------- 1 | belongsToMany(Role::class,'role_users','user_id','role_id'); 14 | } 15 | 16 | public function givePermissionToRoles( array $roles ) 17 | { 18 | foreach ($roles as $role) { 19 | $role = $this->getRole( $role ); 20 | if( $role ) { 21 | $this->permission_roles()->attach([ 22 | $role->id => [ 23 | 'created_at'=>now(), 24 | 'updated_at'=>now() 25 | ], 26 | ]); 27 | } 28 | } 29 | } 30 | 31 | public function syncPermissionToRoles( array $ids ) 32 | { 33 | return $this->permission_roles()->sync($ids); 34 | } 35 | 36 | public function revokePermissionsFromRoles( array $ids = [] ) 37 | { 38 | if( empty( $ids ) ) { 39 | return $this->permission_roles()->detach(); 40 | } 41 | return $this->permission_roles()->detach($ids); 42 | } 43 | 44 | public function assignPermissions( array $breads ) { 45 | foreach ($breads as $bread) { 46 | $permission = $this->getPermission($bread); 47 | if( $permission ) { 48 | $this->permissions()->attach([ 49 | $permission->id => [ 50 | 'created_at'=>now(), 51 | 'updated_at'=>now() 52 | ], 53 | ]); 54 | } 55 | } 56 | } 57 | 58 | public function updatePermissions( array $ids ) 59 | { 60 | return $this->permissions()->sync($ids); 61 | } 62 | 63 | public function syncPermissions( array $ids ) 64 | { 65 | return $this->permissions()->sync($ids); 66 | } 67 | 68 | public function revokePermissions( array $ids = [] ) 69 | { 70 | if( empty( $ids ) ) { 71 | return $this->permissions()->detach(); 72 | } 73 | return $this->permissions()->detach($ids); 74 | } 75 | 76 | public function hasPermission($privilege) 77 | { 78 | foreach( $this->roles as $role ) { 79 | foreach ( $role->permissions as $permission ) { 80 | if ($permission->slug == $privilege) { 81 | return true; 82 | } 83 | } 84 | } 85 | 86 | return false; 87 | } 88 | 89 | protected function getPermission( $permission ){ 90 | if( is_numeric( $permission ) ) { 91 | return Permission::find( (int)$permission ); 92 | }elseif( is_string( $permission ) ){ 93 | return Permission::where('slug', $permission)->first(); 94 | } 95 | 96 | return false; 97 | } 98 | 99 | public function getRole( $role ) { 100 | if( is_numeric($role) ) { 101 | return Role::find( (int)$role ); 102 | }elseif( is_string( $role ) ) { 103 | return Role::where('slug', slug($role))->first(); 104 | 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /src/Commands/InstallPermission.php: -------------------------------------------------------------------------------- 1 | handle($filesystem); 50 | // } 51 | /** 52 | * Execute the console command. 53 | * 54 | * @param \Illuminate\Filesystem\Filesystem $filesystem 55 | * 56 | * @return void 57 | */ 58 | public function handle( Filesystem $filesystem) 59 | { 60 | $this->info('Publishing the Voyager assets, database, and config files'); 61 | // Publish only relevant resources on install 62 | $tags = ['permission.seeds','permission.config']; 63 | $this->call('vendor:publish', ['--provider' => PermissionServiceProvider::class, '--tag' => $tags]); 64 | 65 | $this->info('Migrating the database tables into your application'); 66 | $this->call('migrate', ['--force' => $this->option('force')]); 67 | 68 | // $this->info('Attempting to set Permission User model as parent to App\User'); 69 | // if (file_exists(app_path('User.php'))) { 70 | // $str = file_get_contents(app_path('User.php')); 71 | // if ($str !== false) { 72 | // $str = str_replace('extends Authenticatable', "extends \CodexShaper\Permission\Models\User", $str); 73 | // file_put_contents(app_path('User.php'), $str); 74 | // } 75 | // } else { 76 | // $this->warn('Unable to locate "app/User.php". Did you move this file?'); 77 | // $this->warn('You will need to update this manually. "use HasRoles" in your User model'); 78 | // } 79 | 80 | $this->info('Dumping the autoloaded files and reloading all new files'); 81 | $composer = $this->findComposer(); 82 | $process = Process::fromShellCommandline($composer.' dump-autoload'); 83 | $process->setTimeout(null); // Setting timeout to null to prevent installation from stopping at a certain point in time 84 | $process->setWorkingDirectory(base_path())->run(); 85 | 86 | // Load Permission routes into application's 'routes/web.php' 87 | 88 | $this->info('Adding Permission routes to routes/web.php'); 89 | $routes_contents = $filesystem->get(base_path('routes/web.php')); 90 | if (false === strpos($routes_contents, 'Permission::routes()')) { 91 | $filesystem->append( 92 | base_path('routes/web.php'), 93 | "\n\nRoute::group(['prefix' => config('permission.prefix'),'middleware'=>['role:admin']], function () {\n Permission::routes();\n});\n" 94 | ); 95 | } 96 | 97 | // Seeding Dummy Data 98 | 99 | $this->info('Seeding data into the database'); 100 | 101 | $class = 'PermissionDatabaseSeeder'; 102 | $file = $this->seedersPath.$class.'.php'; 103 | 104 | if ( file_exists( $file ) && !class_exists($class)) { 105 | require_once $file; 106 | } 107 | with(new $class())->run(); 108 | 109 | $this->info('Seeding Completed'); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /resources/assets/dashboard/vendor/datatables/dataTables.bootstrap4.min.css: -------------------------------------------------------------------------------- 1 | table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important;border-spacing:0}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:auto;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:0.85em;white-space:nowrap}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap;justify-content:flex-end}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:before,table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:before,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:before,table.dataTable thead .sorting_desc_disabled:after{position:absolute;bottom:0.9em;display:block;opacity:0.3}table.dataTable thead .sorting:before,table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_desc:before,table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_desc_disabled:before{right:1em;content:"\2191"}table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{right:0.5em;content:"\2193"}table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_desc:after{opacity:1}table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_desc_disabled:after{opacity:0}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody table thead .sorting:before,div.dataTables_scrollBody table thead .sorting_asc:before,div.dataTables_scrollBody table thead .sorting_desc:before,div.dataTables_scrollBody table thead .sorting:after,div.dataTables_scrollBody table thead .sorting_asc:after,div.dataTables_scrollBody table thead .sorting_desc:after{display:none}div.dataTables_scrollBody table tbody tr:first-child th,div.dataTables_scrollBody table tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot>.dataTables_scrollFootInner{box-sizing:content-box}div.dataTables_scrollFoot>.dataTables_scrollFootInner>table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}}table.dataTable.table-sm>thead>tr>th{padding-right:20px}table.dataTable.table-sm .sorting:before,table.dataTable.table-sm .sorting_asc:before,table.dataTable.table-sm .sorting_desc:before{top:5px;right:0.85em}table.dataTable.table-sm .sorting:after,table.dataTable.table-sm .sorting_asc:after,table.dataTable.table-sm .sorting_desc:after{top:5px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:0}table.table-bordered.dataTable tbody th,table.table-bordered.dataTable tbody td{border-bottom-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:last-child{padding-right:0} 2 | -------------------------------------------------------------------------------- /src/PermissionServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadMigrationsFrom(__DIR__.'/../database/migrations'); 26 | // $this->loadViewsFrom(__DIR__.'/../resources/views', 'permission'); 27 | $viewConfigPath = config('permission.views'); 28 | 29 | if( $viewConfigPath != false && is_dir( $viewConfigPath ) ) { 30 | $viewsPath = $viewConfigPath; 31 | }elseif( $viewConfigPath != false && is_dir(base_path($viewConfigPath)) ) { 32 | $viewsPath = base_path($viewConfigPath); 33 | }else { 34 | $viewsPath = __DIR__.'/../resources/views'; 35 | } 36 | $this->loadViewsFrom( $viewsPath, 'permission'); 37 | // $this->loadViewsFrom(config('permission.views'), 'permission'); 38 | } 39 | 40 | /** 41 | * Register the service provider. 42 | * 43 | * @return void 44 | */ 45 | public function register() 46 | { 47 | 48 | $this->app->singleton('permission', function(){ 49 | return new Permission(); 50 | }); 51 | 52 | $this->loadHelpers(); 53 | 54 | $this->mergeConfigFrom( 55 | __DIR__.'/../config/permission.php', 'config' 56 | ); 57 | 58 | $this->registerMiddleware(); 59 | $this->registerPublish(); 60 | $this->registerBladeDirectives(); 61 | $this->registerCommands(); 62 | } 63 | 64 | protected function loadHelpers() 65 | { 66 | foreach (glob(__DIR__.'/Helpers/*.php') as $filename) { 67 | require_once $filename; 68 | } 69 | } 70 | 71 | protected function registerMiddleware() 72 | { 73 | /** @var Kernel|\Illuminate\Foundation\Http\Kernel $kernel */ 74 | $this->app['router']->aliasMiddleware('role', RoleMiddleware::class); 75 | } 76 | 77 | protected function registerPublish() 78 | { 79 | $publishable = [ 80 | 'permission.config' => [ 81 | __DIR__.'/../config/permission.php' => config_path('permission.php'), 82 | ], 83 | 'permission.seeds' => [ 84 | __DIR__."/../database/seeds/" => database_path('seeders'), 85 | ], 86 | 'permission.views' => [ 87 | __DIR__.'/../resources/views' => resource_path('views/vendor/permissions/views'), 88 | ], 89 | 'permission.resources' => [ 90 | __DIR__.'/../resources' => resource_path('views/vendor/permissions'), 91 | ], 92 | ]; 93 | foreach ($publishable as $group => $paths) { 94 | $this->publishes($paths, $group); 95 | } 96 | } 97 | 98 | protected function registerBladeDirectives() { 99 | $this->app->afterResolving('blade.compiler', function( BladeCompiler $blade ){ 100 | $blade->directive('can', function ($permission) { 101 | return "user() && auth()->user()->hasPermission({$permission})): ?>"; 102 | }); 103 | $blade->directive('endcan', function ($expression) { 104 | return ""; 105 | }); 106 | 107 | $blade->directive('role', function ($role) { 108 | return "user() && auth()->user()->hasRole({$role})): ?>"; 109 | }); 110 | $blade->directive('endrole', function () { 111 | return ''; 112 | }); 113 | 114 | $blade->directive('hasrole', function ($arguments) { 115 | list($role, $guard) = explode(',', $arguments.','); 116 | dd( auth($guard) ); 117 | return "check() && auth({$guard})->user()->hasRole({$role})): ?>"; 118 | }); 119 | $blade->directive('endhasrole', function () { 120 | return ''; 121 | }); 122 | 123 | $blade->directive('haspermission', function ($permission) { 124 | return "user() && auth()->user()->hasPermission({$permission})): ?>"; 125 | }); 126 | $blade->directive('endhaspermission', function ($expression) { 127 | return ""; 128 | }); 129 | }); 130 | 131 | } 132 | 133 | private function registerCommands() 134 | { 135 | $this->commands(InstallPermission::class); 136 | $this->commands(InstallPermissionDemo::class); 137 | $this->commands(PublishPermissionResources::class); 138 | $this->commands(PublishPermissionViews::class); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laravel-permission 2 | Laravel Multi Authentication 3 | 4 | Installation video : [click here](https://www.youtube.com/watch?v=2ZmhpYwrGNA) or click below image 5 | 6 | [![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/2ZmhpYwrGNA/0.jpg)](https://www.youtube.com/watch?v=2ZmhpYwrGNA) 7 | 8 | ## Note : Before Install and use this package run below command 9 | Before Laravel version 6.0 10 | ``` 11 | php artisan make:auth 12 | ``` 13 | From Laravel Version 6.0 14 | 15 | ``` 16 | 1. composer require laravel/ui 17 | 2. php artisan ui vue --auth 18 | 3. npm install 19 | 4. npm run dev 20 | ``` 21 | 22 | #### Install the Package 23 | 24 | ``` 25 | composer require codexshaper/laravel-permission 26 | ``` 27 | ##### Publish Resource, Configs, Migration and Seeding Database in a single command 28 | 29 | ``` 30 | php artisan permission:install 31 | ``` 32 | ##### Or Publish Resource, Configs, Migration and Seeding Database Manually 33 | 1. Publish Configs 34 | ``` 35 | php artisan vendor:publish --tag=permission.config 36 | ``` 37 | 2. Publish Seeds 38 | ``` 39 | php artisan vendor:publish --tag=permission.seeds 40 | ``` 41 | 3. Migrate Database 42 | ``` 43 | php artisan migrate 44 | ``` 45 | 4. Run composer dump autoload 46 | ``` 47 | composer dump-autoload 48 | ``` 49 | 5. Seeding Database 50 | ``` 51 | php artisan db:seed --class=PermissionDatabaseSeeder 52 | ``` 53 | 6. Add Routes 54 | ``` 55 | Route::group(['prefix' => config('permission.prefix'),'middleware'=>['role:admin']], function () { 56 | Permission::routes(); 57 | }); 58 | ``` 59 | ##### Import `use CodexShaper\Permission\Traits\HasRoles` or simply `use HasRoles` Trait into your `App\User` Model 60 | ``` 61 | namespace App; 62 | 63 | use CodexShaper\Permission\Traits\HasRoles; 64 | 65 | class User extends Authenticatable 66 | { 67 | use HasRoles; 68 | } 69 | ``` 70 | ##### Check Permission go to ```/admin/laravel-permission``` 71 | 72 | ###### Install Demo 73 | ``` 74 | php artisan permission:install:demo 75 | ``` 76 | ##### Demo url ```/admin/permissions``` 77 | 78 | ###### Publish ```Views``` 79 | ``` 80 | php artisan permission:publish:views 81 | ``` 82 | 83 | ##### Publish ```Resources``` 84 | ``` 85 | php artisan permission:publish:resources 86 | ``` 87 | #### For Overriding Views and Resources, Change your config file ```/config/permission.php``` 88 | ``` 89 | 'resources_path' => 'resources/views/vendor/permissions/assets', 90 | 'views' => 'resources/views/vendor/permissions/views', 91 | ``` 92 | # Permission 93 | ``` 94 | use CodexShaper\Permission\Models\Permission; 95 | 96 | $permission = Permission::create([ 97 | 'name' => 'Browse', 98 | 'slug' => slug('browse'), 99 | 'created_at' => now(), 100 | 'updated_at' => now(), 101 | ]); 102 | ``` 103 | 104 | #### Give Permission to Roles 105 | ``` 106 | // Create Role before set permission 107 | // $roles = [role_slug_or_id] ex: ['admin',1,2,'author'] 108 | $permission->givePermissionToRoles( $roles ); 109 | ``` 110 | #### Update permission roles 111 | ``` 112 | $role_ids = [1,3,5] 113 | $permission->syncPermissionToRoles( $role_ids ); 114 | ``` 115 | #### Delete permission roles 116 | ``` 117 | // Delete specific Roles 118 | $role_ids = [1,3,5]; 119 | $permission->revokePermissionsFromRoles( $role_ids ); 120 | // Delete all roles for current permission 121 | $permission->revokePermissionsFromRoles(); 122 | ``` 123 | # Role 124 | ``` 125 | use CodexShaper\Permission\Models\Role; 126 | 127 | $admin = Role::create([ 128 | 'name' => 'Super Admin', 129 | 'slug' => 'admin', 130 | 'created_at' => now(), 131 | 'updated_at' => now(), 132 | ]); 133 | ``` 134 | #### Assign Permission 135 | ``` 136 | $admin->assignPermissions([ 137 | 'browse', 138 | 'read', 139 | 'edit', 140 | 'add', 141 | 'delete' 142 | ]); 143 | ``` 144 | #### Update Permission 145 | ``` 146 | $permission_ids = [1,3,5] 147 | $admin->syncPermissions( $permission_ids ); 148 | ``` 149 | #### Delete permission 150 | ``` 151 | // Delete specific Permissions 152 | $permission_ids = [1,3,5]; 153 | $admin->revokePermissions( $permission_ids ); 154 | // Delete all roles for current roles 155 | $admin->revokePermissions(); 156 | ``` 157 | #### Check Permission 158 | ``` 159 | $admin->hasPermission( $permission_slug ); 160 | ``` 161 | # User 162 | ``` 163 | use App\User; 164 | 165 | $user = new User; 166 | $user->name = 'John Doe'; 167 | $user->email = 'john@gmail.com'; 168 | $user->password = Hash::make('password'); 169 | $user->save(); 170 | $user->assignRoles('admin'); 171 | ``` 172 | #### Assign Roles into existing user 173 | ``` 174 | $user = User::find(1); 175 | $user->assignRoles('admin'); 176 | ``` 177 | #### Assign Multiple roles 178 | ``` 179 | $user = User::find(1); 180 | // Use pipe(|) 181 | $user->assignRoles('admin|client|customer'); 182 | // Or use comma(,) 183 | $user->assignRoles('admin,client,customer'); 184 | // Or use space 185 | $user->assignRoles('admin client customer'); 186 | // Or Mixed 187 | $user->assignRoles('admin client,customer|write'); 188 | // Pass custom separators 189 | $separators = ',.| '; 190 | $user->assignRoles('admin client,customer|write', $separators); 191 | ``` 192 | #### Update Roles 193 | ``` 194 | $role_ids = [1,2,3]; 195 | $user->syncRoles( $role_ids ); 196 | ``` 197 | #### Delete Roles 198 | ``` 199 | // Delete specific Roles for current User 200 | $role_ids = [1,3,5]; 201 | $user->revokeRoles( $role_ids ); 202 | // Delete all roles for current user 203 | $user->revokeRoles(); 204 | ``` 205 | #### Check Role 206 | ``` 207 | $user->hasRole( $role_slug ); 208 | ``` 209 | # Add Middleware on route 210 | ``` 211 | Route::group(['middleware'=>['role:admin']],function(){ 212 | // Routes 213 | }); 214 | ``` 215 | 216 | # View Directories 217 | ``` 218 | @can('browse') 219 |

You Can Browse

220 | @endcan 221 | 222 | @role('admin') 223 |

You are admin

224 | @endrole 225 | 226 | @hasrole('admin') 227 |

You have admin Permission

228 | @endhasrole 229 | 230 | @haspermission('edit') 231 |

You have admin Permission

232 | @endhaspermission 233 | ``` 234 | ## Authors 235 | 236 | * **Md Abu Ahsan Basir** - *Main Developer & Maintainer* - [github](https://github.com/maab16) 237 | * **Mahabubul Alam** - *Main designer* - [github](https://github.com/mahabubul1) 238 | 239 | See also the list of [contributors](https://github.com/laravel-menu-builder/contributors) who participated in this project. 240 | 241 | ## License 242 | 243 | [![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://badges.mit-license.org) 244 | 245 | - **[MIT license](http://opensource.org/licenses/mit-license.php)** 246 | - Copyright 2019 © CodexShaper. 247 | -------------------------------------------------------------------------------- /src/Http/Controllers/UserController.php: -------------------------------------------------------------------------------- 1 | first()->permissions); 16 | $roles = Role::orderBy('updated_at', 'desc')->get(); 17 | $users = User::orderBy('updated_at', 'desc')->get(); 18 | return view('permission::users.index', compact('roles', 'users')); 19 | } 20 | 21 | public function all( Request $request ) 22 | { 23 | $users = User::orderBy('updated_at', 'desc')->get(); 24 | return response()->json([ 25 | 'success' => true, 26 | 'users' => $users 27 | ]); 28 | } 29 | 30 | public function addUser( Request $request ) { 31 | $validator = Validator::make($request->all(), [ 32 | 'name' => ['required', 'string', 'max:255'], 33 | 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 34 | 'password' => ['required', 'string', 'min:8', 'confirmed'], 35 | ]); 36 | if( $validator->fails() ){ 37 | return response()->json([ 38 | 'success' => false, 39 | 'errors' => $validator->messages() 40 | ]); 41 | } 42 | 43 | $user = User::create([ 44 | 'name' => $request->name, 45 | 'email' => $request->email, 46 | 'password' => Hash::make($request->password), 47 | ]); 48 | 49 | if( $user ) { 50 | if( count( $request->checkedRoles ) > 0 ) { 51 | $user->assignRoles($request->checkedRoles); 52 | return response()->json([ 53 | 'success' => true, 54 | 'user' => $user 55 | ]); 56 | } 57 | } 58 | return response()->json([ 59 | 'success' => false, 60 | ]); 61 | } 62 | 63 | public function getUser( Request $request ) { 64 | if( $request->ajax() && isset($request->id) ) { 65 | $user = User::find( $request->id ); 66 | $userRoles = $user->roles; 67 | $checkedRoles = $user->roles->pluck('id'); 68 | return response()->json([ 69 | 'success' => true, 70 | 'user' => $user, 71 | 'userRoles' => $userRoles, 72 | 'checkedRoles' => $checkedRoles 73 | ]); 74 | } 75 | 76 | return response()->json([ 77 | 'success' => false 78 | ]); 79 | } 80 | 81 | public function allRoles() 82 | { 83 | return response()->json([ 84 | 'success' => true, 85 | 'roles' => Role::all() 86 | ]); 87 | } 88 | 89 | public function updateUser( Request $request ) 90 | { 91 | if( isset( $request->id ) && $user = User::find($request->id) ) { 92 | $validator = Validator::make($request->all(), [ 93 | 'name' => 'required|string|max:255', 94 | 'email' => 'required|string|email|max:255|unique:users,email,'.$request->id, 95 | ]); 96 | if( $validator->fails() ){ 97 | return response()->json([ 98 | 'success' => false, 99 | 'errors' => $validator->messages() 100 | ]); 101 | } 102 | 103 | $user->name = $request->name; 104 | $user->email = $request->email; 105 | $user->updated_at = now(); 106 | if( $user->update() ) { 107 | $user->syncRoles($request->checkedRoles); 108 | } 109 | return response()->json([ 110 | 'success' => true, 111 | 'user' => $request->all() 112 | ]); 113 | } 114 | return response()->json([ 115 | 'success' => false 116 | ]); 117 | } 118 | 119 | public function deleteUser( Request $request ) 120 | { 121 | if(isset($request->id) && $user = User::find($request->id)){ 122 | $user->revokeRoles(); 123 | if( $user->delete() ){ 124 | return response()->json([ 125 | 'success' => true 126 | ]); 127 | } 128 | } 129 | 130 | return response()->json([ 131 | 'success' => false, 132 | ]); 133 | } 134 | 135 | public function addRole(Request $request) 136 | { 137 | if( $request->ajax() ) { 138 | if( !Role::where('slug', slug($request->role_name))->exists() ){ 139 | 140 | $role = new Role; 141 | $role->name = $request->role_name; 142 | $role->slug = slug($request->role_name); 143 | if($role->save()){ 144 | if( count( $request->permissions ) > 0 ) { 145 | $role->assignPermissions( $request->permissions ); 146 | return response()->json([ 147 | 'success' => true, 148 | 'role' => $role 149 | ]); 150 | } 151 | } 152 | }else { 153 | return response()->json([ 154 | 'success' => false, 155 | 'message' => 'Role Already Exists' 156 | ]); 157 | } 158 | } 159 | 160 | return response()->json(['success' => false]); 161 | } 162 | 163 | public function getRole( Request $request ) 164 | { 165 | if( $request->ajax() ) { 166 | if( $request->id ) { 167 | if( $role = Role::find( $request->id ) ){ 168 | $permissions = $role->permissions; 169 | return response()->json([ 170 | 'success' => true, 171 | 'role' => $role, 172 | 'permissions' => $permissions 173 | ]); 174 | } 175 | } 176 | } 177 | 178 | return response()->json([ 179 | 'success' => false, 180 | 'message' => 'There is no ajax request' 181 | ]); 182 | } 183 | 184 | public function updateRole( Request $request ) 185 | { 186 | if($request->ajax()){ 187 | if( isset( $request->role_id ) && $role = Role::find( $request->role_id ) ) { 188 | $role->name = $request->role_name; 189 | $role->slug = slug( $request->role_name ); 190 | if( $role->update() ) { 191 | if( count( $request->permissions ) > 0 ) { 192 | $role->updatePermissions( $request->permissions ); 193 | return response()->json([ 194 | 'success' => true, 195 | 'role' => $role 196 | ]); 197 | } 198 | } 199 | } 200 | } 201 | 202 | return response()->json([ 203 | 'success' => false, 204 | 'data' => $request->all() 205 | ]); 206 | } 207 | 208 | public function deleteRole( Request $request ) 209 | { 210 | if($request->ajax()){ 211 | if( isset( $request->role_id ) && $role = Role::find( $request->role_id ) ) { 212 | $role->revokePermissions(); 213 | if( $role->delete() ) { 214 | return response()->json([ 215 | 'success' => true, 216 | 'role' => $role 217 | ]); 218 | } 219 | } 220 | } 221 | 222 | return response()->json([ 223 | 'success' => false, 224 | 'data' => $request->all() 225 | ]); 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /src/Http/Controllers/PermissionController.php: -------------------------------------------------------------------------------- 1 | first()->permissions); 20 | $roles = Role::orderBy('updated_at', 'desc')->get(); 21 | $permissions = Permission::orderBy('updated_at', 'desc')->get(); 22 | return view('permission::permissions.index', compact('roles', 'permissions')); 23 | } 24 | 25 | public function addPermission(Request $request) 26 | { 27 | if( $request->ajax() ) { 28 | if( !Permission::where('slug', slug($request->permission_name))->exists() ){ 29 | 30 | $permission = new Permission; 31 | $permission->name = $request->permission_name; 32 | $permission->slug = slug($request->permission_name); 33 | if($permission->save()){ 34 | $permission->givePermissionToRoles( $request->roles ); 35 | return response()->json([ 36 | 'success' => true, 37 | 'permission' => $permission, 38 | 'roles' => $permission->permission_roles 39 | ]); 40 | } 41 | }else { 42 | return response()->json([ 43 | 'success' => false, 44 | 'message' => 'Permission Already Exists' 45 | ]); 46 | } 47 | } 48 | 49 | return response()->json(['success' => false]); 50 | } 51 | 52 | public function getPermission( Request $request ) 53 | { 54 | if( $request->ajax() ) { 55 | if( $request->id ) { 56 | if( $permission = Permission::find( $request->id ) ){ 57 | $roles = $permission->permission_roles; 58 | return response()->json([ 59 | 'success' => true, 60 | 'permission' => $permission, 61 | 'roles' => $roles 62 | ]); 63 | } 64 | } 65 | } 66 | 67 | return response()->json([ 68 | 'success' => false, 69 | 'message' => 'There is no ajax request' 70 | ]); 71 | } 72 | 73 | public function updatePermission( Request $request ) 74 | { 75 | if($request->ajax()){ 76 | if( isset( $request->permission_id ) && $permission = Permission::find( $request->permission_id ) ) { 77 | $permission->name = $request->permission_name; 78 | $permission->slug = slug( $request->permission_name ); 79 | if( $permission->update() ) { 80 | if( count( $request->roles ) > 0 ) { 81 | $permission->syncPermissionToRoles( $request->roles ); 82 | return response()->json([ 83 | 'success' => true, 84 | 'permission' => $permission 85 | ]); 86 | } 87 | } 88 | } 89 | } 90 | 91 | return response()->json([ 92 | 'success' => false, 93 | 'data' => $request->all() 94 | ]); 95 | } 96 | 97 | public function deletePermission( Request $request ) 98 | { 99 | if($request->ajax()){ 100 | if( isset( $request->permission_id ) && $permission = Permission::find( $request->permission_id ) ) { 101 | $permission->revokePermissionsFromRoles(); 102 | if( $permission->delete() ) { 103 | return response()->json([ 104 | 'success' => true, 105 | 'permission' => $permission 106 | ]); 107 | } 108 | } 109 | } 110 | 111 | return response()->json([ 112 | 'success' => false, 113 | 'data' => $request->all() 114 | ]); 115 | } 116 | 117 | public function addRole(Request $request) 118 | { 119 | if( $request->ajax() ) { 120 | if( !Role::where('slug', slug($request->role_name))->exists() ){ 121 | 122 | $role = new Role; 123 | $role->name = $request->role_name; 124 | $role->slug = slug($request->role_name); 125 | if($role->save()){ 126 | if( count( $request->permissions ) > 0 ) { 127 | $role->assignPermissions( $request->permissions ); 128 | return response()->json([ 129 | 'success' => true, 130 | 'role' => $role 131 | ]); 132 | } 133 | } 134 | }else { 135 | return response()->json([ 136 | 'success' => false, 137 | 'message' => 'Role Already Exists' 138 | ]); 139 | } 140 | } 141 | 142 | return response()->json(['success' => false]); 143 | } 144 | 145 | public function getRole( Request $request ) 146 | { 147 | if( $request->ajax() ) { 148 | if( $request->id ) { 149 | if( $role = Role::find( $request->id ) ){ 150 | $permissions = $role->permissions; 151 | return response()->json([ 152 | 'success' => true, 153 | 'role' => $role, 154 | 'permissions' => $permissions 155 | ]); 156 | } 157 | } 158 | } 159 | 160 | return response()->json([ 161 | 'success' => false, 162 | 'message' => 'There is no ajax request' 163 | ]); 164 | } 165 | 166 | public function updateRole( Request $request ) 167 | { 168 | if($request->ajax()){ 169 | if( isset( $request->role_id ) && $role = Role::find( $request->role_id ) ) { 170 | $role->name = $request->role_name; 171 | $role->slug = slug( $request->role_name ); 172 | if( $role->update() ) { 173 | if( count( $request->permissions ) > 0 ) { 174 | $role->updatePermissions( $request->permissions ); 175 | return response()->json([ 176 | 'success' => true, 177 | 'role' => $role 178 | ]); 179 | } 180 | } 181 | } 182 | } 183 | 184 | return response()->json([ 185 | 'success' => false, 186 | 'data' => $request->all() 187 | ]); 188 | } 189 | 190 | public function deleteRole( Request $request ) 191 | { 192 | if($request->ajax()){ 193 | if( isset( $request->role_id ) && $role = Role::find( $request->role_id ) ) { 194 | $role->revokePermissions(); 195 | if( $role->delete() ) { 196 | return response()->json([ 197 | 'success' => true, 198 | 'role' => $role 199 | ]); 200 | } 201 | } 202 | } 203 | 204 | return response()->json([ 205 | 'success' => false, 206 | 'data' => $request->all() 207 | ]); 208 | } 209 | 210 | public function assets(Request $request) 211 | { 212 | $file = base_path(trim(config('permission.resources_path'), '/')."/".urldecode($request->path)); 213 | 214 | if (File::exists($file)) { 215 | 216 | switch ( $extension = pathinfo($file, PATHINFO_EXTENSION) ) { 217 | case 'js': 218 | $mimeType = 'text/javascript'; 219 | break; 220 | case 'css': 221 | $mimeType = 'text/css'; 222 | break; 223 | default: 224 | $mimeType = File::mimeType($file); 225 | break; 226 | } 227 | 228 | $response = Response::make(File::get($file), 200); 229 | $response->header('Content-Type', $mimeType); 230 | $response->setSharedMaxAge(31536000); 231 | $response->setMaxAge(31536000); 232 | $response->setExpires(new \DateTime('+1 year')); 233 | 234 | return $response; 235 | } 236 | 237 | return response('', 404); 238 | } 239 | } -------------------------------------------------------------------------------- /resources/assets/lang/en/validation.php: -------------------------------------------------------------------------------- 1 | 'The :attribute must be accepted.', 17 | 'active_url' => 'The :attribute is not a valid URL.', 18 | 'after' => 'The :attribute must be a date after :date.', 19 | 'after_or_equal' => 'The :attribute must be a date after or equal to :date.', 20 | 'alpha' => 'The :attribute may only contain letters.', 21 | 'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.', 22 | 'alpha_num' => 'The :attribute may only contain letters and numbers.', 23 | 'array' => 'The :attribute must be an array.', 24 | 'before' => 'The :attribute must be a date before :date.', 25 | 'before_or_equal' => 'The :attribute must be a date before or equal to :date.', 26 | 'between' => [ 27 | 'numeric' => 'The :attribute must be between :min and :max.', 28 | 'file' => 'The :attribute must be between :min and :max kilobytes.', 29 | 'string' => 'The :attribute must be between :min and :max characters.', 30 | 'array' => 'The :attribute must have between :min and :max items.', 31 | ], 32 | 'boolean' => 'The :attribute field must be true or false.', 33 | 'confirmed' => 'The :attribute confirmation does not match.', 34 | 'date' => 'The :attribute is not a valid date.', 35 | 'date_equals' => 'The :attribute must be a date equal to :date.', 36 | 'date_format' => 'The :attribute does not match the format :format.', 37 | 'different' => 'The :attribute and :other must be different.', 38 | 'digits' => 'The :attribute must be :digits digits.', 39 | 'digits_between' => 'The :attribute must be between :min and :max digits.', 40 | 'dimensions' => 'The :attribute has invalid image dimensions.', 41 | 'distinct' => 'The :attribute field has a duplicate value.', 42 | 'email' => 'The :attribute must be a valid email address.', 43 | 'ends_with' => 'The :attribute must end with one of the following: :values', 44 | 'exists' => 'The selected :attribute is invalid.', 45 | 'file' => 'The :attribute must be a file.', 46 | 'filled' => 'The :attribute field must have a value.', 47 | 'gt' => [ 48 | 'numeric' => 'The :attribute must be greater than :value.', 49 | 'file' => 'The :attribute must be greater than :value kilobytes.', 50 | 'string' => 'The :attribute must be greater than :value characters.', 51 | 'array' => 'The :attribute must have more than :value items.', 52 | ], 53 | 'gte' => [ 54 | 'numeric' => 'The :attribute must be greater than or equal :value.', 55 | 'file' => 'The :attribute must be greater than or equal :value kilobytes.', 56 | 'string' => 'The :attribute must be greater than or equal :value characters.', 57 | 'array' => 'The :attribute must have :value items or more.', 58 | ], 59 | 'image' => 'The :attribute must be an image.', 60 | 'in' => 'The selected :attribute is invalid.', 61 | 'in_array' => 'The :attribute field does not exist in :other.', 62 | 'integer' => 'The :attribute must be an integer.', 63 | 'ip' => 'The :attribute must be a valid IP address.', 64 | 'ipv4' => 'The :attribute must be a valid IPv4 address.', 65 | 'ipv6' => 'The :attribute must be a valid IPv6 address.', 66 | 'json' => 'The :attribute must be a valid JSON string.', 67 | 'lt' => [ 68 | 'numeric' => 'The :attribute must be less than :value.', 69 | 'file' => 'The :attribute must be less than :value kilobytes.', 70 | 'string' => 'The :attribute must be less than :value characters.', 71 | 'array' => 'The :attribute must have less than :value items.', 72 | ], 73 | 'lte' => [ 74 | 'numeric' => 'The :attribute must be less than or equal :value.', 75 | 'file' => 'The :attribute must be less than or equal :value kilobytes.', 76 | 'string' => 'The :attribute must be less than or equal :value characters.', 77 | 'array' => 'The :attribute must not have more than :value items.', 78 | ], 79 | 'max' => [ 80 | 'numeric' => 'The :attribute may not be greater than :max.', 81 | 'file' => 'The :attribute may not be greater than :max kilobytes.', 82 | 'string' => 'The :attribute may not be greater than :max characters.', 83 | 'array' => 'The :attribute may not have more than :max items.', 84 | ], 85 | 'mimes' => 'The :attribute must be a file of type: :values.', 86 | 'mimetypes' => 'The :attribute must be a file of type: :values.', 87 | 'min' => [ 88 | 'numeric' => 'The :attribute must be at least :min.', 89 | 'file' => 'The :attribute must be at least :min kilobytes.', 90 | 'string' => 'The :attribute must be at least :min characters.', 91 | 'array' => 'The :attribute must have at least :min items.', 92 | ], 93 | 'not_in' => 'The selected :attribute is invalid.', 94 | 'not_regex' => 'The :attribute format is invalid.', 95 | 'numeric' => 'The :attribute must be a number.', 96 | 'present' => 'The :attribute field must be present.', 97 | 'regex' => 'The :attribute format is invalid.', 98 | 'required' => 'The :attribute field is required.', 99 | 'required_if' => 'The :attribute field is required when :other is :value.', 100 | 'required_unless' => 'The :attribute field is required unless :other is in :values.', 101 | 'required_with' => 'The :attribute field is required when :values is present.', 102 | 'required_with_all' => 'The :attribute field is required when :values are present.', 103 | 'required_without' => 'The :attribute field is required when :values is not present.', 104 | 'required_without_all' => 'The :attribute field is required when none of :values are present.', 105 | 'same' => 'The :attribute and :other must match.', 106 | 'size' => [ 107 | 'numeric' => 'The :attribute must be :size.', 108 | 'file' => 'The :attribute must be :size kilobytes.', 109 | 'string' => 'The :attribute must be :size characters.', 110 | 'array' => 'The :attribute must contain :size items.', 111 | ], 112 | 'starts_with' => 'The :attribute must start with one of the following: :values', 113 | 'string' => 'The :attribute must be a string.', 114 | 'timezone' => 'The :attribute must be a valid zone.', 115 | 'unique' => 'The :attribute has already been taken.', 116 | 'uploaded' => 'The :attribute failed to upload.', 117 | 'url' => 'The :attribute format is invalid.', 118 | 'uuid' => 'The :attribute must be a valid UUID.', 119 | 120 | /* 121 | |-------------------------------------------------------------------------- 122 | | Custom Validation Language Lines 123 | |-------------------------------------------------------------------------- 124 | | 125 | | Here you may specify custom validation messages for attributes using the 126 | | convention "attribute.rule" to name the lines. This makes it quick to 127 | | specify a specific custom language line for a given attribute rule. 128 | | 129 | */ 130 | 131 | 'custom' => [ 132 | 'attribute-name' => [ 133 | 'rule-name' => 'custom-message', 134 | ], 135 | ], 136 | 137 | /* 138 | |-------------------------------------------------------------------------- 139 | | Custom Validation Attributes 140 | |-------------------------------------------------------------------------- 141 | | 142 | | The following language lines are used to swap our attribute placeholder 143 | | with something more reader friendly such as "E-Mail Address" instead 144 | | of "email". This simply helps us make our message more expressive. 145 | | 146 | */ 147 | 148 | 'attributes' => [], 149 | 150 | ]; 151 | -------------------------------------------------------------------------------- /resources/views/permissions/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('permission::layouts.app') 2 | 3 | @section('styles') 4 | 5 | 6 | @endsection 7 | @section('content') 8 | 9 |
10 |
11 |
12 | 13 | 14 | Add Role 15 | 16 |
17 |
18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | @forelse( $roles as $key => $role ) 29 | 30 | 31 | 36 | 37 | @empty 38 | 39 | 40 | 41 | @endforelse 42 | 43 |
Role NameAction
{{ $role->name }} 32 | View 33 | Edit 34 | Delete 35 |
There is no Role
44 |
45 |
46 |
47 | 48 |
49 | 57 |
58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | @forelse( $permissions as $key => $permission ) 68 | 69 | 70 | 75 | 76 | @empty 77 | 78 | 79 | 80 | @endforelse 81 | 82 |
Permission NameAction
{{ $permission->name }} 71 | View 72 | Edit 73 | Delete 74 |
There is no Role
83 |
84 |
85 |
86 | 87 | 90 | 91 | 92 | 130 | 131 | 149 | 150 | 191 | 194 | 232 | 233 | 251 | 252 | 293 | @endsection 294 | 295 | @section('scripts') 296 | 297 | 298 | 299 | 300 | 313 | @endsection -------------------------------------------------------------------------------- /resources/assets/dashboard/js/custom.js: -------------------------------------------------------------------------------- 1 | (function($){ 2 | $(document).on("submit","#add_role_form",function(e){ 3 | e.preventDefault(); 4 | 5 | var form = $(this); 6 | var action = form.attr('action'); 7 | var method = form.attr('method'); 8 | 9 | var formData = new FormData(form[0]); 10 | 11 | $.ajax({ 12 | url: action, 13 | method: method, 14 | dataType: 'json', 15 | data: formData, 16 | contentType: false, 17 | cache: false, 18 | processData: false, 19 | success: function(result){ 20 | // console.log( result ); 21 | if( result.success == true ) { 22 | 23 | var viewBtn = 'View '; 24 | var editBtn = 'Edit '; 25 | var deleteBtn = 'Delete '; 26 | 27 | $('#role_table').DataTable().row.add([ 28 | result.role.name, viewBtn + editBtn + deleteBtn 29 | ]).draw(); 30 | 31 | form.trigger("reset"); 32 | 33 | $("#addRoleModal").modal('hide'); 34 | $('body').removeClass('modal-open'); 35 | $('.modal-backdrop').fadeOut(); 36 | } 37 | }, 38 | error: function(err){ 39 | // console.log( err ); 40 | } 41 | }); 42 | }); 43 | 44 | $(document).on("click",".view_role", function(e){ 45 | e.preventDefault(); 46 | 47 | var id = $(this).data('id'); 48 | // var action = $(this).data('action'); 49 | 50 | $.ajax({ 51 | url: permission_prefix+'/role/'+id, 52 | method: 'GET', 53 | dataType: 'json', 54 | data: { 55 | 'id' : id 56 | }, 57 | success: function(result){ 58 | // console.log( result ); 59 | if( result.success == true ){ 60 | var form = $('#edit_role_form'); 61 | $("#role_id").val(id); 62 | 63 | var role_name_html = '

'+result.role.name+'

'; 64 | var permissions_html = '
'; 65 | 66 | if( result.permissions.length > 0 ) { 67 | var listItem = ''; 68 | $.each(result.permissions, function( index, permission ){ 69 | listItem = listItem + '
  • '; 70 | }); 71 | } 72 | 73 | var permissions_html = permissions_html + '
      '+listItem+'
  • ' 74 | 75 | $("#viewRoleModal").find(".modal-body").html(role_name_html+permissions_html); 76 | } 77 | }, 78 | error: function( err ){ 79 | // console.log(err); 80 | } 81 | }); 82 | }); 83 | 84 | $(document).on("click",".edit_role", function(e){ 85 | e.preventDefault(); 86 | 87 | var id = $(this).data('id'); 88 | var action = $(this).data('action'); 89 | 90 | $.ajax({ 91 | url: action, 92 | method: 'GET', 93 | dataType: 'json', 94 | data: { 95 | 'id' : id 96 | }, 97 | success: function(result){ 98 | // console.log( result ); 99 | if( result.success == true ){ 100 | document.getElementById("edit_role_form").reset(); 101 | var form = $('#edit_role_form'); 102 | form.find('#role_name').val(""); 103 | form.find(".edit_permissions").each(function(i, v){ 104 | $(this).removeAttr("checked"); 105 | }); 106 | $("#role_id").val(id); 107 | 108 | form.find('#role_name').val(result.role.name); 109 | 110 | if( result.permissions.length > 0 ) { 111 | $.each(result.permissions, function( index, permission ){ 112 | form.find(".edit_permissions").each(function(i, v){ 113 | if( $(this).val() == permission.id ) { 114 | $(this).attr('checked', 'checked'); 115 | } 116 | }); 117 | }); 118 | } 119 | } 120 | }, 121 | error: function( err ){ 122 | // console.log(err); 123 | } 124 | }); 125 | }); 126 | 127 | $(document).on("submit","#edit_role_form", function(e){ 128 | e.preventDefault(); 129 | var form = $(this); 130 | var id = $('#role_id').val(); 131 | var action = form.attr("action"); 132 | var method = form.find('input[name="_method"]').val(); 133 | 134 | var formData = new FormData(form[0]); 135 | 136 | $.ajax({ 137 | url: action, 138 | method: 'POST', 139 | dataType: 'json', 140 | data: formData, 141 | contentType: false, 142 | cache: false, 143 | processData: false, 144 | success: function( result ){ 145 | // console.log( result ); 146 | if( result.success == true ) { 147 | var row_id = $('#row_'+result.role.id).data("row"); 148 | 149 | var viewBtn = 'View '; 150 | var editBtn = 'Edit '; 151 | var deleteBtn = 'Delete '; 152 | 153 | $('#role_table').DataTable().row(row_id).data([ 154 | result.role.name, viewBtn + editBtn + deleteBtn 155 | ]).draw(); 156 | 157 | form.trigger("reset"); 158 | 159 | $("#editRoleModal").modal('hide'); 160 | $('body').removeClass('modal-open'); 161 | $('.modal-backdrop').fadeOut(); 162 | } 163 | }, 164 | error: function( err ) { 165 | // console.log( err ); 166 | } 167 | }); 168 | }); 169 | 170 | $(document).on("click",".delete_role", function(e){ 171 | e.preventDefault(); 172 | Swal.fire({ 173 | title: 'Are you sure?', 174 | text: 'You will not be able to recover this Role', 175 | type: 'warning', 176 | showCancelButton: true, 177 | confirmButtonText: 'Yes, delete it!', 178 | cancelButtonText: 'No, keep it' 179 | }).then((result) => { 180 | if (result.value) { 181 | $.ajax({ 182 | url: permission_prefix+'/role', 183 | method: 'POST', 184 | dataType: 'json', 185 | data: { 186 | "_method": 'DELETE', 187 | "_token": $('meta[name="csrf-token"]').attr('content'), 188 | 'role_id': $(this).data('id'), 189 | }, 190 | success: function(result){ 191 | // console.log( result ); 192 | if( result.success == true ) { 193 | // console.log( data ); 194 | Swal.fire( 195 | 'Deleted!', 196 | 'Role Deleted Successfully', 197 | 'success' 198 | ); 199 | 200 | var row_id = $('#row_'+result.role.id).data("row"); 201 | $('#role_table').DataTable().row(row_id).remove().draw(); 202 | 203 | // $(".menu-container").html(data.html); 204 | 205 | // $('body').removeClass('modal-open'); 206 | // $('.modal-backdrop').fadeOut(); 207 | } 208 | }, 209 | error: function(err){ 210 | // console.log( err ); 211 | } 212 | }); 213 | } else if (result.dismiss === Swal.DismissReason.cancel) { 214 | Swal.fire( 215 | 'Cancelled', 216 | 'Your imaginary file is safe :)', 217 | 'error' 218 | ) 219 | } 220 | }) 221 | }); 222 | 223 | /* 224 | * Permission 225 | */ 226 | 227 | $(document).on("submit","#add_permission_form",function(e){ 228 | e.preventDefault(); 229 | 230 | var form = $(this); 231 | var action = form.attr('action'); 232 | var method = form.attr('method'); 233 | 234 | var formData = new FormData(form[0]); 235 | 236 | $.ajax({ 237 | url: action, 238 | method: method, 239 | dataType: 'json', 240 | data: formData, 241 | contentType: false, 242 | cache: false, 243 | processData: false, 244 | success: function(result){ 245 | // console.log( result ); 246 | if( result.success == true ) { 247 | 248 | var viewBtn = 'View '; 249 | var editBtn = 'Edit '; 250 | var deleteBtn = 'Delete '; 251 | 252 | $('#permission_table').DataTable().row.add([ 253 | result.permission.name, viewBtn + editBtn + deleteBtn 254 | ]).draw(); 255 | 256 | form.trigger("reset"); 257 | 258 | $("#addPermissionModal").modal('hide'); 259 | $('body').removeClass('modal-open'); 260 | $('.modal-backdrop').fadeOut(); 261 | } 262 | }, 263 | error: function(err){ 264 | // console.log( err ); 265 | } 266 | }); 267 | }); 268 | 269 | $(document).on("click",".view_permission", function(e){ 270 | e.preventDefault(); 271 | 272 | var id = $(this).data('id'); 273 | // var action = $(this).data('action'); 274 | 275 | $.ajax({ 276 | url: permission_prefix+'/permission/'+id, 277 | method: 'GET', 278 | dataType: 'json', 279 | data: { 280 | 'id' : id 281 | }, 282 | success: function(result){ 283 | // console.log( result ); 284 | if( result.success == true ){ 285 | var form = $('#edit_permission_form'); 286 | $("#permission_id").val(id); 287 | 288 | var permission_html = '

    '+result.permission.name+'

    '; 289 | 290 | $("#viewPermissionModal").find(".modal-body").html(permission_html); 291 | } 292 | }, 293 | error: function( err ){ 294 | // console.log(err); 295 | } 296 | }); 297 | }); 298 | 299 | $(document).on("click",".edit_permission", function(e){ 300 | e.preventDefault(); 301 | 302 | var id = $(this).data('id'); 303 | var action = $(this).data('action'); 304 | 305 | $.ajax({ 306 | url: action, 307 | method: 'GET', 308 | dataType: 'json', 309 | data: { 310 | 'id' : id 311 | }, 312 | success: function(result){ 313 | // console.log( result ); 314 | if( result.success == true ){ 315 | 316 | document.getElementById("edit_permission_form").reset(); 317 | var form = $('#edit_permission_form'); 318 | form.find('#role_name').val(""); 319 | form.find(".edit_roles").each(function(i, v){ 320 | $(this).removeAttr("checked"); 321 | }); 322 | $("#permission_id").val(id); 323 | 324 | form.find('#permission_name').val(result.permission.name); 325 | 326 | if( result.roles.length > 0 ) { 327 | $.each(result.roles, function( index, role ){ 328 | form.find(".edit_roles").each(function(i, v){ 329 | if( $(this).val() == role.id ) { 330 | $(this).attr('checked', 'checked'); 331 | } 332 | }); 333 | }); 334 | } 335 | } 336 | }, 337 | error: function( err ){ 338 | // console.log(err); 339 | } 340 | }); 341 | }); 342 | 343 | $(document).on("submit","#edit_permission_form", function(e){ 344 | e.preventDefault(); 345 | var form = $(this); 346 | var id = $('#permission_id').val(); 347 | var action = form.attr("action"); 348 | var method = form.find('input[name="_method"]').val(); 349 | 350 | var formData = new FormData(form[0]); 351 | 352 | $.ajax({ 353 | url: action, 354 | method: 'POST', 355 | dataType: 'json', 356 | data: formData, 357 | contentType: false, 358 | cache: false, 359 | processData: false, 360 | success: function( result ){ 361 | // console.log( result ); 362 | if( result.success == true ) { 363 | var row_id = $('#row_'+result.permission.id).data("row"); 364 | 365 | var viewBtn = 'View '; 366 | var editBtn = 'Edit '; 367 | var deleteBtn = 'Delete '; 368 | 369 | $('#permission_table').DataTable().row(row_id).data([ 370 | result.permission.name, viewBtn + editBtn + deleteBtn 371 | ]).draw(); 372 | 373 | form.trigger("reset"); 374 | 375 | $("#editPermissionModal").modal('hide'); 376 | $('body').removeClass('modal-open'); 377 | $('.modal-backdrop').fadeOut(); 378 | } 379 | }, 380 | error: function( err ) { 381 | // console.log( err ); 382 | } 383 | }); 384 | }); 385 | 386 | $(document).on("click",".delete_permission", function(e){ 387 | e.preventDefault(); 388 | Swal.fire({ 389 | title: 'Are you sure?', 390 | text: 'You will not be able to recover this Permission', 391 | type: 'warning', 392 | showCancelButton: true, 393 | confirmButtonText: 'Yes, delete it!', 394 | cancelButtonText: 'No, keep it' 395 | }).then((result) => { 396 | if (result.value) { 397 | $.ajax({ 398 | url: permission_prefix+'/permission', 399 | method: 'POST', 400 | dataType: 'json', 401 | data: { 402 | "_method": 'DELETE', 403 | "_token": $('meta[name="csrf-token"]').attr('content'), 404 | 'permission_id': $(this).data('id'), 405 | }, 406 | success: function(result){ 407 | // console.log( result ); 408 | if( result.success == true ) { 409 | // console.log( data ); 410 | Swal.fire( 411 | 'Deleted!', 412 | 'Permission Deleted Successfully', 413 | 'success' 414 | ); 415 | 416 | var row_id = $('#row_'+result.permission.id).data("row"); 417 | $('#permission_table').DataTable().row(row_id).remove().draw(); 418 | 419 | // $(".menu-container").html(data.html); 420 | 421 | // $('body').removeClass('modal-open'); 422 | // $('.modal-backdrop').fadeOut(); 423 | } 424 | }, 425 | error: function(err){ 426 | // console.log( err ); 427 | } 428 | }); 429 | } else if (result.dismiss === Swal.DismissReason.cancel) { 430 | Swal.fire( 431 | 'Cancelled', 432 | 'Your imaginary file is safe :)', 433 | 'error' 434 | ) 435 | } 436 | }) 437 | }); 438 | })(jQuery); -------------------------------------------------------------------------------- /resources/assets/js/components/Users.vue: -------------------------------------------------------------------------------- 1 | 164 | 165 | -------------------------------------------------------------------------------- /resources/assets/dashboard/css/sweetalert2.min.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";@-webkit-keyframes swal2-show{0%{transform:scale(.7)}45%{transform:scale(1.05)}80%{transform:scale(.95)}100%{transform:scale(1)}}@keyframes swal2-show{0%{transform:scale(.7)}45%{transform:scale(1.05)}80%{transform:scale(.95)}100%{transform:scale(1)}}@-webkit-keyframes swal2-hide{0%{transform:scale(1);opacity:1}100%{transform:scale(.5);opacity:0}}@keyframes swal2-hide{0%{transform:scale(1);opacity:1}100%{transform:scale(.5);opacity:0}}@-webkit-keyframes swal2-animate-success-line-tip{0%{top:1.1875em;left:.0625em;width:0}54%{top:1.0625em;left:.125em;width:0}70%{top:2.1875em;left:-.375em;width:3.125em}84%{top:3em;left:1.3125em;width:1.0625em}100%{top:2.8125em;left:.875em;width:1.5625em}}@keyframes swal2-animate-success-line-tip{0%{top:1.1875em;left:.0625em;width:0}54%{top:1.0625em;left:.125em;width:0}70%{top:2.1875em;left:-.375em;width:3.125em}84%{top:3em;left:1.3125em;width:1.0625em}100%{top:2.8125em;left:.875em;width:1.5625em}}@-webkit-keyframes swal2-animate-success-line-long{0%{top:3.375em;right:2.875em;width:0}65%{top:3.375em;right:2.875em;width:0}84%{top:2.1875em;right:0;width:3.4375em}100%{top:2.375em;right:.5em;width:2.9375em}}@keyframes swal2-animate-success-line-long{0%{top:3.375em;right:2.875em;width:0}65%{top:3.375em;right:2.875em;width:0}84%{top:2.1875em;right:0;width:3.4375em}100%{top:2.375em;right:.5em;width:2.9375em}}@-webkit-keyframes swal2-rotate-success-circular-line{0%{transform:rotate(-45deg)}5%{transform:rotate(-45deg)}12%{transform:rotate(-405deg)}100%{transform:rotate(-405deg)}}@keyframes swal2-rotate-success-circular-line{0%{transform:rotate(-45deg)}5%{transform:rotate(-45deg)}12%{transform:rotate(-405deg)}100%{transform:rotate(-405deg)}}@-webkit-keyframes swal2-animate-error-x-mark{0%{margin-top:1.625em;transform:scale(.4);opacity:0}50%{margin-top:1.625em;transform:scale(.4);opacity:0}80%{margin-top:-.375em;transform:scale(1.15)}100%{margin-top:0;transform:scale(1);opacity:1}}@keyframes swal2-animate-error-x-mark{0%{margin-top:1.625em;transform:scale(.4);opacity:0}50%{margin-top:1.625em;transform:scale(.4);opacity:0}80%{margin-top:-.375em;transform:scale(1.15)}100%{margin-top:0;transform:scale(1);opacity:1}}@-webkit-keyframes swal2-animate-error-icon{0%{transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0);opacity:1}}@keyframes swal2-animate-error-icon{0%{transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0);opacity:1}}body.swal2-toast-shown .swal2-container{background-color:transparent}body.swal2-toast-shown .swal2-container.swal2-shown{background-color:transparent}body.swal2-toast-shown .swal2-container.swal2-top{top:0;right:auto;bottom:auto;left:50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-top-end,body.swal2-toast-shown .swal2-container.swal2-top-right{top:0;right:0;bottom:auto;left:auto}body.swal2-toast-shown .swal2-container.swal2-top-left,body.swal2-toast-shown .swal2-container.swal2-top-start{top:0;right:auto;bottom:auto;left:0}body.swal2-toast-shown .swal2-container.swal2-center-left,body.swal2-toast-shown .swal2-container.swal2-center-start{top:50%;right:auto;bottom:auto;left:0;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-center{top:50%;right:auto;bottom:auto;left:50%;transform:translate(-50%,-50%)}body.swal2-toast-shown .swal2-container.swal2-center-end,body.swal2-toast-shown .swal2-container.swal2-center-right{top:50%;right:0;bottom:auto;left:auto;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-left,body.swal2-toast-shown .swal2-container.swal2-bottom-start{top:auto;right:auto;bottom:0;left:0}body.swal2-toast-shown .swal2-container.swal2-bottom{top:auto;right:auto;bottom:0;left:50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-end,body.swal2-toast-shown .swal2-container.swal2-bottom-right{top:auto;right:0;bottom:0;left:auto}body.swal2-toast-column .swal2-toast{flex-direction:column;align-items:stretch}body.swal2-toast-column .swal2-toast .swal2-actions{flex:1;align-self:stretch;height:2.2em;margin-top:.3125em}body.swal2-toast-column .swal2-toast .swal2-loading{justify-content:center}body.swal2-toast-column .swal2-toast .swal2-input{height:2em;margin:.3125em auto;font-size:1em}body.swal2-toast-column .swal2-toast .swal2-validation-message{font-size:1em}.swal2-popup.swal2-toast{flex-direction:row;align-items:center;width:auto;padding:.625em;overflow-y:hidden;box-shadow:0 0 .625em #d9d9d9}.swal2-popup.swal2-toast .swal2-header{flex-direction:row}.swal2-popup.swal2-toast .swal2-title{flex-grow:1;justify-content:flex-start;margin:0 .6em;font-size:1em}.swal2-popup.swal2-toast .swal2-footer{margin:.5em 0 0;padding:.5em 0 0;font-size:.8em}.swal2-popup.swal2-toast .swal2-close{position:static;width:.8em;height:.8em;line-height:.8}.swal2-popup.swal2-toast .swal2-content{justify-content:flex-start;font-size:1em}.swal2-popup.swal2-toast .swal2-icon{width:2em;min-width:2em;height:2em;margin:0}.swal2-popup.swal2-toast .swal2-icon::before{display:flex;align-items:center;font-size:2em;font-weight:700}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){.swal2-popup.swal2-toast .swal2-icon::before{font-size:.25em}}.swal2-popup.swal2-toast .swal2-icon.swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line]{top:.875em;width:1.375em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left]{left:.3125em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right]{right:.3125em}.swal2-popup.swal2-toast .swal2-actions{flex-basis:auto!important;width:auto;height:auto;margin:0 .3125em}.swal2-popup.swal2-toast .swal2-styled{margin:0 .3125em;padding:.3125em .625em;font-size:1em}.swal2-popup.swal2-toast .swal2-styled:focus{box-shadow:0 0 0 .0625em #fff,0 0 0 .125em rgba(50,100,150,.4)}.swal2-popup.swal2-toast .swal2-success{border-color:#a5dc86}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line]{position:absolute;width:1.6em;height:3em;transform:rotate(45deg);border-radius:50%}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=left]{top:-.8em;left:-.5em;transform:rotate(-45deg);transform-origin:2em 2em;border-radius:4em 0 0 4em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=right]{top:-.25em;left:.9375em;transform-origin:0 1.5em;border-radius:0 4em 4em 0}.swal2-popup.swal2-toast .swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-success .swal2-success-fix{top:0;left:.4375em;width:.4375em;height:2.6875em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line]{height:.3125em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=tip]{top:1.125em;left:.1875em;width:.75em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=long]{top:.9375em;right:.1875em;width:1.375em}.swal2-popup.swal2-toast.swal2-show{-webkit-animation:swal2-toast-show .5s;animation:swal2-toast-show .5s}.swal2-popup.swal2-toast.swal2-hide{-webkit-animation:swal2-toast-hide .1s forwards;animation:swal2-toast-hide .1s forwards}.swal2-popup.swal2-toast .swal2-animate-success-icon .swal2-success-line-tip{-webkit-animation:swal2-toast-animate-success-line-tip .75s;animation:swal2-toast-animate-success-line-tip .75s}.swal2-popup.swal2-toast .swal2-animate-success-icon .swal2-success-line-long{-webkit-animation:swal2-toast-animate-success-line-long .75s;animation:swal2-toast-animate-success-line-long .75s}@-webkit-keyframes swal2-toast-show{0%{transform:translateY(-.625em) rotateZ(2deg)}33%{transform:translateY(0) rotateZ(-2deg)}66%{transform:translateY(.3125em) rotateZ(2deg)}100%{transform:translateY(0) rotateZ(0)}}@keyframes swal2-toast-show{0%{transform:translateY(-.625em) rotateZ(2deg)}33%{transform:translateY(0) rotateZ(-2deg)}66%{transform:translateY(.3125em) rotateZ(2deg)}100%{transform:translateY(0) rotateZ(0)}}@-webkit-keyframes swal2-toast-hide{100%{transform:rotateZ(1deg);opacity:0}}@keyframes swal2-toast-hide{100%{transform:rotateZ(1deg);opacity:0}}@-webkit-keyframes swal2-toast-animate-success-line-tip{0%{top:.5625em;left:.0625em;width:0}54%{top:.125em;left:.125em;width:0}70%{top:.625em;left:-.25em;width:1.625em}84%{top:1.0625em;left:.75em;width:.5em}100%{top:1.125em;left:.1875em;width:.75em}}@keyframes swal2-toast-animate-success-line-tip{0%{top:.5625em;left:.0625em;width:0}54%{top:.125em;left:.125em;width:0}70%{top:.625em;left:-.25em;width:1.625em}84%{top:1.0625em;left:.75em;width:.5em}100%{top:1.125em;left:.1875em;width:.75em}}@-webkit-keyframes swal2-toast-animate-success-line-long{0%{top:1.625em;right:1.375em;width:0}65%{top:1.25em;right:.9375em;width:0}84%{top:.9375em;right:0;width:1.125em}100%{top:.9375em;right:.1875em;width:1.375em}}@keyframes swal2-toast-animate-success-line-long{0%{top:1.625em;right:1.375em;width:0}65%{top:1.25em;right:.9375em;width:0}84%{top:.9375em;right:0;width:1.125em}100%{top:.9375em;right:.1875em;width:1.375em}}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow:hidden}body.swal2-height-auto{height:auto!important}body.swal2-no-backdrop .swal2-shown{top:auto;right:auto;bottom:auto;left:auto;max-width:calc(100% - .625em * 2);background-color:transparent}body.swal2-no-backdrop .swal2-shown>.swal2-modal{box-shadow:0 0 10px rgba(0,0,0,.4)}body.swal2-no-backdrop .swal2-shown.swal2-top{top:0;left:50%;transform:translateX(-50%)}body.swal2-no-backdrop .swal2-shown.swal2-top-left,body.swal2-no-backdrop .swal2-shown.swal2-top-start{top:0;left:0}body.swal2-no-backdrop .swal2-shown.swal2-top-end,body.swal2-no-backdrop .swal2-shown.swal2-top-right{top:0;right:0}body.swal2-no-backdrop .swal2-shown.swal2-center{top:50%;left:50%;transform:translate(-50%,-50%)}body.swal2-no-backdrop .swal2-shown.swal2-center-left,body.swal2-no-backdrop .swal2-shown.swal2-center-start{top:50%;left:0;transform:translateY(-50%)}body.swal2-no-backdrop .swal2-shown.swal2-center-end,body.swal2-no-backdrop .swal2-shown.swal2-center-right{top:50%;right:0;transform:translateY(-50%)}body.swal2-no-backdrop .swal2-shown.swal2-bottom{bottom:0;left:50%;transform:translateX(-50%)}body.swal2-no-backdrop .swal2-shown.swal2-bottom-left,body.swal2-no-backdrop .swal2-shown.swal2-bottom-start{bottom:0;left:0}body.swal2-no-backdrop .swal2-shown.swal2-bottom-end,body.swal2-no-backdrop .swal2-shown.swal2-bottom-right{right:0;bottom:0}.swal2-container{display:flex;position:fixed;z-index:1060;top:0;right:0;bottom:0;left:0;flex-direction:row;align-items:center;justify-content:center;padding:.625em;overflow-x:hidden;background-color:transparent;-webkit-overflow-scrolling:touch}.swal2-container.swal2-top{align-items:flex-start}.swal2-container.swal2-top-left,.swal2-container.swal2-top-start{align-items:flex-start;justify-content:flex-start}.swal2-container.swal2-top-end,.swal2-container.swal2-top-right{align-items:flex-start;justify-content:flex-end}.swal2-container.swal2-center{align-items:center}.swal2-container.swal2-center-left,.swal2-container.swal2-center-start{align-items:center;justify-content:flex-start}.swal2-container.swal2-center-end,.swal2-container.swal2-center-right{align-items:center;justify-content:flex-end}.swal2-container.swal2-bottom{align-items:flex-end}.swal2-container.swal2-bottom-left,.swal2-container.swal2-bottom-start{align-items:flex-end;justify-content:flex-start}.swal2-container.swal2-bottom-end,.swal2-container.swal2-bottom-right{align-items:flex-end;justify-content:flex-end}.swal2-container.swal2-bottom-end>:first-child,.swal2-container.swal2-bottom-left>:first-child,.swal2-container.swal2-bottom-right>:first-child,.swal2-container.swal2-bottom-start>:first-child,.swal2-container.swal2-bottom>:first-child{margin-top:auto}.swal2-container.swal2-grow-fullscreen>.swal2-modal{display:flex!important;flex:1;align-self:stretch;justify-content:center}.swal2-container.swal2-grow-row>.swal2-modal{display:flex!important;flex:1;align-content:center;justify-content:center}.swal2-container.swal2-grow-column{flex:1;flex-direction:column}.swal2-container.swal2-grow-column.swal2-bottom,.swal2-container.swal2-grow-column.swal2-center,.swal2-container.swal2-grow-column.swal2-top{align-items:center}.swal2-container.swal2-grow-column.swal2-bottom-left,.swal2-container.swal2-grow-column.swal2-bottom-start,.swal2-container.swal2-grow-column.swal2-center-left,.swal2-container.swal2-grow-column.swal2-center-start,.swal2-container.swal2-grow-column.swal2-top-left,.swal2-container.swal2-grow-column.swal2-top-start{align-items:flex-start}.swal2-container.swal2-grow-column.swal2-bottom-end,.swal2-container.swal2-grow-column.swal2-bottom-right,.swal2-container.swal2-grow-column.swal2-center-end,.swal2-container.swal2-grow-column.swal2-center-right,.swal2-container.swal2-grow-column.swal2-top-end,.swal2-container.swal2-grow-column.swal2-top-right{align-items:flex-end}.swal2-container.swal2-grow-column>.swal2-modal{display:flex!important;flex:1;align-content:center;justify-content:center}.swal2-container:not(.swal2-top):not(.swal2-top-start):not(.swal2-top-end):not(.swal2-top-left):not(.swal2-top-right):not(.swal2-center-start):not(.swal2-center-end):not(.swal2-center-left):not(.swal2-center-right):not(.swal2-bottom):not(.swal2-bottom-start):not(.swal2-bottom-end):not(.swal2-bottom-left):not(.swal2-bottom-right):not(.swal2-grow-fullscreen)>.swal2-modal{margin:auto}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){.swal2-container .swal2-modal{margin:0!important}}.swal2-container.swal2-fade{transition:background-color .1s}.swal2-container.swal2-shown{background-color:rgba(0,0,0,.4)}.swal2-popup{display:none;position:relative;box-sizing:border-box;flex-direction:column;justify-content:center;width:32em;max-width:100%;padding:1.25em;border:none;border-radius:.3125em;background:#fff;font-family:inherit;font-size:1rem}.swal2-popup:focus{outline:0}.swal2-popup.swal2-loading{overflow-y:hidden}.swal2-header{display:flex;flex-direction:column;align-items:center}.swal2-title{position:relative;max-width:100%;margin:0 0 .4em;padding:0;color:#595959;font-size:1.875em;font-weight:600;text-align:center;text-transform:none;word-wrap:break-word}.swal2-actions{display:flex;z-index:1;flex-wrap:wrap;align-items:center;justify-content:center;width:100%;margin:1.25em auto 0}.swal2-actions:not(.swal2-loading) .swal2-styled[disabled]{opacity:.4}.swal2-actions:not(.swal2-loading) .swal2-styled:hover{background-image:linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.1))}.swal2-actions:not(.swal2-loading) .swal2-styled:active{background-image:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.2))}.swal2-actions.swal2-loading .swal2-styled.swal2-confirm{box-sizing:border-box;width:2.5em;height:2.5em;margin:.46875em;padding:0;-webkit-animation:swal2-rotate-loading 1.5s linear 0s infinite normal;animation:swal2-rotate-loading 1.5s linear 0s infinite normal;border:.25em solid transparent;border-radius:100%;border-color:transparent;background-color:transparent!important;color:transparent;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.swal2-actions.swal2-loading .swal2-styled.swal2-cancel{margin-right:30px;margin-left:30px}.swal2-actions.swal2-loading :not(.swal2-styled).swal2-confirm::after{content:"";display:inline-block;width:15px;height:15px;margin-left:5px;-webkit-animation:swal2-rotate-loading 1.5s linear 0s infinite normal;animation:swal2-rotate-loading 1.5s linear 0s infinite normal;border:3px solid #999;border-radius:50%;border-right-color:transparent;box-shadow:1px 1px 1px #fff}.swal2-styled{margin:.3125em;padding:.625em 2em;box-shadow:none;font-weight:500}.swal2-styled:not([disabled]){cursor:pointer}.swal2-styled.swal2-confirm{border:0;border-radius:.25em;background:initial;background-color:#3085d6;color:#fff;font-size:1.0625em}.swal2-styled.swal2-cancel{border:0;border-radius:.25em;background:initial;background-color:#aaa;color:#fff;font-size:1.0625em}.swal2-styled:focus{outline:0;box-shadow:0 0 0 2px #fff,0 0 0 4px rgba(50,100,150,.4)}.swal2-styled::-moz-focus-inner{border:0}.swal2-footer{justify-content:center;margin:1.25em 0 0;padding:1em 0 0;border-top:1px solid #eee;color:#545454;font-size:1em}.swal2-image{max-width:100%;margin:1.25em auto}.swal2-close{position:absolute;z-index:2;top:0;right:0;justify-content:center;width:1.2em;height:1.2em;padding:0;overflow:hidden;transition:color .1s ease-out;border:none;border-radius:0;outline:initial;background:0 0;color:#ccc;font-family:serif;font-size:2.5em;line-height:1.2;cursor:pointer}.swal2-close:hover{transform:none;background:0 0;color:#f27474}.swal2-content{z-index:1;justify-content:center;margin:0;padding:0;color:#545454;font-size:1.125em;font-weight:400;line-height:normal;text-align:center;word-wrap:break-word}.swal2-checkbox,.swal2-file,.swal2-input,.swal2-radio,.swal2-select,.swal2-textarea{margin:1em auto}.swal2-file,.swal2-input,.swal2-textarea{box-sizing:border-box;width:100%;transition:border-color .3s,box-shadow .3s;border:1px solid #d9d9d9;border-radius:.1875em;background:inherit;box-shadow:inset 0 1px 1px rgba(0,0,0,.06);color:inherit;font-size:1.125em}.swal2-file.swal2-inputerror,.swal2-input.swal2-inputerror,.swal2-textarea.swal2-inputerror{border-color:#f27474!important;box-shadow:0 0 2px #f27474!important}.swal2-file:focus,.swal2-input:focus,.swal2-textarea:focus{border:1px solid #b4dbed;outline:0;box-shadow:0 0 3px #c4e6f5}.swal2-file::-webkit-input-placeholder,.swal2-input::-webkit-input-placeholder,.swal2-textarea::-webkit-input-placeholder{color:#ccc}.swal2-file::-moz-placeholder,.swal2-input::-moz-placeholder,.swal2-textarea::-moz-placeholder{color:#ccc}.swal2-file:-ms-input-placeholder,.swal2-input:-ms-input-placeholder,.swal2-textarea:-ms-input-placeholder{color:#ccc}.swal2-file::-ms-input-placeholder,.swal2-input::-ms-input-placeholder,.swal2-textarea::-ms-input-placeholder{color:#ccc}.swal2-file::placeholder,.swal2-input::placeholder,.swal2-textarea::placeholder{color:#ccc}.swal2-range{margin:1em auto;background:inherit}.swal2-range input{width:80%}.swal2-range output{width:20%;color:inherit;font-weight:600;text-align:center}.swal2-range input,.swal2-range output{height:2.625em;padding:0;font-size:1.125em;line-height:2.625em}.swal2-input{height:2.625em;padding:0 .75em}.swal2-input[type=number]{max-width:10em}.swal2-file{background:inherit;font-size:1.125em}.swal2-textarea{height:6.75em;padding:.75em}.swal2-select{min-width:50%;max-width:100%;padding:.375em .625em;background:inherit;color:inherit;font-size:1.125em}.swal2-checkbox,.swal2-radio{align-items:center;justify-content:center;background:inherit;color:inherit}.swal2-checkbox label,.swal2-radio label{margin:0 .6em;font-size:1.125em}.swal2-checkbox input,.swal2-radio input{margin:0 .4em}.swal2-validation-message{display:none;align-items:center;justify-content:center;padding:.625em;overflow:hidden;background:#f0f0f0;color:#666;font-size:1em;font-weight:300}.swal2-validation-message::before{content:"!";display:inline-block;width:1.5em;min-width:1.5em;height:1.5em;margin:0 .625em;zoom:normal;border-radius:50%;background-color:#f27474;color:#fff;font-weight:600;line-height:1.5em;text-align:center}@supports (-ms-accelerator:true){.swal2-range input{width:100%!important}.swal2-range output{display:none}}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){.swal2-range input{width:100%!important}.swal2-range output{display:none}}@-moz-document url-prefix(){.swal2-close:focus{outline:2px solid rgba(50,100,150,.4)}}.swal2-icon{position:relative;box-sizing:content-box;justify-content:center;width:5em;height:5em;margin:1.25em auto 1.875em;zoom:normal;border:.25em solid transparent;border-radius:50%;font-family:inherit;line-height:5em;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.swal2-icon::before{display:flex;align-items:center;height:92%;font-size:3.75em}.swal2-icon.swal2-error{border-color:#f27474}.swal2-icon.swal2-error .swal2-x-mark{position:relative;flex-grow:1}.swal2-icon.swal2-error [class^=swal2-x-mark-line]{display:block;position:absolute;top:2.3125em;width:2.9375em;height:.3125em;border-radius:.125em;background-color:#f27474}.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left]{left:1.0625em;transform:rotate(45deg)}.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right]{right:1em;transform:rotate(-45deg)}.swal2-icon.swal2-warning{border-color:#facea8;color:#f8bb86}.swal2-icon.swal2-warning::before{content:"!"}.swal2-icon.swal2-info{border-color:#9de0f6;color:#3fc3ee}.swal2-icon.swal2-info::before{content:"i"}.swal2-icon.swal2-question{border-color:#c9dae1;color:#87adbd}.swal2-icon.swal2-question::before{content:"?"}.swal2-icon.swal2-question.swal2-arabic-question-mark::before{content:"؟"}.swal2-icon.swal2-success{border-color:#a5dc86}.swal2-icon.swal2-success [class^=swal2-success-circular-line]{position:absolute;width:3.75em;height:7.5em;transform:rotate(45deg);border-radius:50%}.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=left]{top:-.4375em;left:-2.0635em;transform:rotate(-45deg);transform-origin:3.75em 3.75em;border-radius:7.5em 0 0 7.5em}.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=right]{top:-.6875em;left:1.875em;transform:rotate(-45deg);transform-origin:0 3.75em;border-radius:0 7.5em 7.5em 0}.swal2-icon.swal2-success .swal2-success-ring{position:absolute;z-index:2;top:-.25em;left:-.25em;box-sizing:content-box;width:100%;height:100%;border:.25em solid rgba(165,220,134,.3);border-radius:50%}.swal2-icon.swal2-success .swal2-success-fix{position:absolute;z-index:1;top:.5em;left:1.625em;width:.4375em;height:5.625em;transform:rotate(-45deg)}.swal2-icon.swal2-success [class^=swal2-success-line]{display:block;position:absolute;z-index:2;height:.3125em;border-radius:.125em;background-color:#a5dc86}.swal2-icon.swal2-success [class^=swal2-success-line][class$=tip]{top:2.875em;left:.875em;width:1.5625em;transform:rotate(45deg)}.swal2-icon.swal2-success [class^=swal2-success-line][class$=long]{top:2.375em;right:.5em;width:2.9375em;transform:rotate(-45deg)}.swal2-progress-steps{align-items:center;margin:0 0 1.25em;padding:0;background:inherit;font-weight:600}.swal2-progress-steps li{display:inline-block;position:relative}.swal2-progress-steps .swal2-progress-step{z-index:20;width:2em;height:2em;border-radius:2em;background:#3085d6;color:#fff;line-height:2em;text-align:center}.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step{background:#3085d6}.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step{background:#add8e6;color:#fff}.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step-line{background:#add8e6}.swal2-progress-steps .swal2-progress-step-line{z-index:10;width:2.5em;height:.4em;margin:0 -1px;background:#3085d6}[class^=swal2]{-webkit-tap-highlight-color:transparent}.swal2-show{-webkit-animation:swal2-show .3s;animation:swal2-show .3s}.swal2-show.swal2-noanimation{-webkit-animation:none;animation:none}.swal2-hide{-webkit-animation:swal2-hide .15s forwards;animation:swal2-hide .15s forwards}.swal2-hide.swal2-noanimation{-webkit-animation:none;animation:none}.swal2-rtl .swal2-close{right:auto;left:0}.swal2-animate-success-icon .swal2-success-line-tip{-webkit-animation:swal2-animate-success-line-tip .75s;animation:swal2-animate-success-line-tip .75s}.swal2-animate-success-icon .swal2-success-line-long{-webkit-animation:swal2-animate-success-line-long .75s;animation:swal2-animate-success-line-long .75s}.swal2-animate-success-icon .swal2-success-circular-line-right{-webkit-animation:swal2-rotate-success-circular-line 4.25s ease-in;animation:swal2-rotate-success-circular-line 4.25s ease-in}.swal2-animate-error-icon{-webkit-animation:swal2-animate-error-icon .5s;animation:swal2-animate-error-icon .5s}.swal2-animate-error-icon .swal2-x-mark{-webkit-animation:swal2-animate-error-x-mark .5s;animation:swal2-animate-error-x-mark .5s}@-webkit-keyframes swal2-rotate-loading{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes swal2-rotate-loading{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media print{body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow-y:scroll!important}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown)>[aria-hidden=true]{display:none}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) .swal2-container{position:static!important}} 2 | 3 | --------------------------------------------------------------------------------