build: 增加lint/prettier/unitTest

This commit is contained in:
李东云
2023-12-25 17:10:21 +08:00
parent 03e717138d
commit 1013894cca
30 changed files with 654 additions and 1506 deletions

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
/vendor/ /vendor/
*.cache *.cache
*.log *.log
runtime/
# IDE support # IDE support
.idea/ .idea/

View File

@@ -1,89 +1,16 @@
<?php <?php
$header = <<<'EOF' $finder = PhpCsFixer\Finder::create()->in([
This file is part of Hyperf. __DIR__ . '/publish',
__DIR__ . '/src',
__DIR__ . '/tests',
]);
@link https://www.hyperf.io $config = new PhpCsFixer\Config();
@document https://hyperf.wiki return $config->setRules([
@contact group@hyperf.io '@PSR12' => true,
@license https://github.com/hyperf/hyperf/blob/master/LICENSE 'strict_param' => true,
EOF; 'array_syntax' => ['syntax' => 'short'],
])
return (new PhpCsFixer\Config()) ->setUsingCache(false)
->setRiskyAllowed(true) ->setFinder($finder);
->setRules([
'@PSR2' => true,
'@Symfony' => true,
'@DoctrineAnnotation' => true,
'@PhpCsFixer' => true,
'header_comment' => [
'comment_type' => 'PHPDoc',
'header' => $header,
'separate' => 'none',
'location' => 'after_declare_strict',
],
'array_syntax' => [
'syntax' => 'short'
],
'list_syntax' => [
'syntax' => 'short'
],
'concat_space' => [
'spacing' => 'one'
],
'blank_line_before_statement' => [
'statements' => [
'declare',
],
],
'general_phpdoc_annotation_remove' => [
'annotations' => [
'author'
],
],
'ordered_imports' => [
'imports_order' => [
'class', 'function', 'const',
],
'sort_algorithm' => 'alpha',
],
'single_line_comment_style' => [
'comment_types' => [
],
],
'yoda_style' => [
'always_move_variable' => false,
'equal' => false,
'identical' => false,
],
'phpdoc_align' => [
'align' => 'left',
],
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line',
],
'constant_case' => [
'case' => 'lower',
],
'class_attributes_separation' => true,
'combine_consecutive_unsets' => true,
'declare_strict_types' => true,
'linebreak_after_opening_tag' => true,
'lowercase_static_reference' => true,
'no_useless_else' => true,
'no_unused_imports' => true,
'not_operator_with_successor_space' => true,
'not_operator_with_space' => false,
'ordered_class_elements' => true,
'php_unit_strict' => false,
'phpdoc_separation' => false,
'single_quote' => true,
'standardize_not_equals' => true,
'multiline_comment_opening_closing' => true,
])
->setFinder(
PhpCsFixer\Finder::create()
->exclude('vendor')
->in(__DIR__)
)
->setUsingCache(false);

View File

