├── public ├── .gitkeep └── assets │ ├── js │ ├── app.js │ ├── bootstrap.min.js │ └── selectize.min.js │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff │ └── css │ ├── style.css │ ├── selectize.css │ └── selectize.bootstrap3.css ├── src ├── seeds │ ├── .gitkeep │ ├── PackageCapabilityRolePivotSeeder.php │ ├── PackageRoleUserPivotSeeder.php │ ├── PackageDatabaseSeeder.php │ ├── PackageRolesTableSeeder.php │ ├── PackageCapabilitiesTableSeeder.php │ └── PackageUsersTableSeeder.php ├── views │ ├── .gitkeep │ ├── partials │ │ ├── user │ │ │ ├── search-form.blade.php │ │ │ ├── list.blade.php │ │ │ ├── add.blade.php │ │ │ └── edit.blade.php │ │ ├── sidebar.blade.php │ │ ├── role │ │ │ ├── list.blade.php │ │ │ ├── add.blade.php │ │ │ └── edit.blade.php │ │ └── capability │ │ │ ├── list.blade.php │ │ │ ├── add.blade.php │ │ │ └── edit.blade.php │ └── layout │ │ └── master.blade.php ├── config │ ├── .gitkeep │ └── config.php ├── migrations │ ├── .gitkeep │ ├── 2014_07_31_165825_create_roles_table.php │ ├── 2014_07_31_165858_create_capabilities_table.php │ ├── 2014_07_31_165747_create_users_table.php │ ├── 2014_07_31_171932_create_role_user_table.php │ └── 2014_07_31_171949_create_capability_role_table.php └── Usman │ └── Guardian │ ├── Repositories │ ├── Interfaces │ │ ├── RoleRepositoryInterface.php │ │ ├── UserRepositoryInterface.php │ │ ├── CapabilityRepositoryInterface.php │ │ └── BaseRepositoryInterface.php │ ├── Providers │ │ ├── RoleRepositoryServiceProvider.php │ │ ├── CapabilityRepositoryServiceProvider.php │ │ └── UserRepositoryServiceProvider.php │ ├── RoleRepository.php │ ├── CapabilityRepository.php │ ├── UserRepository.php │ └── BaseRepository.php │ ├── Http │ ├── Controllers │ │ ├── Base.php │ │ ├── Roles.php │ │ ├── Capabilities.php │ │ └── Users.php │ └── routes.php │ ├── AccessControl │ ├── InvalidUserInstanceException.php │ ├── GuardianFacade.php │ ├── GuardianServiceProvider.php │ ├── AccessControlInterface.php │ ├── AccessControlTrait.php │ └── Guardian.php │ ├── Validators │ ├── RoleValidator.php │ ├── CapabilityValidator.php │ ├── Interfaces │ │ └── BaseValidatorInterface.php │ ├── Exceptions │ │ └── ValidationException.php │ ├── UserValidator.php │ └── BaseValidator.php │ ├── Composers │ ├── RoleOptionsComposer.php │ ├── CapabilityOptionsComposer.php │ └── ComposersServiceProvider.php │ └── GuardianServiceProvider.php ├── tests ├── .gitkeep ├── GuardianTestCase.php └── Integration │ ├── ValidatorTest.php │ ├── GuardianFacadeTest.php │ └── RepositoryTest.php ├── .gitignore ├── screenshots ├── main-scr.png └── backend-scr.png ├── .travis.yml ├── phpunit.xml ├── composer.json ├── LICENSE └── README.md /public/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/seeds/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/config/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /screenshots/main-scr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usm4n/guardian/HEAD/screenshots/main-scr.png -------------------------------------------------------------------------------- /screenshots/backend-scr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usm4n/guardian/HEAD/screenshots/backend-scr.png -------------------------------------------------------------------------------- /public/assets/js/app.js: -------------------------------------------------------------------------------- 1 | (function($){ 2 | $('#roles,#capabilities,#role').selectize({ 3 | sortField: 'text' 4 | }); 5 | })(jQuery); 6 | -------------------------------------------------------------------------------- /public/assets/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usm4n/guardian/HEAD/public/assets/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/assets/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usm4n/guardian/HEAD/public/assets/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/assets/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usm4n/guardian/HEAD/public/assets/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/config/config.php: -------------------------------------------------------------------------------- 1 | 'App\User', 4 | 'roleModel' => 'App\Role', 5 | 'capabilityModel' => 'App\Capability', 6 | ]; -------------------------------------------------------------------------------- /src/Usman/Guardian/Repositories/Interfaces/RoleRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | capabilities()->withTimeStamps()->attach([1,2]); 12 | $role::find(2)->capabilities()->withTimeStamps()->attach(3); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/seeds/PackageRoleUserPivotSeeder.php: -------------------------------------------------------------------------------- 1 | roles()->withTimeStamps()->attach([1,2]); 12 | $user::find(2)->roles()->withTimeStamps()->attach(3); 13 | $user::find(3)->roles()->withTimeStamps()->attach(1); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Validators/RoleValidator.php: -------------------------------------------------------------------------------- 1 | [ 12 | 'role_name' => 'required|alpha|unique:roles,role_name', 13 | 'description' => 'regex:/^[a-zA-Z ]+$/' 14 | ], 15 | 'update' => [ 16 | 'description' => 'regex:/^[a-zA-Z ]+$/' 17 | ] 18 | ]; 19 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Validators/CapabilityValidator.php: -------------------------------------------------------------------------------- 1 | [ 12 | 'capability' => 'required|alpha_dash|unique:capabilities,capability', 13 | 'description' => 'regex:/^[a-zA-Z ]+$/' 14 | ], 15 | 'update' => [ 16 | 'description' => 'regex:/^[a-zA-Z ]+$/' 17 | ] 18 | ]; 19 | } -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/seeds/PackageDatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call('PackageUsersTableSeeder'); 18 | $this->call('PackageRolesTableSeeder'); 19 | $this->call('PackageCapabilitiesTableSeeder'); 20 | $this->call('PackageRoleUserPivotSeeder'); 21 | $this->call('PackageCapabilityRolePivotSeeder'); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/Usman/Guardian/Repositories/Providers/RoleRepositoryServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind('Usman\Guardian\Repositories\Interfaces\RoleRepositoryInterface',function() 17 | { 18 | $role = config('guardian.roleModel'); 19 | return new RoleRepository(new $role); 20 | }); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Repositories/RoleRepository.php: -------------------------------------------------------------------------------- 1 | model->role_name = (!empty($data['role_name'])) ? ucfirst($data['role_name']) : $this->model->role_name; 16 | $this->model->description = (!empty($data['description'])) ? $data['description'] : $this->model->description; 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /tests/GuardianTestCase.php: -------------------------------------------------------------------------------- 1 | 'usm4n/guardian']); 23 | Artisan::call('db:seed',['--class'=>'PackageDatabaseSeeder']); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/Usman/Guardian/Repositories/CapabilityRepository.php: -------------------------------------------------------------------------------- 1 | model->capability = (!empty($data['capability'])) ? $data['capability'] : $this->model->capability; 16 | $this->model->description = (!empty($data['description'])) ? $data['description'] : $this->model->description; 17 | 18 | } 19 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Repositories/Providers/CapabilityRepositoryServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind('Usman\Guardian\Repositories\Interfaces\CapabilityRepositoryInterface',function() 16 | { 17 | $capability = config('guardian.capabilityModel'); 18 | return new CapabilityRepository(new $capability); 19 | }); 20 | } 21 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Repositories/Providers/UserRepositoryServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind('Usman\Guardian\Repositories\Interfaces\UserRepositoryInterface',function() 17 | { 18 | $user = config('guardian.userModel'); 19 | return new UserRepository(new $user); 20 | }); 21 | 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /public/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* overrides */ 2 | @media (min-width: 1200px) { 3 | .container { 4 | width: 970px; 5 | } 6 | } 7 | 8 | #header .jumbotron { 9 | margin-bottom: 15px; 10 | } 11 | 12 | #header h1 { 13 | font-size: 36px; 14 | } 15 | 16 | .heading { 17 | text-align: center; 18 | font-size: 18px; 19 | font-weight: normal; 20 | margin: 3px 0; 21 | padding: 10px 0; 22 | border-top: 3px solid rgb(122,98,211); 23 | color: rgb(51, 51, 51); 24 | background-color: rgb(245, 245, 245); 25 | } 26 | 27 | footer { 28 | height: 50px; 29 | color: #fff; 30 | margin: 30px 0 7px 0; 31 | padding: 7px; 32 | background-color: rgb(122,98,211); 33 | } 34 | footer a{ 35 | color: #fff; 36 | text-decoration: underline; 37 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Validators/Interfaces/BaseValidatorInterface.php: -------------------------------------------------------------------------------- 1 | validationErrors = $errors; 22 | } 23 | 24 | /** 25 | * Gets the validation errors. 26 | * 27 | * @return \Illuminate\Support\MessageBag 28 | */ 29 | public function getValidationErrors() 30 | { 31 | return $this->validationErrors; 32 | } 33 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "usm4n/guardian", 3 | "description": "Role Based Access Control Package For Laravel With Backend Interface", 4 | "keywords": ["rbac", "permissions", "access control", "RBAC laravel", "roles"], 5 | "license" : "MIT", 6 | "authors": [ 7 | { 8 | "name": "Usman Riaz", 9 | "email": "usmanri4z@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.4.0", 14 | "illuminate/support": "5.0.x", 15 | "illuminate/html": "~5.0" 16 | }, 17 | "autoload": { 18 | "classmap": [ 19 | "src/migrations", 20 | "src/seeds", 21 | "./tests" 22 | ], 23 | "psr-0": { 24 | "Usman\\Guardian": "src/" 25 | } 26 | }, 27 | "minimum-stability": "stable" 28 | } 29 | -------------------------------------------------------------------------------- /src/migrations/2014_07_31_165825_create_roles_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('role_name'); 19 | $table->string('description')->nullable(); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('roles'); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/Usman/Guardian/Validators/UserValidator.php: -------------------------------------------------------------------------------- 1 | [ 12 | 'username' => 'required|alpha_num|unique:users,username', 13 | 'password' => 'required|between:8,20|confirmed', 14 | 'email' => 'required|email', 15 | 'roles' => 'array|exists:roles,id', 16 | 'active' => 'in:1,0' 17 | ], 18 | 'update' => [ 19 | 'password' => 'between:8,20|confirmed', 20 | 'email' => 'required|email', 21 | 'roles' => 'array|exists:roles,id', 22 | 'active' => 'in:1,0' 23 | ] 24 | ]; 25 | } -------------------------------------------------------------------------------- /src/migrations/2014_07_31_165858_create_capabilities_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('capability'); 19 | $table->string('description')->nullable(); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('capabilities'); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/Usman/Guardian/Composers/RoleOptionsComposer.php: -------------------------------------------------------------------------------- 1 | role = $role; 22 | } 23 | 24 | /** 25 | * Binds the role options to the view 26 | * 27 | * @param View $view 28 | * @return void 29 | */ 30 | public function compose($view) 31 | { 32 | $view->roles = $this->role->getAll(['id','role_name']); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Composers/CapabilityOptionsComposer.php: -------------------------------------------------------------------------------- 1 | capability = $capability; 22 | } 23 | 24 | /** 25 | * Binds the capability options data to the view. 26 | * 27 | * @param View $view 28 | * @return void 29 | */ 30 | public function compose($view) 31 | { 32 | $view->capabilities = $this->capability->getAll(['id','capability']); 33 | } 34 | } -------------------------------------------------------------------------------- /src/migrations/2014_07_31_165747_create_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('username'); 19 | $table->string('password'); 20 | $table->string('email'); 21 | $table->boolean('active')->default(false); 22 | $table->string('remember_token',100)->nullable(); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('users'); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/seeds/PackageRolesTableSeeder.php: -------------------------------------------------------------------------------- 1 | 'Administrator', 12 | 'description' => 'Site Admin', 13 | ], 14 | [ 15 | 'role_name' => 'Editor', 16 | 'description' => 'News Editor and Publisher', 17 | 18 | ], 19 | [ 20 | 'role_name' => 'Reporter', 21 | 'description' => 'News Reporter', 22 | ], 23 | [ 24 | 'role_name' => 'Subscriber', 25 | 'description' => 'News Subscriber', 26 | ] 27 | ]; 28 | 29 | $role = config('guardian.roleModel'); 30 | 31 | foreach($seeds as $seed) 32 | { 33 | $role::create($seed); 34 | } 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /src/views/partials/user/search-form.blade.php: -------------------------------------------------------------------------------- 1 |

