Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ phpcs.xml.dist
# PHPUnit
/tests/coverage
.phpunit
.phpunit.cache
.phpunit.result.cache
phpunit.xml
TEST-*.xml
Expand Down
8 changes: 3 additions & 5 deletions bin/ecs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
#!/bin/bash
# Script used to run ECS check in the application docker container
# Script used to run ECS check in the application container

PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)"
CHECK_DIR=${1:-src}

cd "${PROJECT_ROOT}" || exit 1

if [ -f /.dockerenv ]; then
echo "[INFO] Running ECS check"
vendor/bin/ecs check --fix --config=ecs.php "${CHECK_DIR}"
vendor/bin/ecs check --fix --config=ecs.php
exit
fi

bin/docker-compose run --rm app bash -c \'bin/ecs "${CHECK_DIR}"\'
bin/docker-compose run --rm app bash -c \'bin/ecs\'
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
"ext-redis": "*",
"anzusystems/common-bundle": "^8.0|^9.0|^10.0",
"doctrine/common": "^3.3",
"lcobucci/jwt": "^4.2"
"lcobucci/clock": "^3.0",
"lcobucci/jwt": "^5.5"
},
"require-dev": {
"doctrine/orm": "^2.13|^3.0",
"nelmio/api-doc-bundle": "^4.9",
"nelmio/api-doc-bundle": "^4.38",
"slevomat/coding-standard": "8.20.0",
"squizlabs/php_codesniffer": "^3.13.2",
"symfony/test-pack": "^1.0",
"symplify/easy-coding-standard": "^11.1",
"symplify/easy-coding-standard": "^13.0",
"vimeo/psalm": "^6.0"
},
"autoload": {
Expand Down
204 changes: 81 additions & 123 deletions ecs.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

declare(strict_types=1);
use AnzuSystems\CommonBundle\DependencyInjection\Configuration;

use PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\ForbiddenFunctionsSniff;
use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer;
use PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer;
Expand All @@ -18,18 +18,13 @@
use PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocTagRenameFixer;
use PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer;
use PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer;
use PhpCsFixer\Fixer\Phpdoc\PhpdocAnnotationWithoutDotFixer;
use PhpCsFixer\Fixer\Phpdoc\PhpdocInlineTagNormalizerFixer;
use PhpCsFixer\Fixer\Phpdoc\PhpdocSeparationFixer;
use PhpCsFixer\Fixer\Phpdoc\PhpdocToCommentFixer;
use PhpCsFixer\Fixer\Phpdoc\PhpdocTypesOrderFixer;
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;
use PhpCsFixer\Fixer\Whitespace\MethodChainingIndentationFixer;
use SlevomatCodingStandard\Sniffs\Classes\MethodSpacingSniff;
use SlevomatCodingStandard\Sniffs\Classes\ModernClassNameReferenceSniff;
use SlevomatCodingStandard\Sniffs\Classes\ParentCallSpacingSniff;
use SlevomatCodingStandard\Sniffs\Classes\PropertySpacingSniff;
use SlevomatCodingStandard\Sniffs\Commenting\DocCommentSpacingSniff;
use SlevomatCodingStandard\Sniffs\Commenting\UselessInheritDocCommentSniff;
use SlevomatCodingStandard\Sniffs\ControlStructures\RequireNullCoalesceOperatorSniff;
use SlevomatCodingStandard\Sniffs\Functions\ArrowFunctionDeclarationSniff;
Expand All @@ -41,27 +36,19 @@
use SlevomatCodingStandard\Sniffs\Namespaces\UseFromSameNamespaceSniff;
use SlevomatCodingStandard\Sniffs\Numbers\RequireNumericLiteralSeparatorSniff;
use SlevomatCodingStandard\Sniffs\PHP\UselessParenthesesSniff;
use SlevomatCodingStandard\Sniffs\TypeHints\UselessConstantTypeHintSniff;
use Symplify\CodingStandard\Fixer\ArrayNotation\ArrayListItemNewlineFixer;
use Symplify\CodingStandard\Fixer\ArrayNotation\ArrayOpenerAndCloserNewlineFixer;
use Symplify\EasyCodingStandard\Config\ECSConfig;
use Symplify\EasyCodingStandard\ValueObject\Option;
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;

return static function (ECSConfig $ECSConfig): void {
$ECSConfig->import(SetList::CLEAN_CODE);
$ECSConfig->import(SetList::PSR_12);
$ECSConfig->import(SetList::COMMON);

$parameters = $ECSConfig->parameters();
$parameters->set(Option::PARALLEL, true);
$parameters->set(Option::DEBUG, true);

$ECSConfig->cacheDirectory(__DIR__ . '/var/ecs_cache');

$ECSConfig->skip([
Configuration::class,
PhpdocTypesOrderFixer::class,
return ECSConfig::configure()
->withPreparedSets(psr12: true, common: true, cleanCode: true)
->withParallel()
->withCache(directory: __DIR__ . '/var/ecs_cache')
->withPaths(paths: [
__DIR__ . '/src',
__DIR__ . '/tests',
])
->withSkip([
ArrayListItemNewlineFixer::class => null,
PhpdocToCommentFixer::class => null,
PhpdocAlignFixer::class => null,
Expand All @@ -74,104 +61,75 @@
DoctrineAnnotationBracesFixer::class => null,
NotOperatorWithSuccessorSpaceFixer::class => null,
UselessParenthesesSniff::class => null,
PhpdocSeparationFixer::class => null, // some bug with infinity applied checker
MethodChainingIndentationFixer::class => ['DependencyInjection/*Configuration.php'],
'SlevomatCodingStandard\Sniffs\Whitespaces\DuplicateSpacesSniff.DuplicateDeclareStrictTypesSpaces' => null,
MethodChainingIndentationFixer::class => ['src/DependencyInjection/*Configuration.php'],
'SlevomatCodingStandard\Sniffs\Classes\UnusedPrivateElementsSniff.WriteOnlyProperty' => ['src/Entity/User.php'],
'SlevomatCodingStandard\Sniffs\Whitespaces\DuplicateSpacesSniff.DuplicateSpaces' => null,
'SlevomatCodingStandard\Sniffs\Commenting\DisallowCommentAfterCodeSniff.DisallowedCommentAfterCode' => null,
PhpdocAnnotationWithoutDotFixer::class => null,
PhpCsFixer\Fixer\Import\NoUnusedImportsFixer::class => null // bug: removes usages of attributes if attributes are in one line i.e. #[OARequest, OAResponse]
]);

$services = $ECSConfig->services();

$services->set(NoSuperfluousPhpdocTagsFixer::class)
->call('configure', [['remove_inheritdoc' => false, 'allow_mixed' => false]]);

$services->set(ClassDefinitionFixer::class)
->call('configure', [['multi_line_extends_each_single_line' => false]]);

$services->set(ClassAttributesSeparationFixer::class)
->call('configure', [['elements' => ['method', 'property']]]);

$services->set(DocCommentSpacingSniff::class)
->property('annotationsGroups', [
'@inheritDoc',
'@template, @extends, @implements, @template-implements @template-extends',
'@var, @psalm-var, @param, @psalm-param',
'@return, @psalm-return',
'@throws',
'@psalm-suppress',
])
;

$services->set(MethodSpacingSniff::class);
$services->set(PropertySpacingSniff::class)
->property('minLinesCountBeforeWithComment', 1)
->property('maxLinesCountBeforeWithComment', 1)
->property('maxLinesCountBeforeWithoutComment', 0);

$services->set(UnusedUsesSniff::class)
->property('searchAnnotations', true);

$services->set(DeclareStrictTypesFixer::class);
$services->set(NoNullPropertyInitializationFixer::class);
$services->set(YodaStyleFixer::class);
$services->set(ArrowFunctionDeclarationSniff::class);
$services->set(StrictCallSniff::class);
$services->set(UseDoesNotStartWithBackslashSniff::class);
$services->set(AlphabeticallySortedUsesSniff::class);
$services->set(RequireNumericLiteralSeparatorSniff::class);
$services->set(UselessParenthesesSniff::class);
$services->set(RequireNullCoalesceOperatorSniff::class);
$services->set(ModernClassNameReferenceSniff::class);
$services->set(UselessInheritDocCommentSniff::class);
$services->set(UseFromSameNamespaceSniff::class);
$services->set(UnusedInheritedVariablePassedToClosureSniff::class);
$services->set(UselessConstantTypeHintSniff::class);
$services->set(DoctrineAnnotationArrayAssignmentFixer::class);
$services->set(DoctrineAnnotationIndentationFixer::class);
$services->set(DoctrineAnnotationSpacesFixer::class);

$services->set(ForbiddenFunctionsSniff::class)
->property('forbiddenFunctions', [
'chop' => 'rtrim',
'close' => 'closedir',
'delete' => 'unset',
'doubleval' => 'floatval',
'fputs' => 'fwrite',
'imap_create' => 'createmailbox',
'imap_fetchtext' => 'body',
'imap_header' => 'headerinfo',
'imap_listmailbox' => 'list',
'imap_listsubscribed' => 'lsub',
'imap_rename' => 'renamemailbox',
'imap_scan' => 'listscan',
'imap_scanmailbox' => 'listscan',
'mt_rand' => 'random_int',
'ini_alter' => 'set',
'is_double' => 'is_float',
'is_integer' => 'is_int',
'is_null' => '!== null',
'is_real' => 'is_float',
'is_writeable' => 'is_writable',
'join' => 'implode',
'key_exists' => 'array_key_exists',
'magic_quotes_runtime' => 'set_magic_quotes_runtime',
'pos' => 'current',
'rand' => 'random_int',
'show_source' => 'file',
'sizeof' => 'count',
'strchr' => 'strstr',
'create_function' => null,
'call_user_func' => null,
'call_user_func_array' => null,
'forward_static_call' => null,
'forward_static_call_array' => null,
]);

$services->set(ArraySyntaxFixer::class)
->call('configure', [['syntax' => 'short']]);

$services->set(ListSyntaxFixer::class)
->call('configure', [['syntax' => 'short']]);
};
])
->withConfiguredRule(NoSuperfluousPhpdocTagsFixer::class, ['remove_inheritdoc' => false, 'allow_mixed' => false])
->withConfiguredRule(ClassDefinitionFixer::class, ['multi_line_extends_each_single_line' => false])
->withConfiguredRule(ClassAttributesSeparationFixer::class, ['elements' => ['method', 'property']])
->withConfiguredRule(ArraySyntaxFixer::class, ['syntax' => 'short'])
->withConfiguredRule(ListSyntaxFixer::class, ['syntax' => 'short'])
->withConfiguredRule(PropertySpacingSniff::class, ['minLinesCountBeforeWithComment' => 1, 'maxLinesCountBeforeWithComment' => 1, 'maxLinesCountBeforeWithoutComment' => 0])
->withConfiguredRule(UnusedUsesSniff::class, ['searchAnnotations' => true])
->withConfiguredRule(YodaStyleFixer::class, ['identical' => true])
->withConfiguredRule(ForbiddenFunctionsSniff::class, ['forbiddenFunctions' => [
'chop' => 'rtrim',
'close' => 'closedir',
'delete' => 'unset',
'doubleval' => 'floatval',
'fputs' => 'fwrite',
'imap_create' => 'createmailbox',
'imap_fetchtext' => 'body',
'imap_header' => 'headerinfo',
'imap_listmailbox' => 'list',
'imap_listsubscribed' => 'lsub',
'imap_rename' => 'renamemailbox',
'imap_scan' => 'listscan',
'imap_scanmailbox' => 'listscan',
'mt_rand' => 'random_int',
'ini_alter' => 'set',
'is_double' => 'is_float',
'is_integer' => 'is_int',
'is_null' => '!== null',
'is_real' => 'is_float',
'is_writeable' => 'is_writable',
'join' => 'implode',
'key_exists' => 'array_key_exists',
'magic_quotes_runtime' => 'set_magic_quotes_runtime',
'pos' => 'current',
'rand' => 'random_int',
'show_source' => 'file',
'sizeof' => 'count',
'strchr' => 'strstr',
'create_function' => null,
'call_user_func' => null,
'call_user_func_array' => null,
'forward_static_call' => null,
'forward_static_call_array' => null,
'dump' => null,
'die' => null,
'dd' => null,
'echo' => null,
'var_dump' => null,
]])
->withRules([
DeclareStrictTypesFixer::class,
NoNullPropertyInitializationFixer::class,
ArrowFunctionDeclarationSniff::class,
StrictCallSniff::class,
UseDoesNotStartWithBackslashSniff::class,
AlphabeticallySortedUsesSniff::class,
RequireNumericLiteralSeparatorSniff::class,
UselessParenthesesSniff::class,
RequireNullCoalesceOperatorSniff::class,
ModernClassNameReferenceSniff::class,
UselessInheritDocCommentSniff::class,
UseFromSameNamespaceSniff::class,
UnusedInheritedVariablePassedToClosureSniff::class,
DoctrineAnnotationArrayAssignmentFixer::class,
DoctrineAnnotationIndentationFixer::class,
DoctrineAnnotationSpacesFixer::class,
])
;
14 changes: 12 additions & 2 deletions src/Configuration/OAuth2Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,25 @@ final class OAuth2Configuration
public const SSO_USER_ID_PLACEHOLDER_URL = '{userId}';
public const SSO_USER_EMAIL_PLACEHOLDER_URL = '{email}';

/**
* @param non-empty-string $ssoClientId
*/
public function __construct(
private readonly string $ssoAccessTokenUrl,
private readonly string $ssoAuthorizeUrl,
private readonly string $ssoRedirectUrl,
private readonly string $ssoUserInfoUrl,
private readonly string $ssoUserInfoByEmailUrl,
/** @var class-string<SsoUserDto> */
/**
* @var class-string<SsoUserDto>
*/
private readonly string $ssoUserInfoClass,
private readonly string $ssoClientId,
private readonly string $ssoClientSecret,
private readonly string $ssoPublicCert,
/** @var list<string> */
/**
* @var list<string>
*/
private readonly array $ssoScopes,
private readonly string $ssoScopeDelimiter,
private readonly bool $considerAccessTokenAsJwt,
Expand Down Expand Up @@ -81,6 +88,9 @@ public function getSsoRedirectUrl(): string
return $this->ssoRedirectUrl;
}

/**
* @return non-empty-string
*/
public function getSsoClientId(): string
{
return $this->ssoClientId;
Expand Down
1 change: 0 additions & 1 deletion src/Controller/Api/AbstractAuthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public function refreshToken(Request $request): Response
return $this->refreshTokenProcess->execute($request);
}


#[Route('logout', name: 'logout', methods: [Request::METHOD_GET])]
#[OA\Response(
response: Response::HTTP_FOUND,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ public function execute(Plain $token): void
throw new InvalidJwtException('Please configure SSO public certificate.');
}

