Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IBX-3966: Used user_content_type_identifier configuration key inside user service #155

Merged
merged 5 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
4 changes: 3 additions & 1 deletion src/bundle/Core/ApiLoader/RepositoryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ public function buildRepository(
PermissionService $permissionService,
ContentFilteringHandler $contentFilteringHandler,
LocationFilteringHandler $locationFilteringHandler,
PasswordValidatorInterface $passwordValidator
PasswordValidatorInterface $passwordValidator,
ConfigResolverInterface $configResolver
): Repository {
$config = $this->container->get(\Ibexa\Bundle\Core\ApiLoader\RepositoryConfigurationProvider::class)->getRepositoryConfig();

Expand All @@ -114,6 +115,7 @@ public function buildRepository(
$contentFilteringHandler,
$locationFilteringHandler,
$passwordValidator,
$configResolver,
[
'role' => [
'policyMap' => $this->policyMap,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Bundle\Core\DependencyInjection\Configuration\Parser;

use Ibexa\Bundle\Core\DependencyInjection\Configuration\AbstractParser;
use Ibexa\Bundle\Core\DependencyInjection\Configuration\SiteAccessAware\ContextualizerInterface;
use Symfony\Component\Config\Definition\Builder\NodeBuilder;

/**
* @internal
*
* Configuration parser for user identifier configuration.
*
* Example configuration:
* ```yaml
* ibexa:
* system:
* default: # configuration per siteaccess or siteaccess group
* user_content_type_identifier: ['user', 'my_custom_user_identifier']
* ```
*/
final class UserContentTypeIdentifier extends AbstractParser
{
/**
* Adds semantic configuration definition.
*
* @param \Symfony\Component\Config\Definition\Builder\NodeBuilder $nodeBuilder Node just under ezpublish.system.<siteaccess>
*/
public function addSemanticConfig(NodeBuilder $nodeBuilder)
{
$nodeBuilder
->arrayNode('user_content_type_identifier')
->info('User Content Type identifier configuration.')
->example(['user', 'my_custom_user_identifier'])
->requiresAtLeastOneElement()
->prototype('scalar')->end()
->end();
}

/**
* {@inheritdoc}
*/
public function mapConfig(array &$scopeSettings, $currentScope, ContextualizerInterface $contextualizer): void
ViniTou marked this conversation as resolved.
Show resolved Hide resolved
{
if (empty($scopeSettings['user_content_type_identifier'])) {
return;
}

$contextualizer->setContextualParameter(
'user_content_type_identifier',
$currentScope,
$scopeSettings['user_content_type_identifier']
);
}
}

class_alias(UserContentTypeIdentifier::class, 'EzSystems\EzPlatformAdminUiBundle\DependencyInjection\Configuration\Parser\UserIdentifier');
class_alias(UserContentTypeIdentifier::class, 'Ibexa\Bundle\AdminUi\DependencyInjection\Configuration\Parser\UserIdentifier');
1 change: 1 addition & 0 deletions src/bundle/Core/IbexaCoreBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ public function getContainerExtension()
new ConfigParser\IO(new ComplexSettingParser()),
new ConfigParser\UrlChecker(),
new ConfigParser\TwigVariablesParser(),
new ConfigParser\UserContentTypeIdentifier(),
],
[
new RepositoryConfigParser\Storage(),
Expand Down
1 change: 1 addition & 0 deletions src/bundle/Core/Resources/config/default_settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ parameters:
ibexa.site_access.config.default.storage_dir: "storage" # Where to place new files for storage, it's relative to var directory
ibexa.site_access.config.default.binary_dir: "original"
ibexa.site_access.config.default.anonymous_user_id: 10 # The ID of the user to be used for everyone who is not logged in
ibexa.site_access.config.default.user_content_type_identifier: ['user']
ibexa.site_access.config.default.api_keys: { google_maps: ~ } # Google Maps APIs v3 key (https://developers.google.com/maps/documentation/javascript/get-api-key)

# IO
Expand Down
4 changes: 4 additions & 0 deletions src/lib/Base/Container/ApiLoader/RepositoryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Ibexa\Contracts\Core\Repository\Strategy\ContentThumbnail\ThumbnailStrategy;
use Ibexa\Contracts\Core\Repository\Validator\ContentValidator;
use Ibexa\Contracts\Core\Search\Handler as SearchHandler;
use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;
use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
use Ibexa\Core\FieldType\FieldTypeRegistry;
use Ibexa\Core\Repository\Helper\RelationProcessor;
Expand Down Expand Up @@ -61,6 +62,7 @@ public function __construct(
* directly to make sure you get an instance wrapped inside Event / Cache / * functionality.
*
* @param string[] $languages
* @param string[] $userContentTypeIdentifierList
ViniTou marked this conversation as resolved.
Show resolved Hide resolved
*/
public function buildRepository(
PersistenceHandler $persistenceHandler,
Expand All @@ -81,6 +83,7 @@ public function buildRepository(
ContentFilteringHandler $contentFilteringHandler,
LocationFilteringHandler $locationFilteringHandler,
PasswordValidatorInterface $passwordValidator,
ConfigResolverInterface $configResolver,
array $languages
): Repository {
return new $this->repositoryClass(
Expand All @@ -103,6 +106,7 @@ public function buildRepository(
$contentFilteringHandler,
$locationFilteringHandler,
$passwordValidator,
$configResolver,
[
'role' => [
'policyMap' => $this->policyMap,
Expand Down
6 changes: 6 additions & 0 deletions src/lib/Repository/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
use Ibexa\Contracts\Core\Repository\UserService as UserServiceInterface;
use Ibexa\Contracts\Core\Repository\Validator\ContentValidator;
use Ibexa\Contracts\Core\Search\Handler as SearchHandler;
use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;
use Ibexa\Core\FieldType\FieldTypeRegistry;
use Ibexa\Core\Repository\Helper\NameSchemaService;
use Ibexa\Core\Repository\Helper\RelationProcessor;
Expand Down Expand Up @@ -263,6 +264,8 @@ class Repository implements RepositoryInterface
/** @var \Ibexa\Core\Repository\User\PasswordValidatorInterface */
private $passwordValidator;

private ConfigResolverInterface $configResolver;

public function __construct(
PersistenceHandler $persistenceHandler,
SearchHandler $searchHandler,
Expand All @@ -283,6 +286,7 @@ public function __construct(
ContentFilteringHandler $contentFilteringHandler,
LocationFilteringHandler $locationFilteringHandler,
PasswordValidatorInterface $passwordValidator,
ConfigResolverInterface $configResolver,
array $serviceSettings = [],
?LoggerInterface $logger = null
) {
Expand Down Expand Up @@ -332,6 +336,7 @@ public function __construct(
$this->contentMapper = $contentMapper;
$this->contentValidator = $contentValidator;
$this->passwordValidator = $passwordValidator;
$this->configResolver = $configResolver;
}

/**
Expand Down Expand Up @@ -523,6 +528,7 @@ public function getUserService(): UserServiceInterface
$this->persistenceHandler->locationHandler(),
$this->passwordHashService,
$this->passwordValidator,
$this->configResolver,
$this->serviceSettings['user']
);

Expand Down
35 changes: 25 additions & 10 deletions src/lib/Repository/UserService.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Ibexa\Contracts\Core\Repository\Values\Content\Location;
use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\ContentTypeId as CriterionContentTypeId;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\ContentTypeIdentifier as CriterionContentTypeIdentifier;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\LocationId as CriterionLocationId;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\LogicalAnd as CriterionLogicalAnd;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\ParentLocationId as CriterionParentLocationId;
Expand All @@ -41,6 +42,7 @@
use Ibexa\Contracts\Core\Repository\Values\User\UserGroupUpdateStruct;
use Ibexa\Contracts\Core\Repository\Values\User\UserTokenUpdateStruct;
use Ibexa\Contracts\Core\Repository\Values\User\UserUpdateStruct;
use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;
use Ibexa\Core\Base\Exceptions\BadStateException;
use Ibexa\Core\Base\Exceptions\ContentFieldValidationException;
use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
Expand Down Expand Up @@ -90,6 +92,8 @@ class UserService implements UserServiceInterface
/** @var \Ibexa\Core\Repository\User\PasswordValidatorInterface */
private $passwordValidator;

private ConfigResolverInterface $configResolver;

public function setLogger(LoggerInterface $logger = null)
{
$this->logger = $logger;
Expand All @@ -105,6 +109,7 @@ public function __construct(
LocationHandler $locationHandler,
PasswordHashService $passwordHashGenerator,
PasswordValidatorInterface $passwordValidator,
ConfigResolverInterface $configResolver,
array $settings = []
) {
$this->repository = $repository;
Expand All @@ -114,13 +119,14 @@ public function __construct(
// Union makes sure default settings are ignored if provided in argument
$this->settings = $settings + [
'defaultUserPlacement' => 12,
'userClassID' => 4, // @todo Rename this settings to swap out "Class" for "Type"
'userClassID' => 4, // @deprecated, use `user_content_type_identifier` configuration instead
'userGroupClassID' => 3,
'hashType' => $passwordHashGenerator->getDefaultHashType(),
'siteName' => 'ibexa.co',
];
$this->passwordHashService = $passwordHashGenerator;
$this->passwordValidator = $passwordValidator;
$this->configResolver = $configResolver;
}

/**
Expand Down Expand Up @@ -1045,7 +1051,7 @@ public function loadUsersOfUserGroup(

$searchQuery->filter = new CriterionLogicalAnd(
[
new CriterionContentTypeId($this->settings['userClassID']),
new CriterionContentTypeIdentifier($this->getUserContentTypeIdentifiers()),
new CriterionParentLocationId($mainGroupLocation->id),
]
);
Expand Down Expand Up @@ -1077,7 +1083,11 @@ public function loadUsersOfUserGroup(
public function isUser(APIContent $content): bool
{
// First check against config for fast check
if ($this->settings['userClassID'] == $content->getVersionInfo()->getContentInfo()->contentTypeId) {
if (in_array(
$content->getVersionInfo()->getContentInfo()->getContentType()->identifier,
$this->getUserContentTypeIdentifiers(),
true
)) {
return true;
}

Expand Down Expand Up @@ -1114,9 +1124,9 @@ public function isUserGroup(APIContent $content): bool
public function newUserCreateStruct(string $login, string $email, string $password, string $mainLanguageCode, ?ContentType $contentType = null): APIUserCreateStruct
{
if ($contentType === null) {
$contentType = $this->repository->getContentTypeService()->loadContentType(
$this->settings['userClassID']
);
$userContentTypeIdentifiers = $this->getUserContentTypeIdentifiers();
$defaultIdentifier = reset($userContentTypeIdentifiers);
$contentType = $this->repository->getContentTypeService()->loadContentTypeByIdentifier($defaultIdentifier);
}

$fieldDefIdentifier = '';
Expand Down Expand Up @@ -1206,10 +1216,9 @@ public function validatePassword(string $password, PasswordValidationContext $co
$errors = [];

if ($context === null) {
$contentType = $this->repository->getContentTypeService()->loadContentType(
$this->settings['userClassID']
);

$userContentTypeIdentifiers = $this->getUserContentTypeIdentifiers();
$defaultIdentifier = reset($userContentTypeIdentifiers);
$contentType = $this->repository->getContentTypeService()->loadContentTypeByIdentifier($defaultIdentifier);
$context = new PasswordValidationContext([
'contentType' => $contentType,
]);
Expand Down Expand Up @@ -1404,6 +1413,12 @@ private function getDateTime(?int $timestamp): ?DateTimeInterface

return null;
}

/** @return string[] */
private function getUserContentTypeIdentifiers(): array
{
return $this->configResolver->getParameter('user_content_type_identifier');
}
ViniTou marked this conversation as resolved.
Show resolved Hide resolved
}

class_alias(UserService::class, 'eZ\Publish\Core\Repository\UserService');
1 change: 1 addition & 0 deletions src/lib/Resources/settings/repository/inner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ services:
- '@Ibexa\Contracts\Core\Persistence\Filter\Content\Handler'
- '@Ibexa\Contracts\Core\Persistence\Filter\Location\Handler'
- '@Ibexa\Core\Repository\User\PasswordValidatorInterface'
- '@ibexa.config.resolver'
- '%languages%'

Ibexa\Core\Repository\ContentService:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ parameters:
name_field_identifier: name
parent_location_id: 51

ibexa.site_access.config.default.user_content_type_identifier: ['user']

services:
Ibexa\Core\FieldType\ImageAsset\AssetMapper:
arguments:
Expand Down
2 changes: 2 additions & 0 deletions tests/lib/Repository/Service/Mock/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Ibexa\Contracts\Core\Repository\Strategy\ContentThumbnail\ThumbnailStrategy;
use Ibexa\Contracts\Core\Repository\Validator\ContentValidator;
use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo;
use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;
use Ibexa\Core\FieldType\FieldTypeRegistry;
use Ibexa\Core\Repository\FieldTypeService;
use Ibexa\Core\Repository\Helper\RelationProcessor;
Expand Down Expand Up @@ -124,6 +125,7 @@ protected function getRepository(array $serviceSettings = [])
$this->getContentFilteringHandlerMock(),
$this->getLocationFilteringHandlerMock(),
$this->createMock(PasswordValidatorInterface::class),
$this->createMock(ConfigResolverInterface::class),
$serviceSettings,
);

Expand Down
2 changes: 2 additions & 0 deletions tests/lib/Repository/Service/Mock/UserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo as APIContentInfo;
use Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo as APIVersionInfo;
use Ibexa\Contracts\Core\Repository\Values\User\User as APIUser;
use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;
use Ibexa\Core\Repository\User\PasswordValidatorInterface;
use Ibexa\Core\Repository\UserService;
use Ibexa\Tests\Core\Repository\Service\Mock\Base as BaseServiceMockTest;
Expand Down Expand Up @@ -155,6 +156,7 @@ protected function getPartlyMockedUserService(array $methods = null)
$this->getPersistenceMock()->locationHandler(),
$this->createMock(PasswordHashService::class),
$this->createMock(PasswordValidatorInterface::class),
$this->createMock(ConfigResolverInterface::class),
]
)
->getMock();
Expand Down