Search Options

2 | {!!app('form')->open(['method'=>'GET','route'=>['user.list'],'class'=>'form form-horizontal','style'=>'margin-top:10px;'])!!} 3 |
4 | {!! app('form')->label('role','Select a Role:',['class'=>'col-sm-3 control-label']) !!} 5 |
6 | {!! app('form')->select('role',$roles->lists('role_name','role_name'),Input::get('role')) !!} 7 |
8 |
9 |
10 | {!! app('form')->label('username','Username:',['class'=>'col-sm-3 control-label']) !!} 11 |
12 | {!! app('form')->text('username',Input::get('username'),['class'=>'form-control','placeholder'=>'Username Keyword...']) !!} 13 |
14 | {!!app('form')->submit('Search',['class'=>'btn btn-default'])!!} 15 | {!!app('html')->link(URL::route('user.list'), 'Cancel',['class'=>'btn btn-warning'])!!} 16 |
17 | {!!app('form')->close()!!} 18 | 19 | -------------------------------------------------------------------------------- /src/seeds/PackageCapabilitiesTableSeeder.php: -------------------------------------------------------------------------------- 1 | 'create_user', 12 | 'description' => 'Capability to create users' 13 | ], 14 | [ 15 | 'capability' => 'delete_user', 16 | 'description' => 'Capability to delete users' 17 | ], 18 | [ 19 | 'capability' => 'edit_user', 20 | 'description' => 'Capability to edit users' 21 | ], 22 | [ 23 | 'capability' => 'manage_users', 24 | 'description' => 'Capability to manage all users' 25 | ], 26 | ]; 27 | 28 | $capability = config('guardian.capabilityModel'); 29 | 30 | foreach($seeds as $seed) 31 | { 32 | $capability::create($seed); 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/migrations/2014_07_31_171932_create_role_user_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('role_id')->unsigned()->index(); 19 | //$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); 20 | $table->integer('user_id')->unsigned()->index(); 21 | //$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::drop('role_user'); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/migrations/2014_07_31_171949_create_capability_role_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('capability_id')->unsigned()->index(); 19 | //$table->foreign('capability_id')->references('id')->on('capabilities')->onDelete('cascade'); 20 | $table->integer('role_id')->unsigned()->index(); 21 | //$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::drop('capability_role'); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Usman Riaz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Usman/Guardian/AccessControl/GuardianServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bindShared('guardian',function($app) 16 | { 17 | return new Guardian($app['auth']); 18 | }); 19 | 20 | /*$this->app->booting(function() //registers a boot listener... should better go in boot(). 21 | { 22 | $loader = AliasLoader::getInstance(); 23 | $loader->alias('Guardian','Usman\Guardian\AccessControl\GuardianFacade'); 24 | });*/ 25 | } 26 | 27 | /** 28 | * Adds an alias for the GuardianFacade 29 | * 30 | * @return void 31 | */ 32 | public function boot() 33 | { 34 | $loader = AliasLoader::getInstance(); 35 | $loader->alias('Guardian','Usman\Guardian\AccessControl\GuardianFacade'); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/seeds/PackageUsersTableSeeder.php: -------------------------------------------------------------------------------- 1 | 'riaz', 13 | 'password' => Hash::make('pass123'), 14 | 'email' => 'xyz@xyz.com' 15 | ], 16 | [ 17 | 'username' => 'noman', 18 | 'password' => Hash::make('pass123'), 19 | 'email' => 'xyz@xyz.com' 20 | ], 21 | [ 22 | 'username' => 'affan', 23 | 'password' => Hash::make('pass123'), 24 | 'email' => 'xyz@xyz.com' 25 | ], 26 | [ 27 | 'username' => 'user123', 28 | 'password' => Hash::make('pass123'), 29 | 'email' => 'xyz@xyz.com' 30 | ] 31 | ]; 32 | 33 | $user = config('guardian.userModel'); 34 | 35 | foreach ($seeds as $seed) 36 | { 37 | $user::create($seed); 38 | } 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Composers/ComposersServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->view->composers([ 15 | 'Usman\Guardian\Composers\RoleOptionsComposer' => [ 16 | 'guardian::partials.user.add', 17 | 'guardian::partials.user.edit', 18 | 'guardian::partials.user.search-form', 19 | 'guardian::partials.capability.add', 20 | 'guardian::partials.capability.edit' 21 | ], 22 | 'Usman\Guardian\Composers\CapabilityOptionsComposer' => [ 23 | 'guardian::partials.role.add', 24 | 'guardian::partials.role.edit' 25 | ] 26 | ]); 27 | } 28 | 29 | /** 30 | * Register the service provider. 31 | * 32 | * @return void 33 | */ 34 | public function register() 35 | { 36 | // 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/Usman/Guardian/AccessControl/AccessControlInterface.php: -------------------------------------------------------------------------------- 1 | 2 |

Users

3 | 11 |

Roles

12 | 20 |

Capabilities

21 | 29 | -------------------------------------------------------------------------------- /src/views/layout/master.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Guardian: RBAC Mangement Package For Laravel 7 | {!!app('html')->style('packages/usm4n/guardian/assets/css/bootstrap.css')!!} 8 | {!!app('html')->style('packages/usm4n/guardian/assets/css/style.css')!!} 9 | {!!app('html')->style('packages/usm4n/guardian/assets/css/selectize.bootstrap3.css')!!} 10 | 11 | 12 |
13 | 19 |
20 | 23 |
24 | @yield('content') 25 |
26 |
27 |
28 |
29 | 34 |
35 |
36 |
37 | {!! app('html')->script('packages/usm4n/guardian/assets/js/jquery.js') !!} 38 | {!! app('html')->script('packages/usm4n/guardian/assets/js/selectize.min.js') !!} 39 | {!! app('html')->script('packages/usm4n/guardian/assets/js/bootstrap.min.js') !!} 40 | {!! app('html')->script('packages/usm4n/guardian/assets/js/app.js') !!} 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/Usman/Guardian/Repositories/UserRepository.php: -------------------------------------------------------------------------------- 1 | model->query(); 20 | 21 | if( ! empty($username)) 22 | { 23 | $query->where('username','LIKE','%'.$username.'%'); 24 | } 25 | 26 | if( ! empty($role)) 27 | { 28 | $query->whereHas('roles',function($query) use ($role) 29 | { 30 | $query->where('role_name','=',$role); 31 | }); 32 | } 33 | 34 | return $query->with('roles')->paginate($perPage); 35 | } 36 | 37 | /** 38 | * fills the user model data 39 | * 40 | * @param array $data 41 | * @return void 42 | */ 43 | protected function fillData(array $data) 44 | { 45 | $this->model->username = (!empty($data['username'])) ? $data['username'] : $this->model->username; 46 | $this->model->password = (!empty($data['password'])) ? Hash::make($data['password']) : $this->model->password; 47 | $this->model->email = (!empty($data['email'])) ? $data['email'] : $this->model->email; 48 | $this->model->active = $data['active']; 49 | } 50 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Repositories/Interfaces/BaseRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | Role List 5 | @if(Session::has('success')) 6 |
7 |

{{Session::get('success')}}

8 |
9 | @endif 10 | @if($roles->isEmpty()) 11 |

No Records Found.

12 | @else 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | @foreach($roles as $role) 25 | 26 | 27 | 28 | 29 | 30 | 41 | 42 | @endforeach 43 | 44 |
IdRole NameDescriptionCapabilitiesOperations
{{$role->id}}{{$role->role_name}}{{$role->description}}{{$role->capabilities->implode('capability',', ') ? : 'N/A'}} 31 |
32 | 35 | 39 |
40 |
45 |
46 | {!!$roles->render()!!} 47 |
48 | @endif 49 | @stop -------------------------------------------------------------------------------- /tests/Integration/ValidatorTest.php: -------------------------------------------------------------------------------- 1 | prepareDB(); 11 | $this->validator = $this->app->make('Usman\Guardian\Validators\UserValidator'); 12 | } 13 | 14 | public function test_successfull_validation_on_create() 15 | { 16 | $valid = $this->validator->setFields($this->userValidData())->validate('create'); 17 | 18 | $this->assertTrue($valid); 19 | } 20 | 21 | /** 22 | * @expectedException Usman\Guardian\Validators\Exceptions\ValidationException 23 | */ 24 | public function test_failed_validation_on_create() 25 | { 26 | $this->validator->setFields($this->userInValidData())->validate('create'); 27 | } 28 | 29 | public function test_successfull_validation_on_update() 30 | { 31 | $valid = $this->validator->setFields($this->userValidData())->validate('update'); 32 | 33 | $this->assertTrue($valid); 34 | } 35 | 36 | /** 37 | * @expectedException Usman\Guardian\Validators\Exceptions\ValidationException 38 | */ 39 | public function test_failed_validation_on_update() 40 | { 41 | $this->validator->setFields($this->userInValidData())->validate('update'); 42 | } 43 | 44 | 45 | protected function userValidData() 46 | { 47 | return [ 48 | 'username'=>'newuser', 49 | 'password' => 'pass12346', 50 | 'password_confirmation' => 'pass12346', 51 | 'email' => 'xyz@xyz.com', 52 | 'active' => 1 53 | ]; 54 | } 55 | 56 | protected function userInValidData() 57 | { 58 | return [ 59 | 'username'=>'noman', 60 | 'password' => 'pass123', 61 | 'email' => 'xyz', 62 | 'active' => 'active' 63 | ]; 64 | } 65 | } -------------------------------------------------------------------------------- /src/views/partials/capability/list.blade.php: -------------------------------------------------------------------------------- 1 | @extends('guardian::layout.master') 2 | 3 | @section('content') 4 |

Capability List

5 | @if(Session::has('success')) 6 |
7 |

{{Session::get('success')}}

8 |
9 | @endif 10 | @if($capabilities->isEmpty()) 11 |

No Records Found.

