diff --git a/.github/workflows/codesniffer.yml b/.github/workflows/codesniffer.yml new file mode 100644 index 0000000..6a730e3 --- /dev/null +++ b/.github/workflows/codesniffer.yml @@ -0,0 +1,39 @@ +name: "Codesniffer" + +on: + pull_request: + + push: + branches: [ "*" ] + + schedule: + - cron: "0 8 * * 1" + +jobs: + phpstan: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: "Setup PHP" + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + - name: Run coding standards + run: make cs \ No newline at end of file diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..fba1147 --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,39 @@ +name: PHPstan + +on: + pull_request: + + push: + branches: [ "*" ] + + schedule: + - cron: "0 8 * * 1" + +jobs: + phpstan: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: "Setup PHP" + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + - name: Run phpstan + run: make phpstan \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..f3f637d --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,39 @@ +name: PHP Unit tests + +on: + pull_request: + + push: + branches: [ "*" ] + + schedule: + - cron: "0 8 * * 1" + +jobs: + test82: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: "Setup PHP" + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + - name: Run tests + run: make tests \ No newline at end of file diff --git a/Makefile b/Makefile index 59dfcdf..189b76b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,22 @@ -.PHONY: install tests +.PHONY: install tests qa cs csf phpstan install: composer install +qa: phpstan cs + +cs: +ifdef GITHUB_ACTION + vendor/bin/phpcs --standard=ruleset.xml --encoding=utf-8 --colors -nsp -q --report=checkstyle src tests +else + vendor/bin/phpcs --standard=ruleset.xml --encoding=utf-8 --colors -nsp src tests +endif + +csf: + vendor/bin/phpcbf --standard=ruleset.xml --encoding=utf-8 --colors -nsp src tests + +phpstan: + vendor/bin/phpstan analyse -c phpstan.neon + tests: vendor/bin/phpunit --bootstrap vendor/autoload.php tests \ No newline at end of file diff --git a/composer.json b/composer.json index b5113b3..7cd4d93 100644 --- a/composer.json +++ b/composer.json @@ -2,11 +2,17 @@ "name": "troia-studio/ssh-key-validator", "type": "library", "license": "MIT", + "description": "SSH Public Key validator", "autoload": { "psr-4": { "TroiaStudio\\SshKeyValidator\\": "src/" } }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests" + } + }, "authors": [ { "name": "Jan Galek", @@ -18,6 +24,13 @@ "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10" + "phpunit/phpunit": "^10", + "contributte/qa": "^0.3.1", + "contributte/phpstan": "^0.1.0" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } } } diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..42589b0 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,15 @@ +includes: + - vendor/contributte/phpstan/phpstan.neon + +parameters: + level: 0 + phpVersion: 80200 + + scanDirectories: + - src + + fileExtensions: + - php + + paths: + - src \ No newline at end of file diff --git a/ruleset.xml b/ruleset.xml new file mode 100644 index 0000000..b3a4fed --- /dev/null +++ b/ruleset.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + /tests/tmp + \ No newline at end of file diff --git a/src/Enums/SSH_KEY.php b/src/Enums/SshKey.php similarity index 93% rename from src/Enums/SSH_KEY.php rename to src/Enums/SshKey.php index a2f2bb3..ec3af80 100644 --- a/src/Enums/SSH_KEY.php +++ b/src/Enums/SshKey.php @@ -1,14 +1,17 @@ key = $key; $this->type = $key->name; @@ -45,4 +47,5 @@ public function getComment(): string { return $this->comment; } -} \ No newline at end of file + +} diff --git a/src/KeyFactory.php b/src/KeyFactory.php index c0e938f..347a5df 100644 --- a/src/KeyFactory.php +++ b/src/KeyFactory.php @@ -1,9 +1,10 @@ > $data */ - public static function createFromValidation(array $data, SSH_KEY $type): Key + public static function createFromValidation(array $data, SshKey $type): Key { - return new Key($type, $data[2][0], $data[1][0], empty($data[3]) ? '' : trim($data[3][0])); + return new Key($type, $data[2][0], $data[1][0], trim($data[3][0])); } -} \ No newline at end of file +} diff --git a/src/KeyValidator.php b/src/KeyValidator.php index 83f3617..f0b8703 100644 --- a/src/KeyValidator.php +++ b/src/KeyValidator.php @@ -1,5 +1,6 @@ validate($key)) { $data = $this->keyDataByPattern($key, $this->type); + return KeyFactory::createFromValidation($data, $this->type); } throw new ValidationException('Creation of key object failed by validation'); } - protected function validateByPattern(string $key, SSH_KEY $pattern): bool + protected function validateByPattern(string $key, SshKey $pattern): bool { $result = $this->keyDataByPattern($key, $pattern); + return $result !== null; } - protected function keyDataByPattern(string $key, SSH_KEY $pattern): ?array + /** + * @return array>|null + */ + protected function keyDataByPattern(string $key, SshKey $pattern): ?array { preg_match_all($pattern->value, $key, $result); - if (empty($result[0]) || empty($result[1]) || empty($result[2])) { + if (!isset($result[0][0]) || !isset($result[1][0]) || !isset($result[2][0])) { return null; } return $result; } + } diff --git a/src/Validators/DSSValidator.php b/src/Validators/DSSValidator.php index 1e0041c..7a27a61 100644 --- a/src/Validators/DSSValidator.php +++ b/src/Validators/DSSValidator.php @@ -1,11 +1,14 @@ assertSame($expected->getPrefix(), $keyObject->getPrefix()); } + public function testCreateEd25519NoCommentOk(): void + { + $key = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINCqSM/QRXfw4xbJo+DIW4k9Ehks9hpxMyN/SoFvJHNZ'; + + $expected = new Key( + SshKey::ED25519, + 'AAAAC3NzaC1lZDI1NTE5AAAAINCqSM/QRXfw4xbJo+DIW4k9Ehks9hpxMyN/SoFvJHNZ', + 'ssh-ed25519', + '' + ); + + $keyObject = KeyFactory::create($key); + + $this->assertSame($expected->getType(), $keyObject->getType()); + $this->assertSame($expected->getComment(), $keyObject->getComment()); + $this->assertSame($expected->getValue(), $keyObject->getValue()); + $this->assertSame($expected->getPrefix(), $keyObject->getPrefix()); + } + public function testCreateEd25519BadValidator(): void { $key = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINCqSM/QRXfw4xbJo+DIW4k9Ehks9hpxMyN/SoFvJHNZ test ed25519'; @@ -64,4 +87,5 @@ public function testCreateEd25519False(): void $this->assertSame(null, $keyObject); } -} \ No newline at end of file + +} diff --git a/tests/KeyValidatorTest.php b/tests/KeyValidatorTest.php index 5a667fb..5ce83e0 100644 --- a/tests/KeyValidatorTest.php +++ b/tests/KeyValidatorTest.php @@ -1,5 +1,8 @@ validTest($validators, $key, false); } - protected function validTest(array $validators, $key, bool $expected): void + /** + * @param Validator[] $validators + */ + protected function validTest(array $validators, string $key, bool $expected): void { $validator = new KeyValidator($validators); $this->assertSame($expected, $validator->validate($key)); } -} \ No newline at end of file +}