Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/4.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
ciastektk committed Jan 13, 2025
2 parents 89cc199 + d6d83c7 commit 8258dd9
Show file tree
Hide file tree
Showing 16 changed files with 856 additions and 0 deletions.
119 changes: 119 additions & 0 deletions src/bundle/Controller/Permission/UsersWithPermissionInfoController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?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\AdminUi\Controller\Permission;

use Ibexa\AdminUi\Permission\Mapper\UsersWithPermissionInfoMapper;
use Ibexa\AdminUi\Permission\PermissionCheckContextResolverInterface;
use Ibexa\Contracts\Core\Exception\InvalidArgumentException;
use Ibexa\Contracts\Core\Repository\SearchService;
use Ibexa\Contracts\Core\Repository\Values\Content\Query;
use Ibexa\Core\QueryType\QueryType;
use Ibexa\Rest\Server\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;

final class UsersWithPermissionInfoController extends Controller
{
private const PARAM_LIMIT = 'limit';
private const PARAM_OFFSET = 'offset';

private QueryType $userQueryType;

private PermissionCheckContextResolverInterface $permissionCheckContextResolver;

private SearchService $searchService;

private UsersWithPermissionInfoMapper $userWithPermissionsMapper;

private int $limit;

public function __construct(
QueryType $userQueryType,
PermissionCheckContextResolverInterface $permissionCheckContextResolver,
SearchService $searchService,
UsersWithPermissionInfoMapper $userWithPermissionsMapper,
int $limit
) {
$this->userQueryType = $userQueryType;
$this->permissionCheckContextResolver = $permissionCheckContextResolver;
$this->searchService = $searchService;
$this->userWithPermissionsMapper = $userWithPermissionsMapper;
$this->limit = $limit;
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
*/
public function listAction(
Request $request,
string $module,
string $function
): JsonResponse {
$context = $this->permissionCheckContextResolver->resolve($module, $function, $request);
$searchQuery = $this->getQuery(
$request->query,
$context->getCriteria()
);
$users = $this->searchService->findContentInfo($searchQuery, [], false);

$response = $this->userWithPermissionsMapper->mapSearchResults(
$users,
$context,
$module,
$function
);

return new JsonResponse($response);
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
*/
private function getQuery(
ParameterBag $query,
?Query\CriterionInterface $criteria
): Query {
$parameters = [
'phrase' => $query->get('phrase'),
'extra_criteria' => $criteria,
'limit' => $this->limit,
];

if ($query->has(self::PARAM_LIMIT)) {
$limit = $query->getInt(self::PARAM_LIMIT);

if ($limit <= 0) {
throw new InvalidArgumentException(
self::PARAM_LIMIT,
'Value should be greater than zero'
);
}

$parameters[self::PARAM_LIMIT] = $limit;
}

if ($query->has(self::PARAM_OFFSET)) {
$offset = $query->getInt(self::PARAM_OFFSET);

if ($offset < 0) {
throw new InvalidArgumentException(
self::PARAM_OFFSET,
'Value should be greater or equal zero'
);
}

$parameters[self::PARAM_OFFSET] = $offset;
}

return $this->userQueryType->getQuery($parameters);
}
}
13 changes: 13 additions & 0 deletions src/bundle/Resources/config/routing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -971,3 +971,16 @@ ibexa.focus_mode.change:
path: /user/focus-mode
controller: 'Ibexa\Bundle\AdminUi\Controller\User\FocusModeController::changeAction'
methods: [GET, POST]

#
# Users
#
ibexa.permission.users_with_permission_info:
path: /permission/users-with-permission-info/{module}/{function}
controller: 'Ibexa\Bundle\AdminUi\Controller\Permission\UsersWithPermissionInfoController::listAction'
methods: [GET]
options:
expose: true
requirements:
module: \w+
function: \w+
6 changes: 6 additions & 0 deletions src/bundle/Resources/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ imports:
- { resource: services/role_form_mappers.yaml }
- { resource: services/security.yaml }

parameters:
ibexa.admin_ui.load_users_with_permission_info.limit: 10
ibexa.admin_ui.permission_check_context.content.user_content_type_identifiers: [editor]

services:
_defaults:
autowire: true
Expand Down Expand Up @@ -162,3 +166,5 @@ services:
$siteAccessGroups: '%ibexa.site_access.groups%'
tags:
- {name: kernel.event_subscriber}

Ibexa\AdminUi\Permission\Mapper\UsersWithPermissionInfoMapper: ~
8 changes: 8 additions & 0 deletions src/bundle/Resources/config/services/controllers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,11 @@ services:
$imageMappings: '%ibexa.dam_widget.image.mappings%'
tags:
- controller.service_arguments

Ibexa\Bundle\AdminUi\Controller\Permission\UsersWithPermissionInfoController:
parent: Ibexa\Rest\Server\Controller
arguments:
$userQueryType: '@Ibexa\AdminUi\QueryType\UserQueryType'
$limit: '%ibexa.admin_ui.load_users_with_permission_info.limit%'
tags:
- controller.service_arguments
17 changes: 17 additions & 0 deletions src/bundle/Resources/config/services/permissions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,20 @@ services:

Ibexa\AdminUi\Permission\LimitationResolverInterface:
alias: Ibexa\AdminUi\Permission\LimitationResolver

Ibexa\AdminUi\Permission\PermissionCheckContextResolver:
arguments:
$permissionContextProviders: !tagged_iterator ibexa.admin_ui.permission_check_context.provider

Ibexa\AdminUi\Permission\PermissionCheckContextResolverInterface:
alias: Ibexa\AdminUi\Permission\PermissionCheckContextResolver

Ibexa\Contracts\AdminUi\Permission\PermissionCheckContextProviderInterface: ~

Ibexa\AdminUi\Permission\ContextProvider\ContentItemContextProvider:
arguments:
$userContentTypeIdentifiers: '%ibexa.admin_ui.permission_check_context.content.user_content_type_identifiers%'
tags:
-
name: ibexa.admin_ui.permission_check_context.provider
priority: -100
2 changes: 2 additions & 0 deletions src/bundle/Resources/config/services/query_types.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ services:
Ibexa\AdminUi\QueryType\MediaLocationSubtreeQueryType: ~

Ibexa\AdminUi\QueryType\TrashSearchQueryType: ~

Ibexa\AdminUi\QueryType\UserQueryType: ~
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?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\Contracts\AdminUi\Permission;

use Ibexa\Contracts\AdminUi\Values\PermissionCheckContext;
use Symfony\Component\HttpFoundation\Request;

interface PermissionCheckContextProviderInterface
{
public function supports(string $module, string $function): bool;

public function getPermissionCheckContext(string $module, string $function, Request $request): PermissionCheckContext;
}
53 changes: 53 additions & 0 deletions src/contracts/Values/PermissionCheckContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?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\Contracts\AdminUi\Values;

use Ibexa\Contracts\Core\Repository\Values\Content\Query\CriterionInterface;
use Ibexa\Contracts\Core\Repository\Values\ValueObject;

final class PermissionCheckContext
{
private ValueObject $subject;

/** @var array<\Ibexa\Contracts\Core\Repository\Values\ValueObject> */
private array $targets;

private ?CriterionInterface $criteria;

/**
* @param array<\Ibexa\Contracts\Core\Repository\Values\ValueObject> $targets
*/
public function __construct(
ValueObject $subject,
array $targets,
?CriterionInterface $criteria = null
) {
$this->subject = $subject;
$this->targets = $targets;
$this->criteria = $criteria;
}

public function getSubject(): ValueObject
{
return $this->subject;
}

/**
* @return array<\Ibexa\Contracts\Core\Repository\Values\ValueObject>
*/
public function getTargets(): array
{
return $this->targets;
}

public function getCriteria(): ?CriterionInterface
{
return $this->criteria;
}
}
112 changes: 112 additions & 0 deletions src/lib/Permission/ContextProvider/ContentItemContextProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?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\AdminUi\Permission\ContextProvider;

use Ibexa\Contracts\AdminUi\Permission\PermissionCheckContextProviderInterface;
use Ibexa\Contracts\AdminUi\Values\PermissionCheckContext;
use Ibexa\Contracts\Core\Exception\InvalidArgumentException;
use Ibexa\Contracts\Core\Repository\ContentService;
use Ibexa\Contracts\Core\Repository\LocationService;
use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\CriterionInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;

final class ContentItemContextProvider implements PermissionCheckContextProviderInterface
{
private const POLICY_MODULE_CONTENT = 'content';

private ContentService $contentService;

private LocationService $locationService;

/** @var array<string> */
private array $userContentTypeIdentifiers;

/**
* @param array<string> $userContentTypeIdentifiers
*/
public function __construct(
ContentService $contentService,
LocationService $locationService,
array $userContentTypeIdentifiers
) {
$this->contentService = $contentService;
$this->locationService = $locationService;
$this->userContentTypeIdentifiers = $userContentTypeIdentifiers;
}

public function supports(string $module, string $function): bool
{
return self::POLICY_MODULE_CONTENT === $module;
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidCriterionArgumentException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
*/
public function getPermissionCheckContext(
string $module,
string $function,
Request $request
): PermissionCheckContext {
$query = $request->query;

$contentInfo = $this->getContentInfo($query);
$targets = $this->getTargets($query);
$criteria = $this->createCriteria();

return new PermissionCheckContext($contentInfo, $targets, $criteria);
}

private function getContentInfo(ParameterBag $query): ContentInfo
{
$contentId = $query->getInt('contentId');

return $this->contentService->loadContentInfo($contentId);
}

/**
* @return array<\Ibexa\Contracts\Core\Repository\Values\ValueObject>
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
* @throws \Ibexa\Contracts\Core\Exception\InvalidArgumentException
*/
private function getTargets(ParameterBag $query): array
{
if (!$query->has('locationId')) {
return [];
}

$locationId = $query->getInt('locationId');
if ($locationId <= 0) {
throw new InvalidArgumentException(
'locationId',
'Expected value should be greater than 0.'
);
}

$location = $this->locationService->loadLocation($locationId);

return [$location];
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidCriterionArgumentException
*/
private function createCriteria(): CriterionInterface
{
$criteria = [new Criterion\ContentTypeIdentifier($this->userContentTypeIdentifiers)];

return new Criterion\LogicalAnd($criteria);
}
}
Loading

0 comments on commit 8258dd9

Please sign in to comment.