@@ -19,6 +19,7 @@
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.1",
"ext-redis": "*",
"hyperf/config": "3.1.*", "hyperf/config": "3.1.*",
"hyperf/constants": "3.1.*", "hyperf/constants": "3.1.*",
"hyperf/di": "3.1.*", "hyperf/di": "3.1.*",
@@ -28,8 +29,7 @@
"litesaml/lightsaml": "~3.0.0", "litesaml/lightsaml": "~3.0.0",
"singularity/hdk-core": "^1.0.0", "singularity/hdk-core": "^1.0.0",
"singularity/hdk-auth": "^1.0.0", "singularity/hdk-auth": "^1.0.0",
"teapot/status-code": "^1.1", "teapot/status-code": "^1.1"
"ext-redis": "*"
}, },
"require-dev": { "require-dev": {
"friendsofphp/php-cs-fixer": "^3.0", "friendsofphp/php-cs-fixer": "^3.0",
@@ -51,9 +51,19 @@
} }
}, },
"scripts": { "scripts": {
"test": "phpunit -c phpunit.xml --colors=always", "test": [
"analyse": "phpstan analyse --memory-limit 1024M -l 0 ./src", "rm -rf runtime",
"cs-fix": "php-cs-fixer fix $1" "Composer\\Config::disableProcessTimeout",
"pest --coroutine --prepend tests/bootstrap.php --colors=always"
],
"cs-fix": "php-cs-fixer fix $1 --rules=@PSR12 --allow-risky=yes",
"analyse": "phpstan analyse $1",
"ci": [
"@analyse publish/ src/ tests/",
"@cs-fix",
"@test",
"echo CI Success"
]
}, },
"extra": { "extra": {
"hyperf": { "hyperf": {

1543
composer.lock generated

File diff suppressed because it is too large Load Diff

15
phpstan.dist.neon Normal file
View File

@@ -0,0 +1,15 @@
parameters:
level: 1
reportUnmatchedIgnoredErrors: false
checkGenericClassInNonGenericObjectType: false
paths:
- publish
- src
- tests
ignoreErrors:
- '#Constant BASE_PATH not found#'
- '#Unknown parameter \$[a-zA-Z0-9]+ in call to callable Closure\.#'
- '#Property [a-zA-Z0-9\\_]+::\$[a-zA-Z0-9]+ is never written, only read\.#'
- '#Method [a-zA-Z0-9\\_]+::[a-zA-Z0-9]+\(\) is unused\.#'
- '#Method [a-zA-Z0-9\\_]+::[a-zA-Z0-9]+\(\) has parameter \$response with no value type specified in iterable type array\.#'
- '#Undefined variable: \$this#'

View File

@@ -1,15 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" <phpunit
backupGlobals="false" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
backupStaticAttributes="false" bootstrap="tests/bootstrap.php"
verbose="true"
colors="true" colors="true"
convertErrorsToExceptions="true" stopOnFailure="true"
convertNoticesToExceptions="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd"
convertWarningsToExceptions="true" cacheDirectory=".phpunit.cache"
processIsolation="false" >
stopOnFailure="false"> <testsuites>
<testsuite name="Testsuite"> <testsuite name="Testsuite">
<directory>./tests/</directory> <directory>./tests/</directory>
</testsuite> </testsuite>
</testsuites>
<source>
<include>
<directory>./src</directory>
</include>
</source>
</phpunit> </phpunit>

View File

@@ -2,6 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
use function Hyperf\Support\env;
return [ return [
// 当前项目类型 // 当前项目类型
'type' => 'sp', // 可选值sp/idp 'type' => 'sp', // 可选值sp/idp
@@ -31,7 +33,7 @@ return [
// 以下内容向服务端申请 // 以下内容向服务端申请
'entity_id' => env('ENTITY_ID', ''), // TODO 业务系统唯一标识 'entity_id' => env('ENTITY_ID', ''), // TODO 业务系统唯一标识
'acs_url' => env('ACS_URL', ''), // TODO 回调地址 'acs_url' => env('ACS_URL', ''), // TODO 回调地址
'landing_host' =>env('LANDING_HOST', ''), // TODO 站点 host 'landing_host' => env('LANDING_HOST', ''), // TODO 站点 host
], ],
// 证书 // 证书

View File

@@ -7,6 +7,7 @@
* Created on 2022/4/25 * Created on 2022/4/25
*/ */
declare(strict_types=1); declare(strict_types=1);
namespace Singularity\HyperfSaml\Constants; namespace Singularity\HyperfSaml\Constants;
use Hyperf\Constants\AbstractConstants; use Hyperf\Constants\AbstractConstants;
@@ -23,7 +24,6 @@ use Hyperf\Constants\Annotation\Constants;
*/ */
class SamlErrorCode extends AbstractConstants class SamlErrorCode extends AbstractConstants
{ {
// 203 SAML 鉴权 // 203 SAML 鉴权
/** /**
* @Message("saml_error.default") * @Message("saml_error.default")

View File

@@ -1,6 +1,7 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Singularity\HyperfSaml\Exceptions\Handler; namespace Singularity\HyperfSaml\Exceptions\Handler;
use Hyperf\Di\Annotation\Inject; use Hyperf\Di\Annotation\Inject;
@@ -16,6 +17,8 @@ use Singularity\HyperfSaml\Services\Idp\AbstractLoginService;
use Singularity\HyperfSaml\Services\Idp\AbstractLogoutService; use Singularity\HyperfSaml\Services\Idp\AbstractLogoutService;
use Throwable; use Throwable;
use function Hyperf\Config\config;
/** /**
* IDP 相关错误捕获 * IDP 相关错误捕获
* Singularity\HyperfSaml\Exceptions\Handler\SamlIdpHandler@HyperfSaml * Singularity\HyperfSaml\Exceptions\Handler\SamlIdpHandler@HyperfSaml

View File

@@ -1,14 +1,16 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Singularity\HyperfSaml\Exceptions\Handler; namespace Singularity\HyperfSaml\Exceptions\Handler;
use Exception;
use Hyperf\Codec\Json;
use Hyperf\Di\Annotation\Inject; use Hyperf\Di\Annotation\Inject;
use Hyperf\ExceptionHandler\ExceptionHandler; use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\Framework\Logger\StdoutLogger; use Hyperf\Framework\Logger\StdoutLogger;
use Hyperf\HttpMessage\Stream\SwooleStream; use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Contract\RequestInterface; use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Utils\Codec\Json;
use Lmc\HttpConstants\Header; use Lmc\HttpConstants\Header;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Singularity\HyperfSaml\Constants\SamlErrorCode; use Singularity\HyperfSaml\Constants\SamlErrorCode;
@@ -17,6 +19,8 @@ use Singularity\HyperfSaml\Exceptions\ValidationException;
use Teapot\StatusCode\RFC\RFC7231; use Teapot\StatusCode\RFC\RFC7231;
use Throwable; use Throwable;
use function Hyperf\Config\config;
/** /**
* SP 相关错误捕获 * SP 相关错误捕获
* Singularity\HyperfSaml\Exceptions\Handler\SamlIdpHandler@HyperfSaml * Singularity\HyperfSaml\Exceptions\Handler\SamlIdpHandler@HyperfSaml
@@ -29,22 +33,22 @@ class SamlSpHandler extends ExceptionHandler
{ {
/** /**
* @Inject * @Inject
* @var \Hyperf\Framework\Logger\StdoutLogger * @var StdoutLogger
*/ */
private StdoutLogger $logger; private StdoutLogger $logger;
/** /**
* @Inject(required=false) * @Inject(required=false)
* @var \Hyperf\HttpServer\Contract\RequestInterface|null * @var RequestInterface|null
*/ */
private ?RequestInterface $request; private ?RequestInterface $request;
/** /**
* @param RuntimeException $throwable * @param RuntimeException $throwable
* @param \Psr\Http\Message\ResponseInterface $response * @param ResponseInterface $response
* *
* @return \Psr\Http\Message\ResponseInterface * @return ResponseInterface
* @throws \Exception * @throws Exception
*/ */
public function handle(Throwable $throwable, ResponseInterface $response): ResponseInterface public function handle(Throwable $throwable, ResponseInterface $response): ResponseInterface
{ {
@@ -106,7 +110,6 @@ class SamlSpHandler extends ExceptionHandler
'errorTrack' => $throwable->getTrace(), 'errorTrack' => $throwable->getTrace(),
]; ];
} }
$cookies = json_encode($this->request->getCookieParams(), JSON_UNESCAPED_UNICODE);
$this->logger->error( $this->logger->error(
<<<ERROR_LOG <<<ERROR_LOG
TYPE: $error_type TYPE: $error_type
@@ -143,7 +146,6 @@ ERROR_LOG
$data = Json::encode($data); $data = Json::encode($data);
if ($restful) { if ($restful) {
$response = $response->withStatus( $response = $response->withStatus(
$status_code ??
$throwable->status ?? $throwable->status ??
$throwable->statusCode ?? $throwable->statusCode ??
RFC7231::INTERNAL_SERVER_ERROR RFC7231::INTERNAL_SERVER_ERROR

View File

@@ -1,11 +1,11 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Singularity\HyperfSaml\Exceptions\Logout; namespace Singularity\HyperfSaml\Exceptions\Logout;
use Singularity\HyperfSaml\Exceptions\ValidationException as SAMLValidationException; use Singularity\HyperfSaml\Exceptions\ValidationException as SAMLValidationException;
class ValidationException extends SAMLValidationException class ValidationException extends SAMLValidationException
{ {
} }

View File

@@ -1,6 +1,7 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Singularity\HyperfSaml\Exceptions; namespace Singularity\HyperfSaml\Exceptions;
use Throwable; use Throwable;

View File

@@ -1,6 +1,7 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Singularity\HyperfSaml\Exceptions; namespace Singularity\HyperfSaml\Exceptions;
// use App\Model\ServiceProvider; // use App\Model\ServiceProvider;
@@ -29,7 +30,7 @@ class ValidationException extends RuntimeException
SamlConstants::STATUS_INVALID_NAME_ID_POLICY, SamlConstants::STATUS_INVALID_NAME_ID_POLICY,
$messageId, $messageId,
$relayState, $relayState,
$message ?? SamlErrorCode::getMessage($code) , $message ?? SamlErrorCode::getMessage($code),
$code, $code,
$previous $previous
); );

View File

@@ -37,6 +37,8 @@ use RobRichards\XMLSecLibs\XMLSecurityKey;
use Singularity\HDK\Auth\Resource\User; use Singularity\HDK\Auth\Resource\User;
use Throwable; use Throwable;
use function Hyperf\Config\config;
/** /**
* Singularity\HyperfSaml\Lib\Base@HyperfSaml * Singularity\HyperfSaml\Lib\Base@HyperfSaml
* *

View File

@@ -1,6 +1,7 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Singularity\HyperfSaml\Services\Idp; namespace Singularity\HyperfSaml\Services\Idp;
use DateTime; use DateTime;

View File

@@ -16,6 +16,8 @@ use Singularity\HDK\Core\Constants\CommonErrorCode;
use Singularity\HyperfSaml\Exceptions\Logout\ValidationException; use Singularity\HyperfSaml\Exceptions\Logout\ValidationException;
use Singularity\HyperfSaml\Services\AbstractService; use Singularity\HyperfSaml\Services\AbstractService;
use function Hyperf\Config\config;
class AbstractLogoutService extends AbstractService class AbstractLogoutService extends AbstractService
{ {
/** /**

View File

@@ -31,6 +31,8 @@ use Singularity\HyperfSaml\Exceptions\RuntimeException;
use Singularity\HyperfSaml\Exceptions\ValidationException; use Singularity\HyperfSaml\Exceptions\ValidationException;
use Singularity\HyperfSaml\Services\Base; use Singularity\HyperfSaml\Services\Base;
use function Hyperf\Config\config;
/** /**
* 断言操作类 * 断言操作类
* 用于获取用户登录状态 * 用于获取用户登录状态

View File

@@ -8,9 +8,9 @@
*/ */
declare(strict_types=1); declare(strict_types=1);
namespace Singularity\HyperfSaml\Services\Sp; namespace Singularity\HyperfSaml\Services\Sp;
class MetadataProfile class MetadataProfile
{ {
} }

View File

@@ -15,10 +15,13 @@ use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface; use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\Redis\Redis; use Hyperf\Redis\Redis;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface; use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
use RedisException;
use Singularity\HDK\Auth\Services\AuthenticationInterface; use Singularity\HDK\Auth\Services\AuthenticationInterface;
use Singularity\HyperfSaml\Services\Base; use Singularity\HyperfSaml\Services\Base;
use Teapot\StatusCode\RFC\RFC7231; use Teapot\StatusCode\RFC\RFC7231;
use function Hyperf\Config\config;
/** /**
* 单点退出登录 * 单点退出登录
* Singularity\HyperfSaml\Services\Sp\Slo@HyperfSaml * Singularity\HyperfSaml\Services\Sp\Slo@HyperfSaml
@@ -30,11 +33,11 @@ use Teapot\StatusCode\RFC\RFC7231;
class Slo class Slo
{ {
public function __construct( public function __construct(
private Base $base, private readonly Base $base,
private RequestInterface $request, private readonly RequestInterface $request,
private ResponseInterface $response, private readonly ResponseInterface $response,
private AuthenticationInterface $authentication, private readonly AuthenticationInterface $authentication,
private Redis $redis private readonly Redis $redis
) { ) {
} }
@@ -44,7 +47,7 @@ class Slo
* @param string $uid * @param string $uid
* @param string $originToken * @param string $originToken
* *
* @return \Psr\Http\Message\ResponseInterface * @return PsrResponseInterface
*/ */
public function redirect(string $uid, string $originToken): PsrResponseInterface public function redirect(string $uid, string $originToken): PsrResponseInterface
{ {
@@ -68,7 +71,8 @@ class Slo
/** /**
* 回调方式退出单点登录IDP 通知 SP) * 回调方式退出单点登录IDP 通知 SP)
* *
* @return \Psr\Http\Message\ResponseInterface Account 只根据 StatusCode 判断, 符合 [200, 300) 即可 * @return PsrResponseInterface Account 只根据 StatusCode 判断, 符合 [200, 300) 即可
* @throws RedisException
*/ */
public function callback(): PsrResponseInterface public function callback(): PsrResponseInterface
{ {

View File

@@ -11,7 +11,7 @@ declare(strict_types=1);
namespace Singularity\HyperfSaml\Services\Sp; namespace Singularity\HyperfSaml\Services\Sp;
use Hyperf\Utils\Codec\Json; use Hyperf\Codec\Json;
use Singularity\HDK\Core\Constants\CommonErrorCode; use Singularity\HDK\Core\Constants\CommonErrorCode;
use Singularity\HDK\Core\Exceptions\Forbidden; use Singularity\HDK\Core\Exceptions\Forbidden;
use Swoole\Exception; use Swoole\Exception;
@@ -24,6 +24,8 @@ use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
use Singularity\HyperfSaml\Services\Base; use Singularity\HyperfSaml\Services\Base;
use Teapot\StatusCode\RFC\RFC7231; use Teapot\StatusCode\RFC\RFC7231;
use function Hyperf\Config\config;
/** /**
* SP 单点登录 * SP 单点登录
* Singularity\HyperfSaml\Sp\Sso@HyperfSaml * Singularity\HyperfSaml\Sp\Sso@HyperfSaml

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace HyperfTest\Cases;
use PHPUnit\Framework\TestCase;
/**
* Class AbstractTestCase.
*/
abstract class AbstractTestCase extends TestCase
{
}

View File

@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace HyperfTest\Cases;
/**
* @internal
* @coversNothing
*/
class ExampleTest extends AbstractTestCase
{
public function testExample()
{
$this->assertTrue(true);
}
}

View File

@@ -0,0 +1,5 @@
<?php
test('example', function () {
expect(true)->toBeTrue();
});

45
tests/Pest.php Normal file
View File

@@ -0,0 +1,45 @@
<?php
/*
|--------------------------------------------------------------------------
| Test Case
|--------------------------------------------------------------------------
|
| The closure you provide to your test functions is always bound to a specific PHPUnit test
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
| need to change it using the "uses()" function to bind a different classes or traits.
|
*/
// uses(Tests\TestCase::class)->in('Feature');
/*
|--------------------------------------------------------------------------
| Expectations
|--------------------------------------------------------------------------
|
| When you're writing tests, you often need to check that values meet certain conditions. The
| "expect()" function gives you access to a set of "expectations" methods that you can use
| to assert different things. Of course, you may extend the Expectation API at any time.
|
*/
expect()->extend('toBeOne', function () {
return $this->toBe(1);
});
/*
|--------------------------------------------------------------------------
| Functions
|--------------------------------------------------------------------------
|
| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
| project that you don't want to repeat in every file. Here you can also expose helpers as
| global functions to help you to reduce the number of lines of code in your test files.
|
*/
/*function something()
{
// ..
}*/

10
tests/TestCase.php Normal file
View File

@@ -0,0 +1,10 @@
<?php
namespace Tests;
use PHPUnit\Framework\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
//
}

View File

@@ -0,0 +1,5 @@
<?php
test('example', function () {
expect(true)->toBeTrue();
});

View File

@@ -1,12 +1,31 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
/**
* This file is part of Hyperf. use Hyperf\Context\ApplicationContext;
* use Hyperf\Di\ClassLoader;
* @link https://www.hyperf.io use Hyperf\Di\Container;
* @document https://hyperf.wiki use Hyperf\Di\Definition\DefinitionSource;
* @contact group@hyperf.io use Psr\Container\ContainerInterface;
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE use Swoole\Runtime;
*/
require_once dirname(dirname(__FILE__)) . '/vendor/autoload.php'; ini_set('display_errors', 'on');
ini_set('display_startup_errors', 'on');
error_reporting(E_ALL);
date_default_timezone_set('Asia/Shanghai');
!defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
!defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
Runtime::enableCoroutine(true);
require BASE_PATH . '/vendor/autoload.php';
ClassLoader::init();
$container = new Container(new DefinitionSource([]));
if (!$container instanceof ContainerInterface) {
throw new RuntimeException('The dependency injection container is invalid.');
}
$container = ApplicationContext::setContainer($container);