diff --git a/.github/workflows/add-pr-labels.yml b/.github/workflows/add-pr-labels.yml
index 1c492a3dd09..68add971b34 100644
--- a/.github/workflows/add-pr-labels.yml
+++ b/.github/workflows/add-pr-labels.yml
@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Maybe remove base branch label
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4da0d3a9579..7ab68071717 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -83,7 +83,7 @@ jobs:
working-directory: .
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
path: ${{ env.NEOS_FOLDER }}
@@ -96,7 +96,7 @@ jobs:
ini-values: date.timezone="Africa/Tunis", opcache.fast_shutdown=0, apc.enable_cli=on
- name: Checkout development distribution
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
repository: neos/neos-development-distribution
ref: ${{ env.NEOS_TARGET_VERSION }}
@@ -113,7 +113,7 @@ jobs:
- name: Cache Composer packages
id: composer-cache
- uses: actions/cache@v2
+ uses: actions/cache@v4
with:
path: |
~/.cache/composer
diff --git a/.github/workflows/doctum.yml b/.github/workflows/doctum.yml
index eef9ac3bf07..c972fbdb930 100644
--- a/.github/workflows/doctum.yml
+++ b/.github/workflows/doctum.yml
@@ -9,7 +9,7 @@ jobs:
build-api-docs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Build API documentation
uses: sudo-bot/action-doctum@v5
@@ -20,7 +20,7 @@ jobs:
cli-args: "--output-format=github --no-ansi --no-progress --ignore-parse-errors --only-version=${{ github.ref_name }}"
- name: Check out documentation site
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
repository: neos/neos.github.io
path: docs-site
diff --git a/.github/workflows/postgresql-versions.yml b/.github/workflows/postgresql-versions.yml
index 9e0a6a27eea..acc58643831 100644
--- a/.github/workflows/postgresql-versions.yml
+++ b/.github/workflows/postgresql-versions.yml
@@ -67,7 +67,7 @@ jobs:
working-directory: .
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
path: ${{ env.NEOS_FOLDER }}
@@ -80,7 +80,7 @@ jobs:
ini-values: date.timezone="Africa/Tunis", opcache.fast_shutdown=0, apc.enable_cli=on
- name: Checkout development distribution
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
repository: neos/neos-development-distribution
ref: ${{ env.NEOS_TARGET_VERSION }}
@@ -102,7 +102,7 @@ jobs:
- name: Cache Composer packages
id: composer-cache
- uses: actions/cache@v2
+ uses: actions/cache@v4
with:
path: |
~/.cache/composer
diff --git a/Neos.ContentRepository/Classes/Domain/Model/Node.php b/Neos.ContentRepository/Classes/Domain/Model/Node.php
index 13909e0aebd..6f6b0df8882 100644
--- a/Neos.ContentRepository/Classes/Domain/Model/Node.php
+++ b/Neos.ContentRepository/Classes/Domain/Model/Node.php
@@ -1743,6 +1743,10 @@ protected function createRecursiveCopy(NodeInterface $referenceNode, string $nod
}
/** @var $childNode Node */
foreach ($this->getChildNodes() as $childNode) {
+ // Don't copy removed nodes
+ if ($childNode->isRemoved()) {
+ continue;
+ }
// Prevent recursive copy when copying into itself
if ($childNode->getIdentifier() !== $copiedNode->getIdentifier()) {
$childNode->copyIntoInternal($copiedNode, $childNode->getName(), $detachedCopy);
diff --git a/Neos.ContentRepository/Classes/Domain/Model/NodeData.php b/Neos.ContentRepository/Classes/Domain/Model/NodeData.php
index ca5d7d581e2..c80d2c816e1 100644
--- a/Neos.ContentRepository/Classes/Domain/Model/NodeData.php
+++ b/Neos.ContentRepository/Classes/Domain/Model/NodeData.php
@@ -771,6 +771,7 @@ public function similarize(AbstractNodeData $sourceNode, $isCopy = false)
}
if ($sourceNode instanceof NodeData) {
$propertyNames[] = 'index';
+ $propertyNames[] = 'removed';
}
foreach ($propertyNames as $propertyName) {
ObjectAccess::setProperty($this, $propertyName, ObjectAccess::getProperty($sourceNode, $propertyName));
diff --git a/Neos.ContentRepository/Tests/Functional/Domain/NodesTest.php b/Neos.ContentRepository/Tests/Functional/Domain/NodesTest.php
index e173472a921..b750481a668 100644
--- a/Neos.ContentRepository/Tests/Functional/Domain/NodesTest.php
+++ b/Neos.ContentRepository/Tests/Functional/Domain/NodesTest.php
@@ -259,6 +259,34 @@ public function removedNodesAreNotCountedAsChildNodes()
self::assertFalse($rootNode->hasChildNodes(), 'Third check.');
}
+ /**
+ * @test
+ */
+ public function removedChildNodesAreNotCopied()
+ {
+ $rootNode = $this->context->getRootNode();
+ $parentNode = $rootNode->createNode('parent');
+ $parentNode->createNode('child');
+
+ $context = $this->contextFactory->create([
+ 'workspaceName' => 'user-admin',
+ 'removedContentShown' => true,
+ ]);
+ $this->persistenceManager->persistAll();
+
+ $rootNode = $context->getRootNode();
+ $parentNode = $rootNode->getNode('parent');
+ self::assertTrue($parentNode->hasChildNodes(), 'Parent node should have child nodes, before they are removed');
+
+ $parentNode->getNode('child')->remove();
+ $this->persistenceManager->persistAll();
+
+ $parentNode = $rootNode->getNode('parent');
+ $parentClone = $parentNode->copyInto($rootNode, 'parent-clone');
+
+ self::assertFalse($parentClone->hasChildNodes(), 'Copied parent node should not have any child nodes');
+ }
+
/**
* @test
*/
diff --git a/Neos.Media.Browser/Classes/Controller/AssetController.php b/Neos.Media.Browser/Classes/Controller/AssetController.php
index e49dc7aef29..f4527c0aabc 100644
--- a/Neos.Media.Browser/Classes/Controller/AssetController.php
+++ b/Neos.Media.Browser/Classes/Controller/AssetController.php
@@ -70,8 +70,11 @@
*/
class AssetController extends ActionController
{
- use CreateContentContextTrait;
use BackendUserTranslationTrait;
+ use BackendUserTranslationTrait {
+ BackendUserTranslationTrait::initializeObject as backendUserTranslationTraitInitializeObject;
+ }
+ use CreateContentContextTrait;
use AddTranslatedFlashMessageTrait;
protected const TAG_GIVEN = 0;
@@ -170,6 +173,8 @@ class AssetController extends ActionController
*/
public function initializeObject(): void
{
+ $this->backendUserTranslationTraitInitializeObject();
+
$domain = $this->domainRepository->findOneByActiveRequest();
// Set active asset collection to the current site's asset collection, if it has one, on the first view if a matching domain is found
diff --git a/Neos.Media.Browser/Resources/Private/Layouts/Default.html b/Neos.Media.Browser/Resources/Private/Layouts/Default.html
index bad63b5e40c..63201d802b1 100644
--- a/Neos.Media.Browser/Resources/Private/Layouts/Default.html
+++ b/Neos.Media.Browser/Resources/Private/Layouts/Default.html
@@ -23,7 +23,7 @@
-
+
diff --git a/Neos.Media.Browser/Resources/Public/JavaScript/select.js b/Neos.Media.Browser/Resources/Public/JavaScript/select.js
index c62e95a1743..aaf3b823f5d 100644
--- a/Neos.Media.Browser/Resources/Public/JavaScript/select.js
+++ b/Neos.Media.Browser/Resources/Public/JavaScript/select.js
@@ -1,32 +1,84 @@
-window.addEventListener('DOMContentLoaded', (event) => {
- $(function() {
- if (window.parent !== window && window.parent.NeosMediaBrowserCallbacks) {
- // we are inside iframe
- $('.asset-list').on('click', '[data-asset-identifier]', function(e) {
- if (
- $(e.target).closest('a, button').not('[data-asset-identifier]').length === 0 &&
- window.parent.NeosMediaBrowserCallbacks &&
- typeof window.parent.NeosMediaBrowserCallbacks.assetChosen === 'function'
- ) {
- let localAssetIdentifier = $(this).attr('data-local-asset-identifier');
- if (localAssetIdentifier !== '') {
- window.parent.NeosMediaBrowserCallbacks.assetChosen(localAssetIdentifier);
- } else {
- $.post(
- $('link[rel="neos-media-browser-service-assetproxies-import"]').attr('href'),
- {
- assetSourceIdentifier: $(this).attr('data-asset-source-identifier'),
- assetIdentifier: $(this).attr('data-asset-identifier'),
- __csrfToken: $('body').attr('data-csrf-token')
- },
- function(data) {
- window.parent.NeosMediaBrowserCallbacks.assetChosen(data.localAssetIdentifier);
- }
- );
- }
- e.preventDefault();
- }
- });
- }
- });
+window.addEventListener('DOMContentLoaded', () => {
+ (function () {
+ const NeosMediaBrowserCallbacks = window.parent.NeosMediaBrowserCallbacks;
+ const NeosCMS = window.NeosCMS;
+
+ if (window.parent === window || !NeosCMS || !NeosMediaBrowserCallbacks || typeof NeosMediaBrowserCallbacks.assetChosen !== 'function') {
+ return;
+ }
+
+ function importAsset(asset) {
+ const params = new URLSearchParams();
+ params.append('assetSourceIdentifier', asset.dataset.assetSourceIdentifier);
+ params.append('assetIdentifier', asset.dataset.assetIdentifier);
+ params.append('__csrfToken', document.querySelector('body').dataset.csrfToken);
+
+ fetch(
+ document
+ .querySelector('link[rel="neos-media-browser-service-assetproxies-import"]')
+ .getAttribute('href'),
+ {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ },
+ method: 'POST',
+ credentials: 'include',
+ body: params.toString(),
+ }
+ )
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ return response.json();
+ })
+ .then((data) => {
+ NeosMediaBrowserCallbacks.assetChosen(data.localAssetIdentifier);
+ asset.removeAttribute('data-import-in-process');
+ })
+ .catch((error) => {
+ NeosCMS.Notification.error(NeosCMS.I18n.translate(
+ 'assetImport.importError',
+ 'Asset could not be imported. Please try again.',
+ 'Neos.Media.Browser'
+ ), error);
+ console.error('Error:', error);
+ })
+ }
+
+ const assets = document.querySelectorAll('[data-asset-identifier]');
+ assets.forEach((asset) => {
+ asset.addEventListener('click', (e) => {
+ const assetLink = e.target.closest('a[data-asset-identifier], button[data-asset-identifier]');
+ if (!assetLink) {
+ return;
+ }
+
+ const localAssetIdentifier = asset.dataset.localAssetIdentifier;
+ if (localAssetIdentifier !== '' && !NeosCMS.Helper.isNil(localAssetIdentifier)) {
+ NeosMediaBrowserCallbacks.assetChosen(localAssetIdentifier);
+ } else {
+ if (asset.dataset.importInProcess !== 'true') {
+ asset.dataset.importInProcess = 'true';
+ const message = NeosCMS.I18n.translate(
+ 'assetImport.importInfo',
+ 'Asset is being imported. Please wait.',
+ 'Neos.Media.Browser'
+ );
+ NeosCMS.Notification.ok(message);
+
+ importAsset(asset);
+ } else {
+ const message = NeosCMS.I18n.translate(
+ 'assetImport.importInProcess',
+ 'Import still in process. Please wait.',
+ 'Neos.Media.Browser'
+ );
+ NeosCMS.Notification.warning(message);
+ }
+ }
+ e.preventDefault();
+ });
+ });
+ })();
});
diff --git a/Neos.Neos/Classes/Controller/Backend/ModuleController.php b/Neos.Neos/Classes/Controller/Backend/ModuleController.php
index 737a1b84196..163810a3e78 100644
--- a/Neos.Neos/Classes/Controller/Backend/ModuleController.php
+++ b/Neos.Neos/Classes/Controller/Backend/ModuleController.php
@@ -103,6 +103,7 @@ public function indexAction(array $module)
$moduleResponse = new ActionResponse();
$this->dispatcher->dispatch($moduleRequest, $moduleResponse);
+ $moduleResponse->mergeIntoParentResponse($this->response);
if ($moduleResponse->getRedirectUri() !== null) {
$this->redirectToUri($moduleResponse->getRedirectUri(), 0, $moduleResponse->getStatusCode());
diff --git a/Neos.Neos/Classes/Controller/Module/Administration/UsersController.php b/Neos.Neos/Classes/Controller/Module/Administration/UsersController.php
index c91ceee1e55..4ce6f5e5c9e 100644
--- a/Neos.Neos/Classes/Controller/Module/Administration/UsersController.php
+++ b/Neos.Neos/Classes/Controller/Module/Administration/UsersController.php
@@ -553,7 +553,7 @@ protected function getAllowedRoles(): array
$roles = $this->userService->currentUserIsAdministrator() ? $this->policyService->getRoles() : $currentUserRoles;
usort($roles, static function (Role $a, Role $b) {
- return strcmp($a->getName(), $b->getName());
+ return strcmp($a->getLabel(), $b->getLabel());
});
return $roles;
diff --git a/Neos.Neos/Classes/Controller/Service/NodesController.php b/Neos.Neos/Classes/Controller/Service/NodesController.php
index 65dbaf309d4..3579899aae0 100644
--- a/Neos.Neos/Classes/Controller/Service/NodesController.php
+++ b/Neos.Neos/Classes/Controller/Service/NodesController.php
@@ -23,7 +23,6 @@
use Neos\Neos\View\Service\NodeJsonView;
use Neos\Neos\Service\Mapping\NodePropertyConverterService;
use Neos\ContentRepository\Domain\Model\NodeInterface;
-use Neos\ContentRepository\Domain\Model\NodeType;
use Neos\ContentRepository\Domain\Service\NodeTypeManager;
use Neos\ContentRepository\Domain\Utility\NodePaths;
@@ -93,22 +92,9 @@ class NodesController extends ActionController
*/
public function indexAction($searchTerm = '', array $nodeIdentifiers = [], $workspaceName = 'live', array $dimensions = [], array $nodeTypes = ['Neos.Neos:Document'], NodeInterface $contextNode = null)
{
- $searchableNodeTypeNames = [];
- foreach ($nodeTypes as $nodeTypeName) {
- if (!$this->nodeTypeManager->hasNodeType($nodeTypeName)) {
- $this->throwStatus(400, sprintf('Unknown node type "%s"', $nodeTypeName));
- }
-
- $searchableNodeTypeNames[$nodeTypeName] = $nodeTypeName;
- /** @var NodeType $subNodeType */
- foreach ($this->nodeTypeManager->getSubNodeTypes($nodeTypeName, false) as $subNodeTypeName => $subNodeType) {
- $searchableNodeTypeNames[$subNodeTypeName] = $subNodeTypeName;
- }
- }
-
$contentContext = $this->createContentContext($workspaceName, $dimensions);
if ($nodeIdentifiers === []) {
- $nodes = $this->nodeSearchService->findByProperties($searchTerm, $searchableNodeTypeNames, $contentContext, $contextNode);
+ $nodes = $this->nodeSearchService->findByProperties($searchTerm, $nodeTypes, $contentContext, $contextNode);
} else {
$nodes = array_filter(
array_map(function ($identifier) use ($contentContext) {
diff --git a/Neos.Neos/Classes/Domain/Repository/UserRepository.php b/Neos.Neos/Classes/Domain/Repository/UserRepository.php
index c1d3b6f41ff..5445e674242 100644
--- a/Neos.Neos/Classes/Domain/Repository/UserRepository.php
+++ b/Neos.Neos/Classes/Domain/Repository/UserRepository.php
@@ -53,8 +53,8 @@ public function findBySearchTerm(string $searchTerm, string $sortBy, string $sor
$query = $this->createQuery();
$query->matching(
$query->logicalOr(
- $query->like('accounts.accountIdentifier', '%' . $searchTerm . '%'),
- $query->like('name.fullName', '%' . $searchTerm . '%')
+ $query->like('accounts.accountIdentifier', '%' . $searchTerm . '%', false),
+ $query->like('name.fullName', '%' . $searchTerm . '%', false)
)
);
return $query->setOrderings([$sortBy => $sortDirection])->execute();
diff --git a/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php b/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php
index a50b8c19857..bd2ce4eda5d 100644
--- a/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php
+++ b/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php
@@ -159,7 +159,7 @@ protected function registerAllTagsToFlushForNodeInWorkspace(NodeInterface $node,
{
// Ensure that we're dealing with the variant of the given node that actually
// lives in the given workspace
- if ($node->getWorkspace()->getName() !== $workspace->getName()) {
+ if ($node->isRemoved() === false && $node->getWorkspace()->getName() !== $workspace->getName()) {
$workspaceContext = $this->contextFactory->create(
array_merge(
$node->getContext()->getProperties(),
diff --git a/Neos.Neos/Documentation/Appendixes/ChangeLogs/8314.rst b/Neos.Neos/Documentation/Appendixes/ChangeLogs/8314.rst
new file mode 100644
index 00000000000..8a240786f70
--- /dev/null
+++ b/Neos.Neos/Documentation/Appendixes/ChangeLogs/8314.rst
@@ -0,0 +1,65 @@
+`8.3.14 (2024-06-11) `_
+================================================================================================
+
+Overview of merged pull requests
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`BUGFIX: Prevent multiple imports of the same remote asset in the frontend `_
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+This is a frontend fix for `#5116 `_and prevents users from triggering multiple import processes for the same remote asset. It is not a sufficient fix to only prevent this in the frontend though, since it doesn't catch it, if two or more different users trigger the import for the same asset at the same time.
+
+Changes:
+- ``select.js``: add data attribute ``data-import-in-process`` to asset once import process has started and remove it when import is done
+- ``select.js``: check for new data attribute and only start import process if attribute does not exist
+- ``select.js``: add notification to inform user that asset is being imported
+- ``select.js``: add notification as warning for user if import is already in process
+- ``Main.xlf``: add new notification messages for english
+- ``Default.html``: add id for notification container to be able to send notifications to it via js
+- ``Configuration.js``: update ``hasConfiguration`` after configuration object was created, because otherwise it will always be false and the translations don't work
+
+``related:`` https://github.com/neos/neos-development-collection/issues/5116
+
+**Info for testing:**
+You need to bundle the Neos.Neos assets to get the text for the notification messages.
+- navigate to the Neos.Neos package
+- run ``yarn``
+- run ``yarn build``
+
+* Packages: ``Media.Browser``
+
+`BUGFIX: Flush cache also for deleted nodes `_
+-------------------------------------------------------------------------------------------------------------
+
+Removed nodes can't get found, so they regarding caches don't get flushed.
+
+The bug was introduced with `#4291 `_
+* Fixes: `#5105 `_
+
+* Packages: ``Neos``
+
+`BUGFIX: Fix title attribute for impersonate button in user management `_
+----------------------------------------------------------------------------------------------------------------------------------------
+
+With this change the localized text is rendered instead of always defaulting to english.
+
+Changes:
+
+- ImpersonateButton.js change postion of const localizedTooltip inside ImpersonateButton function and change isNil(window.Typo3Neos) to isNil(window.NeosCMS)
+- RestoreButton.js it was always fallback text used change isNil(window.NeosCMS) to !isNil(window.NeosCMS)
+
+* Fixes: `#4511 `_
+
+Checklist
+
+- [ ] Code follows the PSR-2 coding style
+- [ ] Tests have been created, run and adjusted as needed
+- [x] The PR is created against the `lowest maintained branch `_
+- [x] Reviewer - PR Title is brief but complete and starts with ``FEATURE|TASK|BUGFIX``
+- [ ] Reviewer - The first section explains the change briefly for change-logs
+- [ ] Reviewer - Breaking Changes are marked with ``!!!`` and have upgrade-instructions
+
+* Packages: ``Neos``
+
+`Detailed log `_
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Neos.Neos/Documentation/Appendixes/ChangeLogs/8315.rst b/Neos.Neos/Documentation/Appendixes/ChangeLogs/8315.rst
new file mode 100644
index 00000000000..4bf16acf4a0
--- /dev/null
+++ b/Neos.Neos/Documentation/Appendixes/ChangeLogs/8315.rst
@@ -0,0 +1,38 @@
+`8.3.15 (2024-06-14) `_
+================================================================================================
+
+Overview of merged pull requests
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`BUGFIX: Access isNil function from Helper function to apply selected image to property `_
+---------------------------------------------------------------------------------------------------------------------------------------------------------
+
+**Upgrade instructions**
+
+_None_
+
+**Review instructions**
+
+Follow-up to: `#5117 `_
+
+With the latest Bugfix release of Neos 8.3.14 currently when selecting an image from the media browser it not will be applyied to the image property as the ``IsNil`` function has to be accessed inside of the ``Helper`` function.
+
+```javascript
+NeosCMS.isNil()
+```
+In this case, leads to an unresolved function or method.
+
+### Before
+
+https://github.com/neos/neos-development-collection/assets/39345336/ed761221-924d-467f-bd9f-6eb6c97dd553
+
+### After
+
+https://github.com/neos/neos-development-collection/assets/39345336/2c78211a-c8a8-4f55-808a-15b495fde586
+
+
+
+* Packages: ``Neos`` ``Media.Browser``
+
+`Detailed log `_
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Neos.Neos/Documentation/Appendixes/ChangeLogs/8316.rst b/Neos.Neos/Documentation/Appendixes/ChangeLogs/8316.rst
new file mode 100644
index 00000000000..0cc01093891
--- /dev/null
+++ b/Neos.Neos/Documentation/Appendixes/ChangeLogs/8316.rst
@@ -0,0 +1,63 @@
+`8.3.16 (2024-08-14) `_
+================================================================================================
+
+Overview of merged pull requests
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`BUGFIX: Don’t include subnodetypes of subnodetypes in node search `_
+--------------------------------------------------------------------------------------------------------------------------------------
+
+The subnodetypes of the given filter are collected twice (once in the ``NodesController`` and once in the ``NodeDataRepository``) leading to nodetypes being included which don't inherit from the given list of nodetypes as the second list of nodetypes is not checked against the nodetypefilter but against the subnodetypes of the nodetypefilter. See details in #4502.
+
+* Resolves: `#4502 `_
+
+* Packages: ``Neos``
+
+`BUGFIX: Changed from hardcoded date format to user-localized format. `_
+---------------------------------------------------------------------------------------------------------------------------------------
+
+Changes the hardcoded Y-m-d date format with an user-localized format.
+
+German Interface Language
+!`image `_
+
+English Interface Language
+!`image `_
+
+**Upgrade instructions**
+
+Tested within neos 8.3.15
+
+**Review instructions**
+
+Changed the branch to 8.3, as i've `accidentally `_ choose 8.0 👼
+As discussed in `slack `_ we (actually Bastian) changed from a hardcoded date format to an user-localization.
+
+
+* Packages: ``Neos``
+
+`BUGFIX: Forward status codes and headers set in module actions `_
+---------------------------------------------------------------------------------------------------------------------------------
+
+Previously the status code set in module actions via ``throwStatus`` or ``response->setStatusCode()`` was ignored. With this change the individual module response is merged into the generic module response which then contains the desired status code, headers and other properties.
+
+This is essential if the client (f.e. HTMX) relies on proper headers and status codes to behave properly.
+
+**Review instructions**
+
+Use f.e. ``$this->throwStatus(404)`` in a Neos module controller action and check the status code of the response when calling the action.
+The response code should now be 404 instead of 200.
+
+
+* Packages: ``Neos``
+
+`BUGFIX: Case insensitive user search on PostgreSQL `_
+---------------------------------------------------------------------------------------------------------------------
+
+PostgreSQL is by default case sensitive and its hard to find users depending on their name in the users
+module.
+
+* Packages: ``Neos``
+
+`Detailed log `_
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Neos.Neos/Resources/Private/Templates/Module/Administration/Users/Index.html b/Neos.Neos/Resources/Private/Templates/Module/Administration/Users/Index.html
index 0982754eed7..5deb9f5aaa0 100644
--- a/Neos.Neos/Resources/Private/Templates/Module/Administration/Users/Index.html
+++ b/Neos.Neos/Resources/Private/Templates/Module/Administration/Users/Index.html
@@ -46,7 +46,7 @@