12 | @else 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | @foreach($capabilities as $capability) 25 | 26 | 27 | 28 | 29 | 30 | 41 | 42 | @endforeach 43 | 44 |
IdCapability NameDescriptionAttached RolesOperations
{{$capability->id}}{{$capability->capability}}{{$capability->description}}{{$capability->roles->implode('role_name',', ') ? : 'N/A'}} 31 |
32 | 35 | 39 |
40 |
45 |
46 | {{$capabilities->render()}} 47 |
48 | @endif 49 | @stop -------------------------------------------------------------------------------- /src/views/partials/capability/add.blade.php: -------------------------------------------------------------------------------- 1 | @extends('guardian::layout.master') 2 | 3 | @section('content') 4 |

Add New Capability

5 | @if(Session::has('success')) 6 |
7 |

{{Session::get('success')}}

8 |
9 | @endif 10 | {!!app('form')->open(['route'=>['capability.create'],'class'=>'form form-horizontal','style'=>'margin-top:50px'])!!} 11 |
12 | {!! app('form')->label('capability','Capability Name:',['class'=>'col-sm-3 control-label']) !!} 13 |
14 | {{$errors->first('capability')}} 15 | {!! app('form')->text('capability',Input::old('capability'),['class'=>'form-control','placeholder'=>'format: resource_action|manage_resource etc']) !!} 16 |
17 |
18 |
19 | {!! app('form')->label('description','Description:',['class'=>'col-sm-3 control-label']) !!} 20 |
21 | {{$errors->first('description')}} 22 | {!! app('form')->text('description',Input::old('description'),['class'=>'form-control','placeholder'=>'only alpha chars allowed...']) !!} 23 |
24 |
25 |
26 | {!!app('form')->label('roles','Attach to Roles:',['class'=>'col-sm-3 control-label'])!!} 27 |
28 | @if($roles->isEmpty()) 29 | {!!app('form')->text('fake',null,['class'=>'form-control','placeholder'=>'Create Some Roles First!','disabled'])!!} 30 | @else 31 | {!!app('form')->select('roles',$roles->lists('role_name','id'),Input::old('roles'),['name'=>'roles[]','multiple'])!!} 32 | @endif 33 |
34 |
35 |
36 | {!!app('form')->submit('Create Capability',['class'=>'btn btn-default'])!!} 37 |
38 | {!!app('form')->close()!!} 39 | @stop -------------------------------------------------------------------------------- /src/views/partials/role/add.blade.php: -------------------------------------------------------------------------------- 1 | @extends('guardian::layout.master') 2 | 3 | @section('content') 4 |

Add New Role

5 | @if(Session::has('success')) 6 |
7 |

{{Session::get('success')}}

