├── .gitignore ├── LICENSE ├── composer.json ├── readme.md ├── resources └── config │ └── restricted.php └── src ├── Commands └── CrawlRoutes.php └── RestrictedServiceProvider.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Codulab Techbologies 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 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codulab/restricted", 3 | "type": "library", 4 | "description": "Restricts registration when a user's input (eg: username) matches a list of restricted words", 5 | "keywords": [ 6 | "username", 7 | "restricted", 8 | "security" 9 | ], 10 | "license": "MIT", 11 | "authors": [ 12 | { 13 | "name": "Codulab", 14 | "email": "build@codulab.com" 15 | } 16 | ], 17 | "require": { 18 | "php" : "~5.6|~7.0" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Codulab\\Restricted\\": "src" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Restricted 2 | 3 | Restricted allows you to restrict your users from signing up with reserved words. 4 | 5 | Reserved words can be: 6 | 7 | 1. Your route segments - Example, you have this route: www.mywebsite.com/login 8 | and your application allows to view user profile like this: www.mywebsite.com/username 9 | This package can crawl all your routes and return a validation message when a user tries to register with such words like "login" 10 | 2. Words you just want to reserve - Example: cart, products, admin etc. These words can be added manually to the reserved.txt file. after running the "restricted:index" command. 11 | 12 | ## Installation 13 | 14 | To install Restricted use composer 15 | 16 | ### Download 17 | 18 | ``` 19 | composer require codulab/restricted 20 | ``` 21 | 22 | ### Add service provider 23 | 24 | Add the following service provider to the array in: ```config/app.php``` 25 | 26 | ```php 27 | Codulab\Restricted\RestrictedServiceProvider::class, 28 | ``` 29 | 30 | ### Publish the config 31 | 32 | ``` 33 | php artisan vendor:publish --tag=restricted_config 34 | ``` 35 | 36 | ## Usage 37 | 38 | First, we need to crawl and index the application routes by running the command: 39 | 40 | ``` 41 | php artisan restricted:index 42 | ``` 43 | Now, you can simply add restricted to your validations like so: 44 | 45 | ```php 46 | $this->validate($request, [ 47 | 'name' => 'required|string|min:5', 48 | 'username' => 'required|restricted' 49 | ]); 50 | ``` 51 | You can also add a new validation message 52 | 53 | ```php 54 | $this->validate($request, [ 55 | 'name' => 'required|string|min:5', 56 | 'username' => 'required|restricted' 57 | ],[ 58 | 'username.restricted' => 'A user exists with that username. Please try another or add more characters' 59 | ]); 60 | ``` 61 | ## Settings 62 | 63 | * file_path: (string) File name and path to save the indexed words 64 | * index_level: (int) How deep do u want us to crawl your routes? ExAMPLE => www.mywebsite.com/segment1/segmen2/segment3. setting this value to '2', will allow indexing of segment1 and segment2 and exclude segment3 65 | * merge: (bool) should we to merge the new results with the old ones 66 | 67 | ## License 68 | 69 | MIT license - free to use and abuse! -------------------------------------------------------------------------------- /resources/config/restricted.php: -------------------------------------------------------------------------------- 1 | public_path("reserved.txt"), 15 | 16 | /* 17 | |-------------------------------------------------------------------------- 18 | | Index level 19 | |-------------------------------------------------------------------------- 20 | | 21 | | How deep do u want us to crawl your routes? 22 | | Ex www.mywebsite.com/segment1/segmen2/segment3 23 | | setting this value to '2', will allow indexing of segment1 and segment2 24 | | and exclude segment3 25 | | 26 | */ 27 | 'index_level' => 2, 28 | 29 | /* 30 | |-------------------------------------------------------------------------- 31 | | Should merge 32 | |-------------------------------------------------------------------------- 33 | | 34 | | Do you want to merge the new result with the old one? 35 | | It is recommended to set this to "true" if you 36 | | manually added some words to the txt file. So as not to loss them. 37 | | 38 | */ 39 | 'merge' => true, 40 | 41 | ]; -------------------------------------------------------------------------------- /src/Commands/CrawlRoutes.php: -------------------------------------------------------------------------------- 1 | router = $router; 64 | $this->routes = $router->getRoutes(); 65 | $this->fileName = config('restricted.file_path') ?: public_path("reserved.txt"); 66 | } 67 | 68 | /** 69 | * Execute the console command. 70 | * 71 | * @return mixed 72 | */ 73 | public function handle() 74 | { 75 | $this->info($this->crawl() .' words indexed from this crawl'); 76 | } 77 | 78 | public function crawl() 79 | { 80 | $routes = $this->routes; 81 | $routeCollection = $routes; 82 | $data = []; 83 | 84 | foreach ($routeCollection as $route) { 85 | 86 | $limit = config('restricted.index_level') ?: 1; 87 | $paths = explode('/', $route->uri()); 88 | 89 | foreach ($paths as $i => $path) { 90 | if($i >= $limit) 91 | break; 92 | if(!preg_match("/^\w+$/", $paths[$i])) 93 | continue; 94 | $data[] = $path; 95 | } 96 | } 97 | 98 | $data = collect($data)->unique(); 99 | $this->store($data); 100 | 101 | return $data->count(); 102 | } 103 | 104 | function store($routes){ 105 | $fileName = $this->fileName; 106 | 107 | if(config('restricted.merge') && file_exists($fileName)){ 108 | $old = collect(explode(PHP_EOL, file_get_contents($fileName))) 109 | ->map(function($value){ 110 | return trim($value); 111 | })->all(); 112 | $routes = $routes->merge($old); 113 | } 114 | 115 | $input = $routes->unique()->sort()->implode(PHP_EOL); 116 | 117 | $file = fopen($fileName, 'w+'); 118 | fwrite($file, $input); 119 | fclose($file); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/RestrictedServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 27 | __DIR__.'/../resources/config/restricted.php' => config_path('restricted.php'), 28 | ], 'restricted_config'); 29 | 30 | $this->fileName = config('restricted.file_path') ?: public_path("reserved.txt"); 31 | $this->initialize(); 32 | } 33 | 34 | /** 35 | * Register the application services. 36 | */ 37 | public function register() 38 | { 39 | // 40 | $this->commands(CrawlRoutes::class); 41 | } 42 | 43 | /** 44 | * Get the services provided by the provider. 45 | * 46 | * @return array 47 | */ 48 | public function provides() 49 | { 50 | return ['restricted']; 51 | } 52 | 53 | /** 54 | * @return void 55 | */ 56 | public function initialize() 57 | { 58 | $usernames = $this->getRestrictedUsernames(); 59 | 60 | Validator::extend('restricted', function ($attribute, $value, $parameters, $validator) use ($usernames) { 61 | return ! $usernames->contains($value); 62 | }, $this->getMessage()); 63 | } 64 | 65 | /** 66 | * @return collection 67 | */ 68 | public function getRestrictedUsernames() 69 | { 70 | $path = $this->fileName; 71 | if(file_exists($path)){ 72 | $content = file_get_contents($path); 73 | return collect(explode(PHP_EOL, $content)) 74 | ->map(function($value){ 75 | return preg_replace("/\s/", "", $value); 76 | }); 77 | }else{ 78 | return collect([]); 79 | } 80 | } 81 | 82 | /** 83 | * @return string 84 | */ 85 | public function getMessage() 86 | { 87 | return $this->message; 88 | } 89 | 90 | } --------------------------------------------------------------------------------