/** @psalm-var non-empty-string $subject */
$subject = (string) $token->claims()->get(RegisteredClaims::SUBJECT);

$constraints = [
new PermittedFor($this->OAuth2Configuration->getSsoClientId()),
new RelatedTo((string) $token->claims()->get(RegisteredClaims::SUBJECT)),
new RelatedTo($subject),
new SignedWith(
JwtAlgorithm::from((string) $token->headers()->get('alg'))->signer(),
InMemory::plainText($this->OAuth2Configuration->getSsoPublicCert())
Expand Down
1 change: 0 additions & 1 deletion src/Model/AccessTokenDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public function __construct(string $accessToken, DateTimeInterface $expiresAt, ?
$this->jwt = $accessTokenJwt;
}


public function getJwt(): ?Plain
{
return $this->jwt;
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/config/authorization.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@
->args([
service('security.user_providers'),
])
->tag('kernel.event_listener', ['event' => CheckPassportEvent::class, 'priority' => 1024, 'method' => 'checkPassport'])
->tag('kernel.event_listener', ['event' => CheckPassportEvent::class, 'priority' => 1_024, 'method' => 'checkPassport'])
;
};
2 changes: 1 addition & 1 deletion src/Serializer/Handler/Handlers/JwtHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function deserialize(mixed $value, Metadata $metadata): ?Plain
return null;
}

if (false === is_string($value)) {
if (false === is_string($value) || '' === $value) {
throw new SerializerException('Value must be a type of valid JWT string');
}

Expand Down
Loading