├── .github ├── FUNDING.yml └── workflows │ └── tests.yml ├── .gitignore ├── .styleci.yml ├── .travis.yml ├── LICENSE ├── _config.yml ├── composer.json ├── phpunit.xml ├── readme.md ├── src └── spresnac │ └── createcliuser │ ├── CreateCliUserCommand.php │ └── CreateCliUserCommandServiceProvider.php └── tests └── spresnac └── createcliuser ├── CreateCliUserCommandTest.php └── User.php /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [spresnac] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | custom: ['https://www.paypal.me/paladin', 'https://www.buymeacoffee.com/spresnac'] 9 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | tests: 9 | name: PHP ${{ matrix.php }}; Laravel ${{ matrix.laravel }} 10 | runs-on: ubuntu-latest 11 | 12 | strategy: 13 | matrix: 14 | php: [ '7.4', '8.0', '8.1' ] 15 | laravel: [ '8', '9' ] 16 | 17 | steps: 18 | - name: Checkout Code 19 | uses: actions/checkout@v2 20 | 21 | - name: Setup PHP 22 | uses: shivammathur/setup-php@v2 23 | with: 24 | php-version: ${{ matrix.php }} 25 | tools: composer:v2 26 | coverage: none 27 | 28 | - name: Setup Problem Matchers 29 | run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" 30 | 31 | - name: Select Laravel 7 32 | uses: nick-invision/retry@v1 33 | with: 34 | timeout_minutes: 5 35 | max_attempts: 5 36 | command: composer require "laravel/framework:7.*" --no-update --no-interaction 37 | if: "matrix.laravel == '7'" 38 | 39 | - name: Select Laravel 8 40 | uses: nick-invision/retry@v1 41 | with: 42 | timeout_minutes: 5 43 | max_attempts: 5 44 | command: composer require "laravel/framework:8.*" --no-update --no-interaction 45 | if: "matrix.laravel == '8'" 46 | 47 | - name: Select Laravel 9 48 | uses: nick-invision/retry@v1 49 | with: 50 | timeout_minutes: 5 51 | max_attempts: 5 52 | command: composer require "laravel/framework:9.*" --no-update --no-interaction 53 | if: "matrix.laravel == '9'" 54 | 55 | - name: Install PHP Dependencies 56 | uses: nick-invision/retry@v1 57 | with: 58 | timeout_minutes: 5 59 | max_attempts: 5 60 | command: composer update --no-interaction --no-progress 61 | 62 | - name: Execute PHPUnit 63 | run: composer test-ci 64 | 65 | - name: Push to CodeCov 66 | run: bash <(curl -s https://codecov.io/bash) 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | node_modules/ 3 | npm-debug.log 4 | 5 | # Laravel 4 specific 6 | bootstrap/compiled.php 7 | app/storage/ 8 | 9 | # Laravel 5 & Lumen specific 10 | public/storage 11 | public/hot 12 | storage/*.key 13 | .env.*.php 14 | .env.php 15 | .env 16 | Homestead.yaml 17 | Homestead.json 18 | 19 | .phpunit.result.cache 20 | composer.lock 21 | coverage.xml 22 | .idea 23 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: laravel 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - '7.4' 4 | - '8.0' 5 | - '8.1' 6 | 7 | before_script: 8 | - travis_retry composer self-update 9 | - travis_retry composer install --no-interaction 10 | 11 | script: 12 | - composer test-ci 13 | 14 | after_success: 15 | - bash <(curl -s https://codecov.io/bash) 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Sascha Presnac 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 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spresnac/laravel-create-user-cli", 3 | "description": "Create a user-entry from cli with artisan", 4 | "keywords": ["php", "laravel", "cli", "usermanagement", "ci", "cd"], 5 | "type": "library", 6 | "require": { 7 | "php": "^7.4|^8.0|^8.1" 8 | }, 9 | "require-dev": { 10 | "orchestra/testbench": "^6|^7", 11 | "laravel/framework": "^8|^9" 12 | }, 13 | "autoload": { 14 | "psr-4": { 15 | "spresnac\\": "src/spresnac/" 16 | } 17 | }, 18 | "autoload-dev": { 19 | "psr-4": { 20 | "spresnac\\tests\\": "tests/spresnac/" 21 | } 22 | }, 23 | "minimum-stability": "stable", 24 | "license": "MIT", 25 | "authors": [ 26 | { 27 | "name": "Sascha Presnac", 28 | "email": "sascha.presnac@protonmail.com" 29 | } 30 | ], 31 | "funding": [ 32 | { 33 | "type": "other", 34 | "url": "https://www.buymeacoffee.com/spresnac" 35 | }, 36 | { 37 | "type": "paypal", 38 | "url": "https://www.paypal.me/paladin" 39 | } 40 | ], 41 | "extra": { 42 | "laravel": { 43 | "providers": [ 44 | "spresnac\\createcliuser\\CreateCliUserCommandServiceProvider" 45 | ] 46 | } 47 | }, 48 | "scripts": { 49 | "test-ci": "phpunit --coverage-clover=coverage.xml" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests 10 | 11 | 12 | 13 | 14 | ./src 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Laravel: Create a user from CLI with artisan 2 | 3 | [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=for-the-badge&logo=github)](LICENSE) 4 | [![PHP from Packagist](https://img.shields.io/packagist/php-v/spresnac/laravel-create-user-cli.svg?style=for-the-badge&logo=php)](https://packagist.org/packages/spresnac/laravel-create-user-cli) 5 | [![Laravel Version](https://img.shields.io/badge/Laravel-%5E7%20|%20%5E8-important?style=for-the-badge&logo=laravel)](https://laravel.com) 6 | 7 | [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/spresnac/laravel-create-user-cli/tests?label=GH%20Tests&logo=github&style=for-the-badge)](https://github.com/spresnac/laravel-create-user-cli/actions) 8 | ![Codecov](https://img.shields.io/codecov/c/gh/spresnac/laravel-create-user-cli?logo=codecov&style=for-the-badge&token=6BEX55062B) 9 | [![StyleCI](https://github.styleci.io/repos/174492279/shield)](https://github.styleci.io/repos/174492279) 10 | 11 | --- 12 | # About this package 💡 13 | This package is an easy way to create a user for a ci/cd workflow. Just setup your project as usual and create a new user by firing a cli-command. 14 | 15 | --- 16 | # Installation 💻 17 | First things first, so require the package: 18 | 19 | ``` 20 | composer require spresnac/laravel-create-user-cli 21 | ``` 22 | 23 | Now, register the new command within your ``app\Console\Kernel.php`` 24 | ``` 25 | protected $commands = [ 26 | \spresnac\createcliuser\CreateCliUserCommand::class, 27 | ]; 28 | ``` 29 | --- 30 | # Usage 💪 31 | This package is very simple to use, open up your console and type 32 | ``` 33 | php artisan user:create 34 | ``` 35 | 36 | When using it within some kind of continous deployment, use the parameter and options to get fully automated like 37 | ``` 38 | php artisan user:create "user_name" "user_email" "user_password" --force 39 | ``` 40 | 41 | One can get help with 42 | ``` 43 | php artisan help user:create 44 | ``` 45 | --- 46 | # CI environments 47 | This is an overview of all result codes you can handle in ci environements: 48 | 49 | Code | Description 50 | -----| -------------------------------------------------------------------------------------------------------------------- 51 | 0 | all good 😃 52 | 1 | The user with this data is already existing and was not overwritten. Use the `--force` option to overwrite the user. 53 | 2 | There is a user exisiting with this data and there was a problem updating this database record. 54 | 5 | You should not get this code. If you do, you may have not provided all data correct. 55 | 56 | --- 57 | # Tests 🤓 58 | Start the tests like standard with 59 | ``` 60 | composer test-ci 61 | ``` 62 | or with 63 | ``` 64 | vendor/bin/phpunit 65 | ``` 66 | --- 67 | # Finally 🤩 68 | ... have fun ;) -------------------------------------------------------------------------------- /src/spresnac/createcliuser/CreateCliUserCommand.php: -------------------------------------------------------------------------------- 1 | name = ($this->argument('name') === null) 51 | ? $this->ask('User name: ') 52 | : $this->argument('name'); 53 | 54 | $user->email = ($this->argument('email') === null) 55 | ? $this->ask('User email: ') 56 | : $this->argument('email'); 57 | 58 | $user->password = ($this->argument('password') === null) 59 | ? Hash::make($this->ask('User password: ')) 60 | : Hash::make($this->argument('password')); 61 | 62 | if ($this->option('force') === true || $this->confirm('Save this user?', true)) { 63 | $exists = (new $class)->where([ 64 | 'name' => $user->name, 65 | 'email' => $user->email, 66 | ])->first(); 67 | if ($exists === null) { // user is not exisiting yet, just create him and return 68 | $user->save(); 69 | $this->info('Created a user with id: '.$user->id); 70 | 71 | return self::E_OK; 72 | } 73 | // user is already existing, check the input and handle 74 | if ($this->option('force')) { 75 | if ($exists->update($user->getAttributes())) { 76 | $this->info('Updated an existing user with id: '.$exists->id); 77 | 78 | return self::E_OK; 79 | } 80 | $this->warn('Updating an existing user with id: '.$exists->id.' ended with errors'); 81 | 82 | return self::E_UPDATING_FAILED; 83 | } 84 | $this->error('User already exist with id: '.$exists->id); 85 | 86 | return self::E_USER_EXISTS; 87 | } 88 | 89 | return self::E_CHAOS; // default end with an error to show, that this line was hit accidentially 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/spresnac/createcliuser/CreateCliUserCommandServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->runningInConsole()) { 12 | $this->commands([ 13 | CreateCliUserCommand::class, 14 | ]); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/spresnac/createcliuser/CreateCliUserCommandTest.php: -------------------------------------------------------------------------------- 1 | artisan('user:create') 23 | ->expectsQuestion('User name: ', $expectedUserName) 24 | ->expectsQuestion('User email: ', $expectedUserEmail) 25 | ->expectsQuestion('User password: ', $expectedPassword) 26 | ->expectsQuestion('Save this user?', 'yes') 27 | ->expectsOutput('Created a user with id: 1') 28 | ->assertExitCode(0); 29 | 30 | $this->assertDatabaseHas('users', [ 31 | 'email' => $expectedUserEmail, 32 | 'name' => 'User Name', 33 | ]); 34 | } 35 | 36 | public function testCanCreateUserWithAllArguments(): void 37 | { 38 | $expectedUserName = 'User Name'; 39 | $expectedUserEmail = 'user@email.com'; 40 | $expectedPassword = 'bad_password'; 41 | 42 | $this->artisan( 43 | sprintf( 44 | 'user:create --force "%s" %s %s', 45 | $expectedUserName, 46 | $expectedUserEmail, 47 | $expectedPassword 48 | ) 49 | ) 50 | ->expectsOutput('Created a user with id: 1') 51 | ->assertExitCode(0); 52 | 53 | $this->assertDatabaseHas('users', [ 54 | 'email' => $expectedUserEmail, 55 | 'name' => 'User Name', 56 | ]); 57 | } 58 | 59 | /** @test */ 60 | public function it_can_handle_already_existing_users_and_overwrites_the_user_on_force() 61 | { 62 | $expectedUserName = 'User Name'; 63 | $expectedUserEmail = 'user@email.com'; 64 | $expectedPassword = 'bad_password'; 65 | 66 | $this->artisan( 67 | sprintf( 68 | 'user:create --force "%s" %s %s', 69 | $expectedUserName, 70 | $expectedUserEmail, 71 | $expectedPassword 72 | ) 73 | ) 74 | ->expectsOutput('Created a user with id: 1') 75 | ->assertExitCode(0); 76 | 77 | $this->assertDatabaseHas('users', [ 78 | 'email' => $expectedUserEmail, 79 | 'name' => 'User Name', 80 | ]); 81 | 82 | // From here, we test the output and behaviour when inserting a user that is already existing 83 | $this->artisan( 84 | sprintf( 85 | 'user:create --force "%s" %s %s', 86 | $expectedUserName, 87 | $expectedUserEmail, 88 | $expectedPassword 89 | ) 90 | ) 91 | ->expectsOutput('Updated an existing user with id: 1') 92 | ->assertExitCode(0); 93 | } 94 | 95 | /** @test */ 96 | public function it_can_handle_already_existing_users_and_overwrites_the_user_not_via_default() 97 | { 98 | $expectedUserName = 'User Name'; 99 | $expectedUserEmail = 'user@email.com'; 100 | $expectedPassword = 'bad_password'; 101 | 102 | $this->artisan( 103 | sprintf( 104 | 'user:create --force "%s" %s %s', 105 | $expectedUserName, 106 | $expectedUserEmail, 107 | $expectedPassword 108 | ) 109 | ) 110 | ->expectsOutput('Created a user with id: 1') 111 | ->assertExitCode(0); 112 | 113 | $this->assertDatabaseHas('users', [ 114 | 'email' => $expectedUserEmail, 115 | 'name' => 'User Name', 116 | ]); 117 | 118 | // From here, we test the output and behaviour when inserting a user that is already existing 119 | $this->artisan('user:create') 120 | ->expectsQuestion('User name: ', $expectedUserName) 121 | ->expectsQuestion('User email: ', $expectedUserEmail) 122 | ->expectsQuestion('User password: ', $expectedPassword) 123 | ->expectsQuestion('Save this user?', 'yes') 124 | ->expectsOutput('User already exist with id: 1') 125 | ->assertExitCode(1); 126 | } 127 | 128 | protected function getPackageProviders($app) 129 | { 130 | return [ 131 | CreateCliUserCommandServiceProvider::class, 132 | ]; 133 | } 134 | 135 | protected function setUp(): void 136 | { 137 | parent::setUp(); 138 | 139 | $this->loadLaravelMigrations(); 140 | } 141 | 142 | public function getEnvironmentSetUp($app) 143 | { 144 | $app['config']->set('auth.guards.web.provider', 'users'); 145 | $app['config']->set('auth.providers.users.model', User::class); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /tests/spresnac/createcliuser/User.php: -------------------------------------------------------------------------------- 1 | 'datetime', 40 | ]; 41 | } 42 | --------------------------------------------------------------------------------