Skip to content

Commit afd71af

Browse files
authored
IBX-9266: Added REST endpoint loading available site accesses for location (#1759)
1 parent ff14645 commit afd71af

File tree

12 files changed

+307
-0
lines changed

12 files changed

+307
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Bundle\AdminUi\Controller\SiteAccess;
10+
11+
use Ibexa\AdminUi\REST\Value\SiteAccess\SiteAccessesList;
12+
use Ibexa\Contracts\Core\Repository\Values\Content\Location;
13+
use Ibexa\Rest\Server\Controller as RestController;
14+
use Ibexa\Rest\Server\Exceptions\BadRequestException;
15+
use Psr\Container\NotFoundExceptionInterface;
16+
use Symfony\Component\DependencyInjection\ServiceLocator;
17+
use Symfony\Component\HttpFoundation\Request;
18+
19+
final class SiteAccessController extends RestController
20+
{
21+
private ServiceLocator $siteAccessResolvers;
22+
23+
public function __construct(
24+
ServiceLocator $siteAccessResolvers
25+
) {
26+
$this->siteAccessResolvers = $siteAccessResolvers;
27+
}
28+
29+
/**
30+
* @throws \Psr\Container\ContainerExceptionInterface
31+
* @throws \Psr\Container\NotFoundExceptionInterface
32+
*/
33+
public function loadForLocation(Request $request, Location $location): SiteAccessesList
34+
{
35+
$resolverType = $request->query->get('resolver_type', 'non_admin');
36+
37+
try {
38+
/** @var \Ibexa\AdminUi\Siteaccess\SiteaccessResolverInterface $siteAccessResolver */
39+
$siteAccessResolver = $this->siteAccessResolvers->get($resolverType);
40+
} catch (NotFoundExceptionInterface $e) {
41+
throw new BadRequestException($e->getMessage(), $e->getCode(), $e);
42+
}
43+
44+
return new SiteAccessesList($siteAccessResolver->getSiteAccessesListForLocation($location));
45+
}
46+
}

src/bundle/Resources/config/routing_rest.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,14 @@ ibexa.rest.content_type.load_field_definitions_from_expression:
137137
methods: [POST]
138138
options:
139139
expose: true
140+
141+
#
142+
# Site Access
143+
#
144+
145+
ibexa.rest.site_access.load_for_location:
146+
path: /site-access/by-location/{locationId}
147+
controller: 'Ibexa\Bundle\AdminUi\Controller\SiteAccess\SiteAccessController::loadForLocation'
148+
methods: [GET]
149+
options:
150+
expose: true

src/bundle/Resources/config/services/controllers.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,13 @@ services:
265265
$fieldsByExpressionService: '@Ibexa\Contracts\AdminUi\ContentType\ContentTypeFieldsByExpressionServiceInterface'
266266
tags:
267267
- controller.service_arguments
268+
269+
Ibexa\Bundle\AdminUi\Controller\SiteAccess\SiteAccessController:
270+
parent: Ibexa\Rest\Server\Controller
271+
autowire: true
272+
arguments:
273+
$siteAccessResolvers: !tagged_locator
274+
tag: 'ibexa.site_access.resolver'
275+
index_by: type
276+
tags:
277+
- controller.service_arguments

src/bundle/Resources/config/services/rest.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,10 @@ services:
108108
parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor
109109
tags:
110110
- { name: ibexa.rest.output.value_object.visitor, type: Ibexa\AdminUi\REST\Value\ContentType\FieldDefinitionInfoList }
111+
#
112+
# Site Accesses
113+
#
114+
Ibexa\AdminUi\REST\Output\ValueObjectVisitor\SiteAccess\SiteAccessesListVisitor:
115+
parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor
116+
tags:
117+
- { name: ibexa.rest.output.value_object.visitor, type: Ibexa\AdminUi\REST\Value\SiteAccess\SiteAccessesList }

src/bundle/Resources/config/services/siteaccess.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ services:
1818
Ibexa\AdminUi\Siteaccess\NonAdminSiteaccessResolver:
1919
arguments:
2020
$siteAccessGroups: '%ibexa.site_access.groups%'
21+
tags:
22+
- { name: 'ibexa.site_access.resolver', type: 'non_admin' }
2123

2224
Ibexa\AdminUi\Siteaccess\AdminSiteaccessPreviewVoter:
2325
arguments:
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\AdminUi\REST\Output\ValueObjectVisitor\SiteAccess;
10+
11+
use Ibexa\Contracts\Rest\Output\Generator;
12+
use Ibexa\Contracts\Rest\Output\ValueObjectVisitor;
13+
use Ibexa\Contracts\Rest\Output\Visitor;
14+
15+
final class SiteAccessesListVisitor extends ValueObjectVisitor
16+
{
17+
/**
18+
* @param \Ibexa\AdminUi\REST\Value\SiteAccess\SiteAccessesList $data
19+
*/
20+
public function visit(Visitor $visitor, Generator $generator, $data): void
21+
{
22+
$generator->startObjectElement('SiteAccessesList');
23+
$visitor->setHeader('Content-Type', $generator->getMediaType('SiteAccessesList'));
24+
25+
$generator->startList('values');
26+
foreach ($data->getSiteAccesses() as $siteAccess) {
27+
$generator->startObjectElement('SiteAccess');
28+
29+
$generator->valueElement('name', $siteAccess->name);
30+
31+
$generator->endObjectElement('SiteAccess');
32+
}
33+
$generator->endList('values');
34+
35+
$generator->endObjectElement('SiteAccessesList');
36+
}
37+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\AdminUi\REST\Value\SiteAccess;
10+
11+
use Ibexa\Rest\Value as RestValue;
12+
13+
final class SiteAccessesList extends RestValue
14+
{
15+
/** @var \Ibexa\Core\MVC\Symfony\SiteAccess[] */
16+
private array $siteAccesses;
17+
18+
/**
19+
* @param \Ibexa\Core\MVC\Symfony\SiteAccess[] $siteAccesses
20+
*/
21+
public function __construct(array $siteAccesses = [])
22+
{
23+
$this->siteAccesses = $siteAccesses;
24+
}
25+
26+
/**
27+
* @return \Ibexa\Core\MVC\Symfony\SiteAccess[]
28+
*/
29+
public function getSiteAccesses(): array
30+
{
31+
return $this->siteAccesses;
32+
}
33+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Tests\Integration\AdminUi\REST;
10+
11+
use Ibexa\Contracts\Test\Rest\Request\Value\EndpointRequestDefinition;
12+
13+
/**
14+
* Coverage for /site-access/by-location/{locationId} REST endpoint.
15+
*/
16+
final class GetSiteAccessesListTest extends BaseAdminUiRestWebTestCase
17+
{
18+
/**
19+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
20+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
21+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\ForbiddenException
22+
*/
23+
protected function setUp(): void
24+
{
25+
parent::setUp();
26+
27+
// to create a new user before logging-in via REST
28+
$this->getIbexaTestCore()->setAdministratorUser();
29+
30+
$this->loginAsUser(
31+
$this->createUserWithPolicies(
32+
'editor',
33+
[
34+
'user/login' => [],
35+
'content/read' => [],
36+
'content/versionread' => [],
37+
]
38+
)
39+
);
40+
}
41+
42+
protected static function getEndpointsToTest(): iterable
43+
{
44+
foreach (self::REQUIRED_FORMATS as $format) {
45+
yield new EndpointRequestDefinition(
46+
'GET',
47+
'/api/ibexa/v2/site-access/by-location/2?resolver_type=non_admin',
48+
'SiteAccessesList',
49+
"application/vnd.ibexa.api.SiteAccessesList+$format",
50+
['HTTP_X-SiteAccess' => 'admin'],
51+
null,
52+
null,
53+
'SiteAccessesList'
54+
);
55+
}
56+
}
57+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"type": "object",
4+
"properties": {
5+
"SiteAccessesList": {
6+
"type": "object",
7+
"properties": {
8+
"_media-type": {
9+
"type": "string"
10+
},
11+
"values": {
12+
"type": "array",
13+
"items": [
14+
{
15+
"type": "object",
16+
"properties": {
17+
"_media-type": {
18+
"type": "string"
19+
},
20+
"name": {
21+
"type": "string"
22+
}
23+
},
24+
"required": [
25+
"_media-type",
26+
"name"
27+
]
28+
}
29+
]
30+
}
31+
},
32+
"required": [
33+
"_media-type",
34+
"values"
35+
]
36+
}
37+
},
38+
"required": [
39+
"SiteAccessesList"
40+
]
41+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
3+
<xs:element name="SiteAccessesList">
4+
<xs:complexType>
5+
<xs:sequence>
6+
<xs:element name="SiteAccess" maxOccurs="unbounded" minOccurs="0">
7+
<xs:complexType>
8+
<xs:sequence>
9+
<xs:element name="name" type="xs:string" />
10+
</xs:sequence>
11+
<xs:attribute name="media-type" type="xs:string" use="required" />
12+
</xs:complexType>
13+
</xs:element>
14+
</xs:sequence>
15+
<xs:attribute name="media-type" type="xs:string" use="required" />
16+
</xs:complexType>
17+
</xs:element>
18+
</xs:schema>

0 commit comments

Comments
 (0)