8 |
9 | @endif 10 | {!!app('form')->open(['route'=>['role.create'],'class'=>'form form-horizontal','style'=>'margin-top:50px'])!!} 11 |
12 | {!! app('form')->label('role_name','Role Name:',['class'=>'col-sm-3 control-label']) !!} 13 |
14 | {{$errors->first('role_name')}} 15 | {!! app('form')->text('role_name',Input::old('role_name'),['class'=>'form-control','placeholder'=>'only alpha chars allowed...']) !!} 16 |
17 |
18 |
19 | {!! app('form')->label('description','Role Description:',['class'=>'col-sm-3 control-label']) !!} 20 |
21 | {{$errors->first('description')}} 22 | {!! app('form')->text('description',Input::old('description'),['class'=>'form-control','placeholder'=>'only alpha chars allowed...']) !!} 23 |
24 |
25 |
26 | {!! app('form')->label('capabilities','Attach Capabilities:',['class'=>'col-sm-3 control-label']) !!} 27 |
28 | @if($capabilities->isEmpty()) 29 | {!!app('form')->text('fake',null,['class'=>'form-control','placeholder'=>'Create Some Capabilities First!','disabled'])!!} 30 | @else 31 | {!! app('form')->select('capabilities',$capabilities->lists('capability','id'),Input::old('capabilities'),['name'=>'capabilities[]','multiple']) !!} 32 | @endif 33 |
34 |
35 |
36 | {!!app('form')->submit('Create Role',['class'=>'btn btn-default'])!!} 37 |
38 | {!!app('form')->close()!!} 39 | @stop -------------------------------------------------------------------------------- /src/Usman/Guardian/Validators/BaseValidator.php: -------------------------------------------------------------------------------- 1 | validator = $validator; 38 | } 39 | 40 | /** 41 | * Validates the data. 42 | * 43 | * @param string $type type of validation create/update. 44 | * @throws ValidationException 45 | * @return boolean 46 | */ 47 | public function validate($type) 48 | { 49 | $v = $this->validator->make($this->fields,$this->rules[$type]); 50 | 51 | if($v->fails()) 52 | { 53 | throw new ValidationException($v->errors()); 54 | } 55 | else 56 | { 57 | return true; 58 | } 59 | } 60 | 61 | /** 62 | * Sets the fields to be validated. 63 | * 64 | * @param array $fields 65 | */ 66 | public function setFields(array $fields) 67 | { 68 | $this->fields = $fields; 69 | return $this; 70 | } 71 | 72 | /** 73 | * Adds additional rules for data validation. 74 | * 75 | * @param string $type 76 | * @param string $field 77 | * @param string $rule 78 | */ 79 | public function addRule($type, $field, $rule) 80 | { 81 | $this->rules[$type][$field] = $rule; 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /src/views/partials/user/list.blade.php: -------------------------------------------------------------------------------- 1 | @extends('guardian::layout.master') 2 | 3 | @section('content') 4 | @include('guardian::partials.user.search-form') 5 |

User List

6 | @if(Session::has('success')) 7 |
8 |

{{Session::get('success')}}

9 |
10 | @endif 11 | @if($users->isEmpty()) 12 |

No Records Found.

13 | @else 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | @foreach($users as $user) 27 | 28 | 29 | 30 | 31 | 32 | 33 | 44 | 45 | @endforeach 46 | 47 |
IdUsernameEmailRolesActiveOperations
{{$user->id}}{{$user->username}}{{$user->email}}{{$user->roles->implode('role_name',', ') ? : 'N/A'}}{{$user->active ? 'Yes' : 'No' }} 34 |
35 | 38 | 42 |
43 |
48 |
49 | {!!$users->render()!!} 50 |
51 | @endif 52 | @stop -------------------------------------------------------------------------------- /src/views/partials/role/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('guardian::layout.master') 2 | 3 | @section('content') 4 |

Edit Role

5 | @if(Session::has('success')) 6 |
7 |

{{Session::get('success')}}

8 |
9 | @endif 10 | {!!app('form')->open(['route'=>['role.update',$role->id,'ref'=>Request::get('ref')],'class'=>'form form-horizontal','style'=>'margin-top:50px'])!!} 11 |
12 | {!! app('form')->label('role_name','Role Name:',['class'=>'col-sm-3 control-label']) !!} 13 |
14 | {{$errors->first('role_name')}} 15 | {!! app('form')->text('role_name',Input::old('role_name',$role->role_name),['class'=>'form-control','placeholder'=>'only alpha chars allowed...']) !!} 16 |
17 |
18 |
19 | {!! app('form')->label('description','Role Description:',['class'=>'col-sm-3 control-label']) !!} 20 |
21 | {{$errors->first('description')}} 22 | {!! app('form')->text('description',Input::old('description',$role->description),['class'=>'form-control','placeholder'=>'only alpha chars allowed...']) !!} 23 |
24 |
25 |
26 | {!! app('form')->label('capabilities','Attach Capabilities:',['class'=>'col-sm-3 control-label']) !!} 27 |
28 | @if($capabilities->isEmpty()) 29 | {!!app('form')->text('fake',null,['class'=>'form-control','placeholder'=>'Create Some Capabilities First!','disabled'])!!} 30 | @else 31 | {!! app('form')->select('capabilities',$capabilities->lists('capability','id'),Input::old('capabilities',$role->capabilities->lists('id')),['name'=>'capabilities[]','multiple']) !!} 32 | @endif 33 |
34 |
35 |
36 | {!!app('html')->link(URL::route('role.list',Input::get('ref')), 'Back',['class'=>'btn btn-warning'])!!} 37 | {!!app('form')->submit('Update Role',['class'=>'btn btn-default'])!!} 38 |
39 | {!!app('form')->close()!!} 40 | @stop -------------------------------------------------------------------------------- /src/views/partials/capability/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('guardian::layout.master') 2 | 3 | @section('content') 4 |

Edit Capability

5 | @if(Session::has('success')) 6 |
7 |

{{Session::get('success')}}

8 |
9 | @endif 10 | {!!app('form')->open(['route'=>['capability.update',$capability->id,'ref'=>Request::get('ref')],'class'=>'form form-horizontal','style'=>'margin-top:50px'])!!} 11 |
12 | {!! app('form')->label('capability','Capability Name:',['class'=>'col-sm-3 control-label']) !!} 13 |
14 | {{$errors->first('capability')}} 15 | {!! app('form')->text('capability',Input::old('capability',$capability->capability),['class'=>'form-control','placeholder'=>'format: resource_action|manage_resource etc']) !!} 16 |
17 |
18 |
19 | {!! app('form')->label('description','Description:',['class'=>'col-sm-3 control-label']) !!} 20 |
21 | {{$errors->first('description')}} 22 | {!! app('form')->text('description',Input::old('description',$capability->description),['class'=>'form-control','placeholder'=>'only alpha chars allowed...']) !!} 23 |
24 |
25 |
26 | {!!app('form')->label('roles','Attach to Roles:',['class'=>'col-sm-3 control-label'])!!} 27 |
28 | @if($roles->isEmpty()) 29 | {!!app('form')->text('fake',null,['class'=>'form-control','placeholder'=>'Create Some Roles First!','disabled'])!!} 30 | @else 31 | {!!app('form')->select('roles',$roles->lists('role_name','id'),Input::old('roles',$capability->roles->lists('id')),['name'=>'roles[]','multiple'])!!} 32 | @endif 33 |
34 |
35 |
36 | {!!app('html')->link(URL::route('capability.list',Input::get('ref')), 'Back',['class'=>'btn btn-warning'])!!} 37 | {!!app('form')->submit('Update Capability',['class'=>'btn btn-default'])!!} 38 |
39 | {!!app('form')->close()!!} 40 | @stop -------------------------------------------------------------------------------- /src/Usman/Guardian/Http/routes.php: -------------------------------------------------------------------------------- 1 | 'guardian/backend', 5 | 'namespace'=>'Usman\Guardian\Http\Controllers', 6 | 'middleware' => 'auth' 7 | ], 8 | function() 9 | { 10 | Route::get('/',function() 11 | { 12 | return \Redirect::to('guardian/backend/user/list'); 13 | }); 14 | 15 | Route::group(['prefix'=>'user'],function() 16 | { 17 | //get user routes. 18 | Route::get('/list',['as'=>'user.list','uses'=>'Users@listUser']); 19 | Route::get('/add',['as'=>'user.add','uses'=>'Users@addUser']); 20 | Route::get('/edit/{id}',['as'=>'user.edit','uses'=>'Users@editUser']); 21 | Route::get('/delete/{id}',['as'=>'user.delete','uses'=>'Users@deleteUser']); 22 | 23 | //post user routes 24 | Route::post('/create',['as'=>'user.create','uses'=>'Users@createUser']); 25 | Route::post('/update/{id}',['as'=>'user.update','uses'=>'Users@updateUser']); 26 | 27 | }); 28 | 29 | Route::group(['prefix'=>'role'],function() 30 | { 31 | //get role routes. 32 | Route::get('/list',['as'=>'role.list','uses'=>'Roles@listRole']); 33 | Route::get('/add',['as'=>'role.add','uses'=>'Roles@addRole']); 34 | Route::get('/edit/{id}',['as'=>'role.edit','uses'=>'Roles@editRole']); 35 | Route::get('/delete/{id}',['as'=>'role.delete','uses'=>'Roles@deleteRole']); 36 | 37 | //post role routes. 38 | Route::post('/create',['as'=>'role.create','uses'=>'Roles@createRole']); 39 | Route::post('/update/{id}',['as'=>'role.update','uses'=>'Roles@updateRole']); 40 | 41 | }); 42 | 43 | Route::group(['prefix'=>'capability'],function() 44 | { 45 | //get capability routes. 46 | Route::get('/list',['as'=>'capability.list','uses'=>'Capabilities@listCapability']); 47 | Route::get('/add',['as'=>'capability.add','uses'=>'Capabilities@addCapability']); 48 | Route::get('/edit/{id}',['as'=>'capability.edit','uses'=>'Capabilities@editCapability']); 49 | Route::get('/delete/{id}',['as'=>'capability.delete','uses'=>'Capabilities@deleteCapability']); 50 | 51 | //post routes. 52 | Route::post('/create',['as'=>'capability.create','uses'=>'Capabilities@createCapability']); 53 | Route::post('/update/{id}',['as'=>'capability.update','uses'=>'Capabilities@updateCapability']); 54 | 55 | }); 56 | }); 57 | 58 | -------------------------------------------------------------------------------- /tests/Integration/GuardianFacadeTest.php: -------------------------------------------------------------------------------- 1 | prepareDB(); 11 | $this->user = User::find(1); 12 | } 13 | 14 | public function test_has_role_when_logged_in() 15 | { 16 | $this->be($this->user); 17 | $status = Guardian::hasRole('administrator'); 18 | 19 | $this->assertTrue($status); 20 | } 21 | public function test_has_any_role_when_logged_in() 22 | { 23 | $this->be($this->user); 24 | $status = Guardian::hasAnyRole(['editor','reporter']); 25 | 26 | $this->assertTrue($status); 27 | } 28 | 29 | public function test_has_all_role_when_logged_in() 30 | { 31 | $this->be($this->user); 32 | $status = Guardian::hasAllRoles(['editor','reporter']); 33 | 34 | $this->assertFalse($status); 35 | } 36 | 37 | public function test_has_capability_when_logged_in() 38 | { 39 | $this->be($this->user); 40 | $status1 = Guardian::hasCapability('manage_users'); 41 | $status2 = Guardian::hasCapability('create_user'); 42 | 43 | $this->assertFalse($status1); 44 | $this->assertTrue($status2); 45 | } 46 | 47 | public function test_has_any_capability_when_logged_in() 48 | { 49 | $this->be($this->user); 50 | $status1 = Guardian::hasAnyCapability(['create_user','delete_user']); 51 | $status2 = Guardian::hasAnyCapability(['manage_users']); 52 | 53 | $this->assertTrue($status1); 54 | $this->assertFalse($status2); 55 | } 56 | 57 | public function test_has_all_capabilities_when_logged_in() 58 | { 59 | $this->be($this->user); 60 | $status1 = Guardian::hasAllCapabilities(['create_user','delete_user']); 61 | $status2 = Guardian::hasAllCapabilities(['manage_users,create_user']); 62 | 63 | $this->assertTrue($status1); 64 | $this->assertFalse($status2); 65 | } 66 | 67 | public function test_all_false_when_not_logged_in() 68 | { 69 | $this->assertFalse(Guardian::hasRole('editor')); 70 | $this->assertFalse(Guardian::hasAnyRole(['editor'])); 71 | $this->assertFalse(Guardian::hasAllRoles(['editor','reporter'])); 72 | $this->assertFalse(Guardian::hasCapability('create_user')); 73 | $this->assertFalse(Guardian::hasAnyCapability(['create_user','edit_user'])); 74 | $this->assertFalse(Guardian::hasAllCapabilities(['create_user','edit_user'])); 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /src/views/partials/user/add.blade.php: -------------------------------------------------------------------------------- 1 | @extends('guardian::layout.master') 2 | 3 | @section('content') 4 |

Add New User

5 | @if(Session::has('success')) 6 |
7 |

{{Session::get('success')}}

8 |
9 | @endif 10 | {!!app('form')->open(['route'=>['user.create'],'class'=>'form form-horizontal','style'=>'margin-top:50px'])!!} 11 |
12 | {!! app('form')->label('username','User Name:',['class'=>'col-sm-3 control-label']) !!} 13 |
14 | {{$errors->first('username')}} 15 | {!! app('form')->text('username',Input::old('username'),['class'=>'form-control']) !!} 16 |
17 |
18 |
19 | {!! app('form')->label('email','User Email:',['class'=>'col-sm-3 control-label']) !!} 20 |
21 | {{$errors->first('email')}} 22 | {!! app('form')->text('email',Input::old('email'),['class'=>'form-control']) !!} 23 |
24 |
25 |
26 | {!! app('form')->label('password','User Password:',['class'=>'col-sm-3 control-label']) !!} 27 |
28 | {{$errors->first('password')}} 29 | {!! app('form')->password('password',['class'=>'form-control']) !!} 30 |
31 |
32 |
33 | {!! app('form')->label('password_confirmation','Confirm Password:',['class'=>'col-sm-3 control-label']) !!} 34 |
35 | {{$errors->first('password_confirmation')}} 36 | {!! app('form')->password('password_confirmation',['class'=>'form-control']) !!} 37 |
38 |
39 |
40 | {!! app('form')->label('active','Set as active:',['class'=>'col-sm-3 control-label'])!!} 41 |
42 | {!! app('form')->select('active',['No','Yes'],Input::old('active',0),['class'=>'form-control'])!!} 43 |
44 |
45 |
46 | {!!app('form')->label('roles','Attach Roles:',['class'=>'col-sm-3 control-label'])!!} 47 |
48 | @if($roles->isEmpty()) 49 | {!!app('form')->text('fake',null,['class'=>'form-control','placeholder'=>'Create Some Roles First!','disabled'])!!} 50 | @else 51 | {!!app('form')->select('roles',$roles->lists('role_name','id'),Input::old('roles'),['name'=>'roles[]','multiple'])!!} 52 | @endif 53 |
54 |
55 |
56 | {!!app('form')->submit('Create User',['class'=>'btn btn-default'])!!} 57 |
58 | {!!app('form')->close()!!} 59 | @stop -------------------------------------------------------------------------------- /src/Usman/Guardian/AccessControl/AccessControlTrait.php: -------------------------------------------------------------------------------- 1 | belongsToMany(config('guardian.roleModel')); 13 | } 14 | 15 | /** 16 | * Checks for a role 17 | * 18 | * @param string $roleName 19 | * @return boolean 20 | */ 21 | public function hasRole($roleName) 22 | { 23 | foreach($this->roles as $role) 24 | { 25 | if(strtolower($role->role_name) == strtolower($roleName)) 26 | { 27 | return true; 28 | } 29 | } 30 | return false; 31 | } 32 | 33 | /** 34 | * Checks for any role 35 | * 36 | * @param array $roleNames 37 | * @return boolean 38 | */ 39 | public function hasAnyRole(array $roleNames) 40 | { 41 | foreach($roleNames as $roleName) 42 | { 43 | if($this->hasRole($roleName)) return true; 44 | } 45 | return false; 46 | } 47 | 48 | /** 49 | * Checks for all roles 50 | * 51 | * @param array $roleNames 52 | * @return boolean 53 | */ 54 | public function hasAllRoles(array $roleNames) 55 | { 56 | foreach($roleNames as $roleName) 57 | { 58 | if( ! $this->hasRole($roleName)) return false; 59 | } 60 | return true; 61 | } 62 | 63 | /** 64 | * Checks if a user has a capability 65 | * 66 | * @param string $capabilityName 67 | * @return boolean 68 | */ 69 | public function hasCapability($capabilityName) 70 | { 71 | foreach($this->roles as $role) 72 | { 73 | foreach($role->capabilities as $capability) 74 | { 75 | if(strtolower($capability->capability) == strtolower($capabilityName)) 76 | { 77 | return true; 78 | } 79 | } 80 | } 81 | return false; 82 | } 83 | 84 | /** 85 | * Checks if a user has any capability 86 | * 87 | * @param array $capabilityNames 88 | * @return boolean 89 | */ 90 | public function hasAnyCapability(array $capabilityNames) 91 | { 92 | foreach($capabilityNames as $capabilityName) 93 | { 94 | if($this->hasCapability($capabilityName)) return true; 95 | } 96 | return false; 97 | 98 | } 99 | 100 | /** 101 | * Checks if a user has all the capabilities 102 | * 103 | * @param array $capabilityNames 104 | * @return boolean 105 | */ 106 | public function hasAllCapabilities(array $capabilityNames) 107 | { 108 | foreach($capabilityNames as $capabilityName) 109 | { 110 | if( ! $this->hasCapability($capabilityName)) return false; 111 | } 112 | return true; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/views/partials/user/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('guardian::layout.master') 2 | 3 | @section('content') 4 |

Edit User

5 | @if(Session::has('success')) 6 |
7 |

{{Session::get('success')}}

8 |
9 | @endif 10 | {!!app('form')->open(['route'=>['user.update',$user->id,'ref'=>Request::get('ref')],'class'=>'form form-horizontal','style'=>'margin-top:50px'])!!} 11 |
12 | {!! app('form')->label('username','User Name:',['class'=>'col-sm-3 control-label']) !!} 13 |
14 | {{$errors->first('username')}} 15 | {!! app('form')->text('username',Input::old('username',$user->username),['class'=>'form-control']) !!} 16 |
17 |
18 |
19 | {!! app('form')->label('email','User Email:',['class'=>'col-sm-3 control-label']) !!} 20 |
21 | {{$errors->first('email')}} 22 | {!! app('form')->text('email',Input::old('email',$user->email),['class'=>'form-control']) !!} 23 |
24 |
25 |
26 | {!! app('form')->label('password','New Password:',['class'=>'col-sm-3 control-label']) !!} 27 |
28 | {{$errors->first('password')}} 29 | {!! app('form')->password('password',['class'=>'form-control']) !!} 30 |
31 |
32 |
33 | {!! app('form')->label('password_confirmation','Confirm Password:',['class'=>'col-sm-3 control-label']) !!} 34 |
35 | {{$errors->first('password_confirmation')}} 36 | {!! app('form')->password('password_confirmation',['class'=>'form-control']) !!} 37 |
38 |
39 |
40 | {!! app('form')->label('active','Set as active',['class'=>'col-sm-3 control-label']) !!} 41 |
42 | {!! app('form')->select('active',['No','Yes'],Input::old('active',$user->active),['class'=>'form-control']) !!} 43 |
44 |
45 |
46 | {!!app('form')->label('roles','Attach Roles:',['class'=>'col-sm-3 control-label'])!!} 47 |
48 | @if($roles->isEmpty()) 49 | {!!app('form')->text('fake',null,['class'=>'form-control','placeholder'=>'Create Some Roles First!','disabled'])!!} 50 | @else 51 | {!!app('form')->select('roles',$roles->lists('role_name','id'),Input::old('roles',$user->roles->lists('id')),['name'=>'roles[]','multiple'])!!} 52 | @endif 53 |
54 |
55 |
56 | {!!app('html')->link(URL::route('user.list',Input::get('ref')), 'Back',['class'=>'btn btn-warning'])!!} 57 | {!!app('form')->submit('Update User',['class'=>'btn btn-default'])!!} 58 |
59 | {!!app('form')->close()!!} 60 | @stop -------------------------------------------------------------------------------- /tests/Integration/RepositoryTest.php: -------------------------------------------------------------------------------- 1 | prepareDB(); 11 | $this->repo = $this->app->make('Usman\Guardian\Repositories\Interfaces\UserRepositoryInterface'); 12 | } 13 | 14 | public function test_find_by_id() 15 | { 16 | $data = $this->repo->findById(1); 17 | 18 | $this->assertEquals('riaz',$data->username); 19 | } 20 | 21 | public function test_find_by_id_with() 22 | { 23 | $data = $this->repo->findByIdWith(1,'roles'); 24 | 25 | $this->assertTrue( ! empty($data['relations'])); 26 | $this->assertInstanceOf('Illuminate\Support\Collection', $data->roles); 27 | 28 | } 29 | 30 | public function test_get_by_page_with() 31 | { 32 | $data = $this->repo->getByPageWith('roles'); 33 | 34 | $this->assertTrue( ! empty($data[0]['relations'])); 35 | $this->assertInstanceOf('Illuminate\Pagination\Paginator', $data); 36 | } 37 | 38 | public function test_get_all() 39 | { 40 | $data = $this->repo->getAll(); 41 | 42 | $this->assertInstanceOf('Illuminate\Support\Collection', $data); 43 | } 44 | 45 | public function test_create() 46 | { 47 | $id = $this->repo->create([ 48 | 'username'=>'user1', 49 | 'email'=>'xyz@xyz.com', 50 | 'password'=>'pass123', 51 | 'active'=>false 52 | ]); 53 | 54 | $this->assertInternalType('int', $id); 55 | } 56 | 57 | public function test_update() 58 | { 59 | $status = $this->repo->update(1,['username'=>'usman','active'=>1]); 60 | $data = $this->repo->findById(1); 61 | 62 | $this->assertTrue($status); 63 | $this->assertEquals('usman',$data->username); 64 | $this->assertEquals('1',$data->active); 65 | 66 | } 67 | 68 | public function test_attach() 69 | { 70 | $this->repo->attach(1,[1,3],'roles'); 71 | $data = $this->repo->findByIdWith(1,'roles'); 72 | 73 | $this->assertContains(3,$data->roles->modelKeys()); 74 | } 75 | 76 | public function test_delete_with() 77 | { 78 | $status = $this->repo->deleteWith(2,['roles']); 79 | $roles = DB::table('role_user')->whereUserId(2)->get(); 80 | 81 | $this->assertTrue($status); 82 | $this->assertEmpty($roles); 83 | } 84 | 85 | public function test_delete() 86 | { 87 | $this->assertTrue($this->repo->delete(4)); 88 | } 89 | 90 | public function test_search_user_by_role() 91 | { 92 | $data = $this->repo->searchUserByRole('an','Administrator'); 93 | 94 | $this->assertInstanceOf('Illuminate\Pagination\Paginator',$data); 95 | $this->assertRegExp('/an/', $data[0]->username); 96 | $this->assertContains('Administrator',$data[0]->roles->lists('role_name')); 97 | } 98 | 99 | /*public function tearDown() 100 | { 101 | Artisan::call('migrate:reset'); 102 | }*/ 103 | } 104 | -------------------------------------------------------------------------------- /src/Usman/Guardian/GuardianServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadAndPublishViews(); 22 | $this->publishAssets(); 23 | $this->publishConfig(); 24 | $this->publishMigrations(); 25 | 26 | //routes 27 | include __DIR__.'/Http/routes.php'; 28 | } 29 | 30 | /** 31 | * Register the service provider. 32 | * 33 | * @return void 34 | */ 35 | public function register() 36 | { 37 | $this->mergeConfiguration(); 38 | 39 | //register other providers 40 | $this->app->register('Usman\Guardian\Repositories\Providers\UserRepositoryServiceProvider'); 41 | $this->app->register('Usman\Guardian\Repositories\Providers\RoleRepositoryServiceProvider'); 42 | $this->app->register('Usman\Guardian\Repositories\Providers\CapabilityRepositoryServiceProvider'); 43 | $this->app->register('Usman\Guardian\AccessControl\GuardianServiceProvider'); 44 | $this->app->register('Usman\Guardian\Composers\ComposersServiceProvider'); 45 | } 46 | 47 | /** 48 | * loads and publishes the package view files 49 | * 50 | * @return void 51 | */ 52 | private function loadAndPublishViews() 53 | { 54 | $viewPath = __DIR__.'/../../views'; 55 | $this->loadViewsFrom($viewPath, 'guardian'); 56 | 57 | $this->publishes([ 58 | $viewPath => base_path('resources/views/vendor/guardian'), 59 | ],'guardian-views'); 60 | } 61 | 62 | /** 63 | * publishes the package assets 64 | * 65 | * @return void 66 | */ 67 | private function publishAssets() 68 | { 69 | $assetPath = __DIR__.'/../../../public'; 70 | $this->publishes([ 71 | $assetPath => public_path('packages/usm4n/guardian'), 72 | ], 'guardian-assets'); 73 | } 74 | 75 | /** 76 | * publishes the package config file 77 | * 78 | * @return void 79 | */ 80 | private function publishConfig() 81 | { 82 | $configPath = __DIR__.'/../../config/config.php'; 83 | $this->publishes([$configPath => config_path('guardian.php')], 'guardian-config'); 84 | } 85 | 86 | /** 87 | * publishes the package migration files 88 | * 89 | * @return void 90 | */ 91 | private function publishMigrations() 92 | { 93 | $migrationPath = __DIR__.'/../../migrations'; 94 | $this->publishes([$migrationPath => base_path('database/migrations')], 'guardian-migrations'); 95 | } 96 | 97 | /** 98 | * merges the package config with the app config 99 | * 100 | * @return void 101 | */ 102 | private function mergeConfiguration() 103 | { 104 | $configPath = __DIR__.'/../../config/config.php'; 105 | $this->mergeConfigFrom($configPath, 'guardian'); 106 | 107 | } 108 | 109 | /** 110 | * Get the services provided by the provider. 111 | * 112 | * @return array 113 | */ 114 | public function provides() 115 | { 116 | return array(); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/Usman/Guardian/AccessControl/Guardian.php: -------------------------------------------------------------------------------- 1 | auth = $auth; 34 | $this->init(); 35 | } 36 | 37 | /** 38 | * Checks for a role 39 | * 40 | * @param string $roleName 41 | * @return boolean 42 | */ 43 | public function hasRole($role) 44 | { 45 | if( ! $this->loggedIn) return false; 46 | 47 | return $this->user->hasRole($role); 48 | } 49 | 50 | /** 51 | * Checks for any role 52 | * 53 | * @param array $roleNames 54 | * @return boolean 55 | */ 56 | public function hasAnyRole(array $roleNames) 57 | { 58 | if( ! $this->loggedIn) return false; 59 | 60 | return $this->user->hasAnyRole($roleNames); 61 | } 62 | 63 | /** 64 | * Checks for all roles 65 | * 66 | * @param array $roleNames 67 | * @return boolean 68 | */ 69 | public function hasAllRoles(array $roleNames) 70 | { 71 | if ( ! $this->loggedIn) return false; 72 | 73 | return $this->user->hasAllRoles($roleNames); 74 | } 75 | 76 | /** 77 | * Checks if a user has a capability 78 | * 79 | * @param string $capabilityName 80 | * @return boolean 81 | */ 82 | public function hasCapability($capability) 83 | { 84 | if( ! $this->loggedIn) return false; 85 | 86 | return $this->user->hasCapability($capability); 87 | 88 | } 89 | 90 | /** 91 | * Checks if a user has any capability 92 | * 93 | * @param array $capabilityNames 94 | * @return boolean 95 | */ 96 | public function hasAnyCapability(array $capabilityNames) 97 | { 98 | if( ! $this->loggedIn) return false; 99 | 100 | return $this->user->hasAnyCapability($capabilityNames); 101 | } 102 | 103 | /** 104 | * Checks if a user has all the capabilities 105 | * 106 | * @param array $capabilityNames 107 | * @return boolean 108 | */ 109 | public function hasAllCapabilities(array $capabilityNames) 110 | { 111 | if( ! $this->loggedIn) return false; 112 | 113 | return $this->user->hasAllCapabilities($capabilityNames); 114 | } 115 | 116 | /** 117 | * Initializes the Guardian instance. 118 | * 119 | * @return void 120 | */ 121 | protected function init() 122 | { 123 | $user = $this->auth->user(); 124 | 125 | if(is_null($user)) 126 | { 127 | return $this->loggedIn = false; 128 | } 129 | else 130 | { 131 | if( ! ($user instanceof AccessControlInterface)) 132 | { 133 | throw new InvalidUserInstanceException('User Model Should Implement Usman\Guardian\AccessControl\AccessControlInterface'); 134 | } 135 | 136 | $this->user = $user; 137 | $this->loggedIn = true; 138 | } 139 | 140 | } 141 | 142 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Http/Controllers/Roles.php: -------------------------------------------------------------------------------- 1 | role = $role; 35 | $this->validator = $validator; 36 | } 37 | 38 | /** 39 | * Shows an index of the roles. 40 | * 41 | * @return Response 42 | */ 43 | public function listRole() 44 | { 45 | $roles = $this->role->getByPageWith('capabilities'); 46 | return View::make('guardian::partials.role.list')->with('roles',$roles); 47 | } 48 | 49 | /** 50 | * Shows the add role form. 51 | * 52 | * @return Response 53 | */ 54 | public function addRole() 55 | { 56 | return View::make('guardian::partials.role.add'); 57 | } 58 | 59 | /** 60 | * Saves the new role in the database. 61 | * 62 | * @return Response 63 | */ 64 | public function createRole() 65 | { 66 | try 67 | { 68 | $this->validator->setFields(Input::all())->validate('create'); 69 | $id = $this->role->create(Input::all()); 70 | if(Input::has('capabilities')) 71 | { 72 | $this->role->attach($id,Input::get('capabilities'),'capabilities'); 73 | } 74 | return Redirect::back()->withSuccess('Role Added Successfully!'); 75 | } 76 | catch(ValidationException $e) 77 | { 78 | $errors = $e->getValidationErrors(); 79 | return Redirect::back()->withErrors($errors)->withInput(); 80 | } 81 | } 82 | 83 | /** 84 | * Shows the edit role form. 85 | * 86 | * @param int $id 87 | * @return Response 88 | */ 89 | public function editRole($id) 90 | { 91 | $role = $this->role->findByIdWith($id,'capabilities'); 92 | return View::make('guardian::partials.role.edit')->with('role',$role); 93 | } 94 | 95 | /** 96 | * Updates the role record in the database. 97 | * 98 | * @param int $id 99 | * @return Response 100 | */ 101 | public function updateRole($id) 102 | { 103 | try 104 | { 105 | $this->validator->addRule('update','role_name','required|alpha|unique:roles,role_name,'.$id); 106 | $this->validator->setFields(Input::all())->validate('update'); 107 | $this->role->update($id,Input::all()); 108 | $this->role->attach($id,Input::get('capabilities',[]),'capabilities'); 109 | return Redirect::route('role.list',Input::get('ref'))->withSuccess('Role Updated Successfully!'); 110 | } 111 | catch(ValidationException $e) 112 | { 113 | $errors = $e->getValidationErrors(); 114 | return Redirect::back()->withErrors($errors)->withInput(); 115 | } 116 | } 117 | 118 | /** 119 | * Deletes a role from the database. 120 | * 121 | * @param int $id 122 | * @return Response 123 | */ 124 | public function deleteRole($id) 125 | { 126 | $this->role->deleteWith($id,['users','capabilities']); 127 | return Redirect::back()->withSuccess('Deleted Successfully!'); 128 | 129 | } 130 | 131 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Http/Controllers/Capabilities.php: -------------------------------------------------------------------------------- 1 | capability = $capability; 35 | $this->validator = $validator; 36 | } 37 | 38 | /** 39 | * Shows the index of capabilities. 40 | * 41 | * @return Response 42 | */ 43 | public function listCapability() 44 | { 45 | $capabilities = $this->capability->getByPageWith('roles'); 46 | return View::make('guardian::partials.capability.list')->with('capabilities',$capabilities); 47 | } 48 | 49 | /** 50 | * Shows the new capability form. 51 | * 52 | * @return Response 53 | */ 54 | public function addCapability() 55 | { 56 | return View::make('guardian::partials.capability.add'); 57 | 58 | } 59 | 60 | /** 61 | * Saves the newly created capability. 62 | * 63 | * @return Response 64 | */ 65 | public function createCapability() 66 | { 67 | try 68 | { 69 | $this->validator->setFields(Input::all())->validate('create'); 70 | $id = $this->capability->create(Input::all()); 71 | if(Input::has('roles')) 72 | { 73 | $this->capability->attach($id,Input::get('roles'),'roles'); 74 | } 75 | return Redirect::back()->withSuccess('Capability Created Successfully!'); 76 | } 77 | catch(ValidationException $e) 78 | { 79 | $errors = $e->getValidationErrors(); 80 | return Redirect::back()->withErrors($errors)->withInput(); 81 | } 82 | } 83 | 84 | /** 85 | * Shows the edit capability form. 86 | * 87 | * @param int $id 88 | * @return Response 89 | */ 90 | public function editCapability($id) 91 | { 92 | $capability = $this->capability->findByIdWith($id,'roles'); 93 | return View::make('guardian::partials.capability.edit')->with('capability',$capability); 94 | } 95 | 96 | /** 97 | * Updates the capability in database. 98 | * 99 | * @param int $id 100 | * @return Response 101 | */ 102 | public function updateCapability($id) 103 | { 104 | try 105 | { 106 | $this->validator->addRule('update','capability','required|alpha_dash|unique:capabilities,capability,'.$id); 107 | $this->validator->setFields(Input::all())->validate('update'); 108 | $this->capability->update($id,Input::all()); 109 | $this->capability->attach($id,Input::get('roles',[]),'roles'); 110 | return Redirect::route('capability.list',Input::get('ref'))->withSuccess('Capability Updated Successfully!'); 111 | } 112 | catch(ValidationException $e) 113 | { 114 | $errors = $e->getValidationErrors(); 115 | return Redirect::back()->withErrors($errors)->withInput(); 116 | } 117 | } 118 | 119 | /** 120 | * Deletes a capability from database. 121 | * 122 | * @param int $id 123 | * @return Response 124 | */ 125 | public function deleteCapability($id) 126 | { 127 | $this->capability->deleteWith($id,['roles']); 128 | return Redirect::back()->withSuccess('Deleted Successfully!'); 129 | } 130 | 131 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Repositories/BaseRepository.php: -------------------------------------------------------------------------------- 1 | model = $model; 25 | } 26 | 27 | /** 28 | * Finds a single record by given id. 29 | * 30 | * @param int $id 31 | * @return Illuminate\Database\Eloquent\Model 32 | */ 33 | public function findById($id) 34 | { 35 | return $this->model->findOrFail($id); 36 | } 37 | 38 | /** 39 | * Retrieves a single record from storage with related records 40 | * 41 | * @param int $id 42 | * @param string $related 43 | * @return Illuminate\Database\Eloquent\Model 44 | */ 45 | public function findByIdWith($id, $related) 46 | { 47 | return $this->model->with($related)->findOrFail($id); 48 | } 49 | 50 | /** 51 | * Retrieves a single page of records with related records 52 | * 53 | * @param string $related 54 | * @param int $perPage 55 | * @return Illuminate\Pagination\Paginator an instance of paginator. 56 | */ 57 | public function getbyPageWith($related, $perPage = self::PAGE) 58 | { 59 | return $this->model->with($related)->paginate($perPage); 60 | } 61 | 62 | /** 63 | * Retrieves all records from storage 64 | * 65 | * @param array $col 66 | * @return Illuminate\Support\Collection 67 | */ 68 | public function getAll($col = ['*']) 69 | { 70 | return $this->model->get($col); 71 | } 72 | 73 | /** 74 | * Template method for creating a record in storage 75 | * 76 | * @param array $fields 77 | * @return mixed 78 | */ 79 | public function create(array $fields) 80 | { 81 | $this->fillData($fields); 82 | return $this->model->save() ? $this->model->id : false; 83 | } 84 | 85 | /** 86 | * Template method for updating a record in storage 87 | * 88 | * @param int $id 89 | * @param array $fields 90 | * @return bool 91 | */ 92 | public function update($id, array $fields) 93 | { 94 | //caching the updated model 95 | $this->model = $this->findById($id); 96 | $this->fillData($fields); 97 | return $this->model->save($fields); 98 | } 99 | 100 | /** 101 | * Deletes a record from storage 102 | * 103 | * @param int $id 104 | * @return bool 105 | */ 106 | public function delete($id) 107 | { 108 | return $this->findById($id)->delete(); 109 | } 110 | 111 | /** 112 | * Deletes a record and its related records. 113 | * 114 | * @param int $id 115 | * @param array $method methods that define the relation 116 | * @return bool 117 | */ 118 | public function deleteWith($id, array $methods) 119 | { 120 | $model = $this->findById($id); 121 | 122 | foreach($methods as $method) 123 | { 124 | $model->{$method}()->detach(); 125 | } 126 | 127 | return $model->delete(); 128 | } 129 | 130 | /** 131 | * Attaches the related ids in pivot table 132 | * 133 | * @param ind $id 134 | * @param array $ids 135 | * @param string $method Name of the method that defines the relation 136 | * @return void 137 | */ 138 | public function attach($id, array $ids = [], $method) 139 | { 140 | //checking if this id is set on a recently updated or created model. 141 | if($this->model->id == $id) 142 | { 143 | $this->model->{$method}()->withTimeStamps()->sync($ids); 144 | } 145 | else 146 | { 147 | $this->findById($id)->{$method}()->withTimeStamps()->sync($ids); 148 | } 149 | } 150 | 151 | /** 152 | * Fills the model attributes. 153 | * 154 | * @param array $data 155 | * @return void 156 | */ 157 | abstract protected function fillData(array $data); 158 | 159 | } -------------------------------------------------------------------------------- /src/Usman/Guardian/Http/Controllers/Users.php: -------------------------------------------------------------------------------- 1 | user = $user; 36 | $this->validator = $validator; 37 | } 38 | 39 | /** 40 | * Lists ths users. 41 | * 42 | * @return Response 43 | */ 44 | public function listUser() 45 | { 46 | //we will check if a form is submitted with either 47 | //a role name or a username as a search term. 48 | if(Input::has('role') or Input::has('username')) 49 | { 50 | extract(Input::only(['role','username'])); 51 | $users = $this->user->searchUserByRole($username,$role); 52 | $users->appends(compact('role','username')); 53 | return View::make('guardian::partials.user.list')->with('users',$users); 54 | }//otherwise we will display the default users list 55 | else 56 | { 57 | $users = $this->user->getByPageWith('roles'); 58 | return View::make('guardian::partials.user.list',compact('users')); 59 | } 60 | } 61 | 62 | /** 63 | * Shows the add user form 64 | * 65 | * @return Response 66 | */ 67 | public function addUser() 68 | { 69 | return View::make('guardian::partials.user.add'); 70 | } 71 | 72 | /** 73 | * Saves the new user in the database. 74 | * 75 | * @return Response 76 | */ 77 | public function createUser() 78 | { 79 | try 80 | { 81 | $this->validator->setFields(Input::all())->validate('create'); 82 | $id = $this->user->create(Input::all()); 83 | if(Input::has('roles')) 84 | { 85 | $this->user->attach($id, Input::get('roles'),'roles'); 86 | } 87 | return Redirect::back()->withSuccess('User Created Successfully'); 88 | } 89 | catch (ValidationException $e) 90 | { 91 | $errors = $e->getValidationErrors(); 92 | return Redirect::back()->withErrors($errors)->withInput(); 93 | } 94 | 95 | } 96 | 97 | /** 98 | * Shows the user edit form. 99 | * 100 | * @param int $id 101 | * @return Response 102 | */ 103 | public function editUser($id) 104 | { 105 | $user = $this->user->findByIdWith($id,'roles'); 106 | return View::make('guardian::partials.user.edit')->with('user',$user); 107 | } 108 | 109 | /** 110 | * Updates the database record for the user. 111 | * 112 | * @param int $id 113 | * @return Response 114 | */ 115 | public function updateUser($id) 116 | { 117 | try 118 | { 119 | $this->validator->addRule('update','username','required|alpha_num|unique:users,username,'.$id); 120 | $this->validator->setFields(Input::all())->validate('update'); 121 | $this->user->update($id, Input::all()); 122 | $this->user->attach($id, Input::get('roles',[]),'roles'); 123 | return Redirect::route('user.list',Input::get('ref'))->withSuccess('User Updated Successfully'); 124 | } 125 | catch(ValidationException $e) 126 | { 127 | $errors = $e->getValidationErrors(); 128 | return Redirect::back()->withErrors($errors)->withInput(); 129 | } 130 | 131 | } 132 | 133 | /** 134 | * Deletes a user from the database. 135 | * 136 | * @param int $id 137 | * @return Response 138 | */ 139 | public function deleteUser($id) 140 | { 141 | $this->user->deleteWith($id,['roles']); 142 | return Redirect::back()->withSuccess('Deleted Successfully!'); 143 | } 144 | 145 | } -------------------------------------------------------------------------------- /public/assets/css/selectize.css: -------------------------------------------------------------------------------- 1 | /** 2 | * selectize.css (v0.11.0) 3 | * Copyright (c) 2013 Brian Reavis & contributors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 6 | * file except in compliance with the License. You may obtain a copy of the License at: 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under 10 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | * ANY KIND, either express or implied. See the License for the specific language 12 | * governing permissions and limitations under the License. 13 | * 14 | * @author Brian Reavis 15 | */ 16 | 17 | .selectize-control { 18 | position: relative; 19 | } 20 | .selectize-dropdown, 21 | .selectize-input, 22 | .selectize-input input { 23 | color: #303030; 24 | font-family: inherit; 25 | font-size: 13px; 26 | line-height: 18px; 27 | -webkit-font-smoothing: inherit; 28 | } 29 | .selectize-input, 30 | .selectize-control.single .selectize-input.input-active { 31 | background: #ffffff; 32 | cursor: text; 33 | display: inline-block; 34 | } 35 | .selectize-input { 36 | border: 1px solid #d0d0d0; 37 | padding: 8px 8px; 38 | display: inline-block; 39 | width: 100%; 40 | overflow: hidden; 41 | position: relative; 42 | z-index: 1; 43 | -webkit-box-sizing: border-box; 44 | -moz-box-sizing: border-box; 45 | box-sizing: border-box; 46 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); 47 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); 48 | -webkit-border-radius: 3px; 49 | -moz-border-radius: 3px; 50 | border-radius: 3px; 51 | } 52 | .selectize-control.multi .selectize-input.has-items { 53 | padding: 6px 8px 3px; 54 | } 55 | .selectize-input.full { 56 | background-color: #ffffff; 57 | } 58 | .selectize-input.disabled, 59 | .selectize-input.disabled * { 60 | cursor: default !important; 61 | } 62 | .selectize-input.focus { 63 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); 64 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); 65 | } 66 | .selectize-input.dropdown-active { 67 | -webkit-border-radius: 3px 3px 0 0; 68 | -moz-border-radius: 3px 3px 0 0; 69 | border-radius: 3px 3px 0 0; 70 | } 71 | .selectize-input > * { 72 | vertical-align: baseline; 73 | display: -moz-inline-stack; 74 | display: inline-block; 75 | zoom: 1; 76 | *display: inline; 77 | } 78 | .selectize-control.multi .selectize-input > div { 79 | cursor: pointer; 80 | margin: 0 3px 3px 0; 81 | padding: 2px 6px; 82 | background: #f2f2f2; 83 | color: #303030; 84 | border: 0 solid #d0d0d0; 85 | } 86 | .selectize-control.multi .selectize-input > div.active { 87 | background: #e8e8e8; 88 | color: #303030; 89 | border: 0 solid #cacaca; 90 | } 91 | .selectize-control.multi .selectize-input.disabled > div, 92 | .selectize-control.multi .selectize-input.disabled > div.active { 93 | color: #7d7d7d; 94 | background: #ffffff; 95 | border: 0 solid #ffffff; 96 | } 97 | .selectize-input > input { 98 | padding: 0 !important; 99 | min-height: 0 !important; 100 | max-height: none !important; 101 | max-width: 100% !important; 102 | margin: 0 2px 0 0 !important; 103 | text-indent: 0 !important; 104 | border: 0 none !important; 105 | background: none !important; 106 | line-height: inherit !important; 107 | -webkit-user-select: auto !important; 108 | -webkit-box-shadow: none !important; 109 | box-shadow: none !important; 110 | } 111 | .selectize-input > input::-ms-clear { 112 | display: none; 113 | } 114 | .selectize-input > input:focus { 115 | outline: none !important; 116 | } 117 | .selectize-input::after { 118 | content: ' '; 119 | display: block; 120 | clear: left; 121 | } 122 | .selectize-input.dropdown-active::before { 123 | content: ' '; 124 | display: block; 125 | position: absolute; 126 | background: #f0f0f0; 127 | height: 1px; 128 | bottom: 0; 129 | left: 0; 130 | right: 0; 131 | } 132 | .selectize-dropdown { 133 | position: absolute; 134 | z-index: 10; 135 | border: 1px solid #d0d0d0; 136 | background: #ffffff; 137 | margin: -1px 0 0 0; 138 | border-top: 0 none; 139 | -webkit-box-sizing: border-box; 140 | -moz-box-sizing: border-box; 141 | box-sizing: border-box; 142 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); 143 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); 144 | -webkit-border-radius: 0 0 3px 3px; 145 | -moz-border-radius: 0 0 3px 3px; 146 | border-radius: 0 0 3px 3px; 147 | } 148 | .selectize-dropdown [data-selectable] { 149 | cursor: pointer; 150 | overflow: hidden; 151 | } 152 | .selectize-dropdown [data-selectable] .highlight { 153 | background: rgba(125, 168, 208, 0.2); 154 | -webkit-border-radius: 1px; 155 | -moz-border-radius: 1px; 156 | border-radius: 1px; 157 | } 158 | .selectize-dropdown [data-selectable], 159 | .selectize-dropdown .optgroup-header { 160 | padding: 5px 8px; 161 | } 162 | .selectize-dropdown .optgroup:first-child .optgroup-header { 163 | border-top: 0 none; 164 | } 165 | .selectize-dropdown .optgroup-header { 166 | color: #303030; 167 | background: #ffffff; 168 | cursor: default; 169 | } 170 | .selectize-dropdown .active { 171 | background-color: #f5fafd; 172 | color: #495c68; 173 | } 174 | .selectize-dropdown .active.create { 175 | color: #495c68; 176 | } 177 | .selectize-dropdown .create { 178 | color: rgba(48, 48, 48, 0.5); 179 | } 180 | .selectize-dropdown-content { 181 | overflow-y: auto; 182 | overflow-x: hidden; 183 | max-height: 200px; 184 | } 185 | .selectize-control.single .selectize-input, 186 | .selectize-control.single .selectize-input input { 187 | cursor: pointer; 188 | } 189 | .selectize-control.single .selectize-input.input-active, 190 | .selectize-control.single .selectize-input.input-active input { 191 | cursor: text; 192 | } 193 | .selectize-control.single .selectize-input:after { 194 | content: ' '; 195 | display: block; 196 | position: absolute; 197 | top: 50%; 198 | right: 15px; 199 | margin-top: -3px; 200 | width: 0; 201 | height: 0; 202 | border-style: solid; 203 | border-width: 5px 5px 0 5px; 204 | border-color: #808080 transparent transparent transparent; 205 | } 206 | .selectize-control.single .selectize-input.dropdown-active:after { 207 | margin-top: -4px; 208 | border-width: 0 5px 5px 5px; 209 | border-color: transparent transparent #808080 transparent; 210 | } 211 | .selectize-control.rtl.single .selectize-input:after { 212 | left: 15px; 213 | right: auto; 214 | } 215 | .selectize-control.rtl .selectize-input > input { 216 | margin: 0 4px 0 -2px !important; 217 | } 218 | .selectize-control .selectize-input.disabled { 219 | opacity: 0.5; 220 | background-color: #fafafa; 221 | } 222 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##Guardian: Role Based Access Control Package For Laravel 5 and 4 With Backend Interface 2 | 3 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/usm4n/guardian/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/usm4n/guardian/?branch=master) 4 | [![Build Status](https://scrutinizer-ci.com/g/usm4n/guardian/badges/build.png?b=master)](https://scrutinizer-ci.com/g/usm4n/guardian/build-status/master) 5 | [![Latest Stable Version](https://poser.pugx.org/usm4n/guardian/v/stable.svg)](https://packagist.org/packages/usm4n/guardian) 6 | [![Total Downloads](https://poser.pugx.org/usm4n/guardian/downloads.svg)](https://packagist.org/packages/usm4n/guardian) 7 | [![Latest Unstable Version](https://poser.pugx.org/usm4n/guardian/v/unstable.svg)](https://packagist.org/packages/usm4n/guardian) [![License](https://poser.pugx.org/usm4n/guardian/license.svg)](https://packagist.org/packages/usm4n/guardian) 8 | 9 | ###For Laravel 4 please switch to the [old branch](https://github.com/usm4n/guardian/tree/old) . 10 | 11 | Guardian package for Laravel provides an easy interface to manage Role Based Access Control. Through its minimalist interface you can add users, roles and capabilities. Each user can be assigned multiple roles (many to many) and each role can be assigned multiple capabilities. 12 | 13 | Guardian also comes with plenty of Access Control helper methods that make it easy to track access for a specific user inside your code. 14 | 15 | ![Edit Role](./screenshots/main-scr.png) 16 | 17 | ##Installation and Setup 18 | 19 | To install guardian, add the following lines in your `composer.json` file: 20 | 21 | "require-dev": { 22 | "usm4n/guardian": "dev-master" 23 | } 24 | 25 | After adding the above lines, save the file and run: 26 | 27 | composer update --dev 28 | 29 | After the successful completion of the composer installation process, add the following line to the `providers` array inside the `app/config/app.php` file: 30 | 31 | 'Usman\Guardian\GuardianServiceProvider' 32 | 33 | > If you have not already installed the `illuminate/html` package, then you will need to add the `Illuminate\Html\HtmlServiceProvider` into the `providers` array as well. 34 | 35 | ###Running Package Migrations 36 | 37 | To setup the database for the guardian, you will need to run the following commands to run the package migration files: 38 | 39 | artisan vendor:publish --provider="Usman\Guardian\GuardianServiceProvider" --tag="guardian-migrations" 40 | 41 | artisan migrate 42 | 43 | The first command will copy the package migration files into your installation's `database/migrations` directory. You can make your custom changes to any table before running the second command. 44 | 45 | ###Publishing View and Assets 46 | 47 | Run the following `artisan` commands to publish the package assets and views into `public` and `resources/views` directory respectively. 48 | 49 | artisan vendor:publish --provider="Usman\Guardian\GuardianServiceProvider" --tag="guardian-assets" 50 | artisan vendor:publish --provider="Usman\Guardian\GuardianServiceProvider" --tag="guardian-views" 51 | 52 | ###Model Setup 53 | 54 | Guardian requires you to have the following models inside your `app` directory: `User`, `Role` and `Capability`. 55 | 56 | app/Role.php 57 | 58 | ```php 59 | belongsToMany('App\User'); 68 | } 69 | 70 | public function capabilities() 71 | { 72 | return $this->belongsToMany('App\Capability'); 73 | } 74 | 75 | } 76 | ``` 77 | app/Capability.php 78 | 79 | ```php 80 | belongsToMany('App\Role'); 90 | } 91 | 92 | } 93 | ``` 94 | The `User` model will require the following changes: 95 | 96 | ```php 97 | ... 98 | use Usman\Guardian\AccessControl\AccessControlTrait; 99 | use Usman\Guardian\AccessControl\AccessControlInterface; 100 | 101 | class User extends Model implements AccessControlInterface, AuthenticatableContract, CanResetPasswordContract { 102 | 103 | use Authenticatable, CanResetPassword, AccessControlTrait; 104 | 105 | ``` 106 | 107 | Please note that, if your models are namespaced other then `App\`, you will need to reflect the changes in the package `config.php` file. You can use the following command to copy the package configuration file into your `app/config` directory: 108 | 109 | artisan vendor:publish --provider="Usman\Guardian\GuardianServiceProvider" --tag="guardian-config" 110 | 111 | >Note: you can run the `artisan vendor:publish --provider="Usman\Guardian\GuardianServiceProvider"` command to publish all the package files at once. 112 | 113 | vendor/usm4n/guardian/src/config/config.php 114 | 115 | ```php 116 | 'App\User', 119 | 'roleModel' => 'App\Role', 120 | 'capabilityModel' => 'App\Capability', 121 | ]; 122 | ``` 123 | After making the requested changes you will be able to access the guardian backend at `http://www.yoursite.com/guardian/backend`. The `auth` middleware is applied by default. So, you will need to log in first. 124 | 125 | > In a development/local environment you can remove the `'middleware'=>'auth'` key value pair from the package's `routes.php` file for a test drive. 126 | 127 | ![Backend Screenshot](./screenshots/backend-scr.png) 128 | 129 | ##Guardian Helpers 130 | 131 | The following helper methods are available through `Guardian` Facade: 132 | 133 | - `Guardian::hasRole($roleName)` - returns true if the current user has the role otherwise false will be returned. 134 | - `Guardian::hasAnyRole(array $roleNames)` - returns true if user has any of the supplied roles otherwise false will be returned. 135 | - `Guardian::hasAllRoles(array $rolesNames)` - returns true only if user has all the supplied roles otherwise false will be returned. 136 | - `Guardian::hasCapability($capabilityName)` - returns true if the user has the supplied capability otherwise false will be returned. 137 | - `Guardian::hasAnyCapability($capabilityNames)` - returns true if the user has any of the supplied capabilities otherwise false will be returned. 138 | - `Guardian::hasAllCapabilities($capabilityNames)` - returns true if the user has all the supplied capabilities otherwise false will be returned. 139 | 140 | ##Help Resources For Laravel 141 | 142 | - [Laravel docs](http://laravel.com/docs) 143 | - [LaraCasts](https://laracasts.com/) 144 | - [Laravel forum](http://laravel.io/forum) 145 | - [Laravel Reddit](http://www.reddit.com/r/laravel/) 146 | 147 | ##Acknowledgements 148 | 149 | - [Selectize.js](http://brianreavis.github.io/selectize.js/) 150 | - [divshot/bootstrap-theme-white-plum](https://github.com/divshot/bootstrap-theme-white-plum) 151 | 152 | ##License 153 | 154 | Guardian is a free software released under the terms of the MIT license. 155 | 156 | ##To-do list 157 | 158 | - Code documentation. -------------------------------------------------------------------------------- /public/assets/css/selectize.bootstrap3.css: -------------------------------------------------------------------------------- 1 | /** 2 | * selectize.bootstrap3.css (v0.11.0) - Bootstrap 3 Theme 3 | * Copyright (c) 2013 Brian Reavis & contributors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 6 | * file except in compliance with the License. You may obtain a copy of the License at: 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under 10 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11 | * ANY KIND, either express or implied. See the License for the specific language 12 | * governing permissions and limitations under the License. 13 | * 14 | * @author Brian Reavis 15 | */ 16 | .selectize-control { 17 | position: relative; 18 | } 19 | .selectize-dropdown, 20 | .selectize-input, 21 | .selectize-input input { 22 | color: #7a62d3; 23 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 24 | font-size: 14px; 25 | line-height: 20px; 26 | -webkit-font-smoothing: inherit; 27 | } 28 | .selectize-input, 29 | .selectize-control.single .selectize-input.input-active { 30 | background: #ffffff; 31 | cursor: text; 32 | display: inline-block; 33 | } 34 | .selectize-input { 35 | border: 1px solid #cccccc; 36 | padding: 6px 12px; 37 | display: inline-block; 38 | width: 100%; 39 | overflow: hidden; 40 | position: relative; 41 | z-index: 1; 42 | -webkit-box-sizing: border-box; 43 | -moz-box-sizing: border-box; 44 | box-sizing: border-box; 45 | -webkit-box-shadow: none; 46 | box-shadow: none; 47 | -webkit-border-radius: 0; 48 | -moz-border-radius: 0; 49 | border-radius: 0; 50 | } 51 | .selectize-control.multi .selectize-input.has-items { 52 | padding: 5px 12px 2px; 53 | } 54 | .selectize-input.full { 55 | background-color: #ffffff; 56 | } 57 | .selectize-input.disabled, 58 | .selectize-input.disabled * { 59 | cursor: default !important; 60 | } 61 | .selectize-input.focus { 62 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); 63 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); 64 | } 65 | .selectize-input.dropdown-active { 66 | -webkit-border-radius: 0 0 0 0; 67 | -moz-border-radius: 0 0 0 0; 68 | border-radius: 0 0 0 0; 69 | } 70 | .selectize-input > * { 71 | vertical-align: baseline; 72 | display: -moz-inline-stack; 73 | display: inline-block; 74 | zoom: 1; 75 | *display: inline; 76 | } 77 | .selectize-control.multi .selectize-input > div { 78 | cursor: pointer; 79 | margin: 0 3px 3px 0; 80 | padding: 1px 3px; 81 | background: #f2f2f2; 82 | color: #7a62d3; 83 | border: 0 solid rgba(0, 0, 0, 0); 84 | } 85 | .selectize-control.multi .selectize-input > div.active { 86 | background: #5b94de; 87 | color: #ffffff; 88 | border: 0 solid rgba(0, 0, 0, 0); 89 | } 90 | .selectize-control.multi .selectize-input.disabled > div, 91 | .selectize-control.multi .selectize-input.disabled > div.active { 92 | color: #e7e7e7; 93 | background: #ffffff; 94 | border: 0 solid rgba(77, 77, 77, 0); 95 | } 96 | .selectize-input > input { 97 | padding: 0 !important; 98 | min-height: 0 !important; 99 | max-height: none !important; 100 | max-width: 100% !important; 101 | margin: 0 !important; 102 | text-indent: 0 !important; 103 | border: 0 none !important; 104 | background: none !important; 105 | line-height: inherit !important; 106 | -webkit-user-select: auto !important; 107 | -webkit-box-shadow: none !important; 108 | box-shadow: none !important; 109 | } 110 | .selectize-input > input::-ms-clear { 111 | display: none; 112 | } 113 | .selectize-input > input:focus { 114 | outline: none !important; 115 | } 116 | .selectize-input::after { 117 | content: ' '; 118 | display: block; 119 | clear: left; 120 | } 121 | .selectize-input.dropdown-active::before { 122 | content: ' '; 123 | display: block; 124 | position: absolute; 125 | background: #ffffff; 126 | height: 1px; 127 | bottom: 0; 128 | left: 0; 129 | right: 0; 130 | } 131 | .selectize-dropdown { 132 | position: absolute; 133 | z-index: 10; 134 | border: 1px solid #cccccc; 135 | background: #ffffff; 136 | margin: -1px 0 0 0; 137 | border-top: 0 none; 138 | -webkit-box-sizing: border-box; 139 | -moz-box-sizing: border-box; 140 | box-sizing: border-box; 141 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); 142 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); 143 | -webkit-border-radius: 0 0 0 0; 144 | -moz-border-radius: 0 0 0 0; 145 | border-radius: 0 0 0 0; 146 | } 147 | .selectize-dropdown [data-selectable] { 148 | cursor: pointer; 149 | overflow: hidden; 150 | } 151 | .selectize-dropdown [data-selectable] .highlight { 152 | background: rgba(255, 237, 40, 0.4); 153 | -webkit-border-radius: 1px; 154 | -moz-border-radius: 1px; 155 | border-radius: 1px; 156 | } 157 | .selectize-dropdown [data-selectable], 158 | .selectize-dropdown .optgroup-header { 159 | padding: 3px 12px; 160 | } 161 | .selectize-dropdown .optgroup:first-child .optgroup-header { 162 | border-top: 0 none; 163 | } 164 | .selectize-dropdown .optgroup-header { 165 | color: #777777; 166 | background: #ffffff; 167 | cursor: default; 168 | } 169 | .selectize-dropdown .active { 170 | background-color: #7a62d3; 171 | color: #ffffff; 172 | } 173 | .selectize-dropdown .active.create { 174 | color: #7a62d3; 175 | } 176 | .selectize-dropdown .create { 177 | color: rgba(122, 98, 211, 0.5); 178 | } 179 | .selectize-dropdown-content { 180 | overflow-y: auto; 181 | overflow-x: hidden; 182 | max-height: 200px; 183 | } 184 | .selectize-control.single .selectize-input, 185 | .selectize-control.single .selectize-input input { 186 | cursor: pointer; 187 | } 188 | .selectize-control.single .selectize-input.input-active, 189 | .selectize-control.single .selectize-input.input-active input { 190 | cursor: text; 191 | } 192 | .selectize-control.single .selectize-input:after { 193 | content: ' '; 194 | display: block; 195 | position: absolute; 196 | top: 50%; 197 | right: 17px; 198 | margin-top: -3px; 199 | width: 0; 200 | height: 0; 201 | border-style: solid; 202 | border-width: 5px 5px 0 5px; 203 | border-color: #7a62d3 transparent transparent transparent; 204 | } 205 | .selectize-control.single .selectize-input.dropdown-active:after { 206 | margin-top: -4px; 207 | border-width: 0 5px 5px 5px; 208 | border-color: transparent transparent #7a62d3 transparent; 209 | } 210 | .selectize-control.rtl.single .selectize-input:after { 211 | left: 17px; 212 | right: auto; 213 | } 214 | .selectize-control.rtl .selectize-input > input { 215 | margin: 0 4px 0 -2px !important; 216 | } 217 | .selectize-control .selectize-input.disabled { 218 | opacity: 0.5; 219 | background-color: #ffffff; 220 | } 221 | .selectize-dropdown, 222 | .selectize-dropdown.form-control { 223 | height: auto; 224 | padding: 0; 225 | margin: 2px 0 0 0; 226 | z-index: 1000; 227 | background: #ffffff; 228 | border: 1px solid #cccccc; 229 | border: 1px solid rgba(0, 0, 0, 0.15); 230 | -webkit-border-radius: 0; 231 | -moz-border-radius: 0; 232 | border-radius: 0; 233 | -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); 234 | box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); 235 | } 236 | .selectize-dropdown .optgroup-header { 237 | font-size: 12px; 238 | line-height: 1.42857143; 239 | } 240 | .selectize-dropdown .optgroup:first-child:before { 241 | display: none; 242 | } 243 | .selectize-dropdown .optgroup:before { 244 | content: ' '; 245 | display: block; 246 | height: 1px; 247 | margin: 9px 0; 248 | overflow: hidden; 249 | background-color: #e5e5e5; 250 | margin-left: -12px; 251 | margin-right: -12px; 252 | } 253 | .selectize-dropdown-content { 254 | padding: 5px 0; 255 | } 256 | .selectize-dropdown-header { 257 | padding: 6px 12px; 258 | } 259 | .selectize-input { 260 | min-height: 34px; 261 | } 262 | .selectize-input.dropdown-active { 263 | -webkit-border-radius: 0; 264 | -moz-border-radius: 0; 265 | border-radius: 0; 266 | } 267 | .selectize-input.dropdown-active::before { 268 | display: none; 269 | } 270 | .selectize-input.focus { 271 | border-color: #66afe9; 272 | outline: 0; 273 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); 274 | box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); 275 | } 276 | .selectize-control.multi .selectize-input.has-items { 277 | padding-left: 9px; 278 | padding-right: 9px; 279 | } 280 | .selectize-control.multi .selectize-input > div { 281 | -webkit-border-radius: -1px; 282 | -moz-border-radius: -1px; 283 | border-radius: -1px; 284 | } 285 | .form-control.selectize-control { 286 | padding: 0; 287 | height: auto; 288 | border: none; 289 | background: none; 290 | -webkit-box-shadow: none; 291 | box-shadow: none; 292 | -webkit-border-radius: 0; 293 | -moz-border-radius: 0; 294 | border-radius: 0; 295 | } 296 | -------------------------------------------------------------------------------- /public/assets/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.2.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('