diff --git a/src/bundle/Controller/SiteAccess/SiteAccessController.php b/src/bundle/Controller/SiteAccess/SiteAccessController.php
new file mode 100644
index 0000000000..e64880c4be
--- /dev/null
+++ b/src/bundle/Controller/SiteAccess/SiteAccessController.php
@@ -0,0 +1,46 @@
+siteAccessResolvers = $siteAccessResolvers;
+ }
+
+ /**
+ * @throws \Psr\Container\ContainerExceptionInterface
+ * @throws \Psr\Container\NotFoundExceptionInterface
+ */
+ public function loadForLocation(Request $request, Location $location): SiteAccessesList
+ {
+ $resolverType = $request->query->get('resolver_type', 'non_admin');
+
+ try {
+ /** @var \Ibexa\AdminUi\Siteaccess\SiteaccessResolverInterface $siteAccessResolver */
+ $siteAccessResolver = $this->siteAccessResolvers->get($resolverType);
+ } catch (NotFoundExceptionInterface $e) {
+ throw new BadRequestException($e->getMessage(), $e->getCode(), $e);
+ }
+
+ return new SiteAccessesList($siteAccessResolver->getSiteAccessesListForLocation($location));
+ }
+}
diff --git a/src/bundle/Resources/config/routing_rest.yaml b/src/bundle/Resources/config/routing_rest.yaml
index 20113ea6d4..4282977378 100644
--- a/src/bundle/Resources/config/routing_rest.yaml
+++ b/src/bundle/Resources/config/routing_rest.yaml
@@ -137,3 +137,14 @@ ibexa.rest.content_type.load_field_definitions_from_expression:
methods: [POST]
options:
expose: true
+
+#
+# Site Access
+#
+
+ibexa.rest.site_access.load_for_location:
+ path: /site-access/by-location/{locationId}
+ controller: 'Ibexa\Bundle\AdminUi\Controller\SiteAccess\SiteAccessController::loadForLocation'
+ methods: [GET]
+ options:
+ expose: true
diff --git a/src/bundle/Resources/config/services/controllers.yaml b/src/bundle/Resources/config/services/controllers.yaml
index ab509005ec..e86dba98e0 100644
--- a/src/bundle/Resources/config/services/controllers.yaml
+++ b/src/bundle/Resources/config/services/controllers.yaml
@@ -265,3 +265,13 @@ services:
$fieldsByExpressionService: '@Ibexa\Contracts\AdminUi\ContentType\ContentTypeFieldsByExpressionServiceInterface'
tags:
- controller.service_arguments
+
+ Ibexa\Bundle\AdminUi\Controller\SiteAccess\SiteAccessController:
+ parent: Ibexa\Rest\Server\Controller
+ autowire: true
+ arguments:
+ $siteAccessResolvers: !tagged_locator
+ tag: 'ibexa.site_access.resolver'
+ index_by: type
+ tags:
+ - controller.service_arguments
diff --git a/src/bundle/Resources/config/services/rest.yaml b/src/bundle/Resources/config/services/rest.yaml
index 0cbc65fd13..98ebcdb3d3 100644
--- a/src/bundle/Resources/config/services/rest.yaml
+++ b/src/bundle/Resources/config/services/rest.yaml
@@ -108,3 +108,10 @@ services:
parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor
tags:
- { name: ibexa.rest.output.value_object.visitor, type: Ibexa\AdminUi\REST\Value\ContentType\FieldDefinitionInfoList }
+ #
+ # Site Accesses
+ #
+ Ibexa\AdminUi\REST\Output\ValueObjectVisitor\SiteAccess\SiteAccessesListVisitor:
+ parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor
+ tags:
+ - { name: ibexa.rest.output.value_object.visitor, type: Ibexa\AdminUi\REST\Value\SiteAccess\SiteAccessesList }
diff --git a/src/bundle/Resources/config/services/siteaccess.yaml b/src/bundle/Resources/config/services/siteaccess.yaml
index 5490a7045e..53e73436aa 100644
--- a/src/bundle/Resources/config/services/siteaccess.yaml
+++ b/src/bundle/Resources/config/services/siteaccess.yaml
@@ -18,6 +18,8 @@ services:
Ibexa\AdminUi\Siteaccess\NonAdminSiteaccessResolver:
arguments:
$siteAccessGroups: '%ibexa.site_access.groups%'
+ tags:
+ - { name: 'ibexa.site_access.resolver', type: 'non_admin' }
Ibexa\AdminUi\Siteaccess\AdminSiteaccessPreviewVoter:
arguments:
diff --git a/src/lib/REST/Output/ValueObjectVisitor/SiteAccess/SiteAccessesListVisitor.php b/src/lib/REST/Output/ValueObjectVisitor/SiteAccess/SiteAccessesListVisitor.php
new file mode 100644
index 0000000000..e99007336a
--- /dev/null
+++ b/src/lib/REST/Output/ValueObjectVisitor/SiteAccess/SiteAccessesListVisitor.php
@@ -0,0 +1,37 @@
+startObjectElement('SiteAccessesList');
+ $visitor->setHeader('Content-Type', $generator->getMediaType('SiteAccessesList'));
+
+ $generator->startList('values');
+ foreach ($data->getSiteAccesses() as $siteAccess) {
+ $generator->startObjectElement('SiteAccess');
+
+ $generator->valueElement('name', $siteAccess->name);
+
+ $generator->endObjectElement('SiteAccess');
+ }
+ $generator->endList('values');
+
+ $generator->endObjectElement('SiteAccessesList');
+ }
+}
diff --git a/src/lib/REST/Value/SiteAccess/SiteAccessesList.php b/src/lib/REST/Value/SiteAccess/SiteAccessesList.php
new file mode 100644
index 0000000000..bd8ab6d1de
--- /dev/null
+++ b/src/lib/REST/Value/SiteAccess/SiteAccessesList.php
@@ -0,0 +1,33 @@
+siteAccesses = $siteAccesses;
+ }
+
+ /**
+ * @return \Ibexa\Core\MVC\Symfony\SiteAccess[]
+ */
+ public function getSiteAccesses(): array
+ {
+ return $this->siteAccesses;
+ }
+}
diff --git a/tests/integration/REST/GetSiteAccessesListTest.php b/tests/integration/REST/GetSiteAccessesListTest.php
new file mode 100644
index 0000000000..0c41e8c682
--- /dev/null
+++ b/tests/integration/REST/GetSiteAccessesListTest.php
@@ -0,0 +1,57 @@
+getIbexaTestCore()->setAdministratorUser();
+
+ $this->loginAsUser(
+ $this->createUserWithPolicies(
+ 'editor',
+ [
+ 'user/login' => [],
+ 'content/read' => [],
+ 'content/versionread' => [],
+ ]
+ )
+ );
+ }
+
+ protected static function getEndpointsToTest(): iterable
+ {
+ foreach (self::REQUIRED_FORMATS as $format) {
+ yield new EndpointRequestDefinition(
+ 'GET',
+ '/api/ibexa/v2/site-access/by-location/2?resolver_type=non_admin',
+ 'SiteAccessesList',
+ "application/vnd.ibexa.api.SiteAccessesList+$format",
+ ['HTTP_X-SiteAccess' => 'admin'],
+ null,
+ null,
+ 'SiteAccessesList'
+ );
+ }
+ }
+}
diff --git a/tests/integration/Resources/REST/Schemas/SiteAccessesList.json b/tests/integration/Resources/REST/Schemas/SiteAccessesList.json
new file mode 100644
index 0000000000..c99d90396c
--- /dev/null
+++ b/tests/integration/Resources/REST/Schemas/SiteAccessesList.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "type": "object",
+ "properties": {
+ "SiteAccessesList": {
+ "type": "object",
+ "properties": {
+ "_media-type": {
+ "type": "string"
+ },
+ "values": {
+ "type": "array",
+ "items": [
+ {
+ "type": "object",
+ "properties": {
+ "_media-type": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "_media-type",
+ "name"
+ ]
+ }
+ ]
+ }
+ },
+ "required": [
+ "_media-type",
+ "values"
+ ]
+ }
+ },
+ "required": [
+ "SiteAccessesList"
+ ]
+}
diff --git a/tests/integration/Resources/REST/Schemas/SiteAccessesList.xsd b/tests/integration/Resources/REST/Schemas/SiteAccessesList.xsd
new file mode 100644
index 0000000000..0210f9c2a2
--- /dev/null
+++ b/tests/integration/Resources/REST/Schemas/SiteAccessesList.xsd
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/integration/Resources/REST/Snapshots/SiteAccessesList.json b/tests/integration/Resources/REST/Snapshots/SiteAccessesList.json
new file mode 100644
index 0000000000..fbf576070d
--- /dev/null
+++ b/tests/integration/Resources/REST/Snapshots/SiteAccessesList.json
@@ -0,0 +1,27 @@
+{
+ "SiteAccessesList": {
+ "_media-type": "application/vnd.ibexa.api.SiteAccessesList+json",
+ "values": [
+ {
+ "_media-type": "application/vnd.ibexa.api.SiteAccess+json",
+ "name": "__default_site_access__"
+ },
+ {
+ "_media-type": "application/vnd.ibexa.api.SiteAccess+json",
+ "name": "__second_site_access__"
+ },
+ {
+ "_media-type": "application/vnd.ibexa.api.SiteAccess+json",
+ "name": "ger"
+ },
+ {
+ "_media-type": "application/vnd.ibexa.api.SiteAccess+json",
+ "name": "eng"
+ },
+ {
+ "_media-type": "application/vnd.ibexa.api.SiteAccess+json",
+ "name": "ku6\"H"
+ }
+ ]
+ }
+}
diff --git a/tests/integration/Resources/REST/Snapshots/SiteAccessesList.xml b/tests/integration/Resources/REST/Snapshots/SiteAccessesList.xml
new file mode 100644
index 0000000000..c03df4e75e
--- /dev/null
+++ b/tests/integration/Resources/REST/Snapshots/SiteAccessesList.xml
@@ -0,0 +1,18 @@
+
+
+
+ __default_site_access__
+
+
+ __second_site_access__
+
+
+ ger
+
+
+ eng
+
+
+ ku6"H
+
+