diff --git a/appinfo/routes.php b/appinfo/routes.php
index 488a0f849..6017a9b12 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -121,6 +121,8 @@
['name' => 'search#all', 'url' => '/search/all', 'verb' => 'GET'],
],
'ocs' => [
+ ['name' => 'navigation#getAppsNavigation', 'url' => '/navigation', 'verb' => 'GET'],
+
// API v2
['name' => 'ApiGeneral#index', 'url' => '/api/2/init', 'verb' => 'GET'],
// -> tables
diff --git a/cypress/e2e/context.cy.js b/cypress/e2e/context.cy.js
index e3444a02c..6363d2ef8 100644
--- a/cypress/e2e/context.cy.js
+++ b/cypress/e2e/context.cy.js
@@ -188,7 +188,6 @@ describe('Manage a context', () => {
cy.login(nonLocalUser)
cy.visit('apps/tables')
cy.loadContext(contextTitle)
- cy.contains('header .app-menu-entry', contextTitle).should('exist')
cy.contains('h1', contextTitle).should('exist')
cy.contains('h1', tableTitle).should('exist')
cy.get('button').contains('Create row').click()
diff --git a/lib/Controller/NavigationController.php b/lib/Controller/NavigationController.php
new file mode 100644
index 000000000..db07f0752
--- /dev/null
+++ b/lib/Controller/NavigationController.php
@@ -0,0 +1,43 @@
+= 31.
+ */
+class NavigationController extends \OC\Core\Controller\NavigationController {
+ public function __construct(
+ protected ContextService $contextService,
+ protected IUserSession $userSession,
+ string $appName,
+ IRequest $request,
+ INavigationManager $navigationManager,
+ IURLGenerator $urlGenerator
+ ) {
+ parent::__construct($appName, $request, $navigationManager, $urlGenerator);
+ }
+
+ #[NoAdminRequired]
+ #[NoCSRFRequired]
+ #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)]
+ public function getAppsNavigation(bool $absolute = false): DataResponse {
+ $this->contextService->addToNavigation($this->userSession->getUser()?->getUID());
+ return parent::getAppsNavigation($absolute);
+ }
+}
diff --git a/lib/Db/ContextMapper.php b/lib/Db/ContextMapper.php
index a957c7238..a7e314346 100644
--- a/lib/Db/ContextMapper.php
+++ b/lib/Db/ContextMapper.php
@@ -96,6 +96,9 @@ protected function formatResultRows(array $rows, ?string $userId) {
'display_mode_default' => (int)$item['display_mode_default'],
];
if ($userId !== null) {
+ if ($item['display_mode'] === null) {
+ $item['display_mode'] = $item['display_mode_default'];
+ }
$carry[$item['share_id']]['display_mode'] = (int)$item['display_mode'];
}
return $carry;
diff --git a/lib/Db/ContextNavigationMapper.php b/lib/Db/ContextNavigationMapper.php
index f32a53f59..be304fb05 100644
--- a/lib/Db/ContextNavigationMapper.php
+++ b/lib/Db/ContextNavigationMapper.php
@@ -7,6 +7,7 @@
*/
namespace OCA\Tables\Db;
+use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\Exception;
use OCP\DB\QueryBuilder\IQueryBuilder;
@@ -41,4 +42,63 @@ public function setDisplayModeByShareId(int $shareId, int $displayMode, string $
return $this->insertOrUpdate($entity);
}
+
+ // we have to overwrite QBMapper`s insert() because we do not have
+ // an id column in this table. Sad.
+ public function insert(Entity $entity): Entity {
+ // get updated fields to save, fields have to be set using a setter to
+ // be saved
+ $properties = $entity->getUpdatedFields();
+
+ $qb = $this->db->getQueryBuilder();
+ $qb->insert($this->tableName);
+
+ // build the fields
+ foreach ($properties as $property => $updated) {
+ $column = $entity->propertyToColumn($property);
+ $getter = 'get' . ucfirst($property);
+ $value = $entity->$getter();
+
+ $type = $this->getParameterTypeForProperty($entity, $property);
+ $qb->setValue($column, $qb->createNamedParameter($value, $type));
+ }
+
+ $qb->executeStatement();
+
+ return $entity;
+ }
+
+ // we have to overwrite QBMapper`s update() because we do not have
+ // an id column in this table. Sad.
+ public function update(Entity $entity): ContextNavigation {
+ if (!$entity instanceof ContextNavigation) {
+ throw new \LogicException('Can only update context navigation entities');
+ }
+
+ // if entity wasn't changed it makes no sense to run a db query
+ $properties = $entity->getUpdatedFields();
+ if (\count($properties) === 0) {
+ return $entity;
+ }
+
+ $qb = $this->db->getQueryBuilder();
+ $qb->update($this->tableName);
+
+ // build the fields
+ foreach ($properties as $property => $updated) {
+ $column = $entity->propertyToColumn($property);
+ $getter = 'get' . ucfirst($property);
+ $value = $entity->$getter();
+
+ $type = $this->getParameterTypeForProperty($entity, $property);
+ $qb->set($column, $qb->createNamedParameter($value, $type));
+ }
+
+ $qb->where($qb->expr()->eq('share_id', $qb->createNamedParameter($entity->getShareId(), IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->eq('user_id', $qb->createNamedParameter($entity->getUserId(), IQueryBuilder::PARAM_STR)));
+
+ $qb->executeStatement();
+
+ return $entity;
+ }
}
diff --git a/lib/Listener/BeforeTemplateRenderedListener.php b/lib/Listener/BeforeTemplateRenderedListener.php
index b26bc6592..d34836518 100644
--- a/lib/Listener/BeforeTemplateRenderedListener.php
+++ b/lib/Listener/BeforeTemplateRenderedListener.php
@@ -7,13 +7,10 @@
namespace OCA\Tables\Listener;
-use OCA\Tables\AppInfo\Application;
use OCA\Tables\Service\ContextService;
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
-use OCP\INavigationManager;
-use OCP\IURLGenerator;
use OCP\IUserSession;
/**
@@ -21,10 +18,8 @@
*/
class BeforeTemplateRenderedListener implements IEventListener {
public function __construct(
- protected INavigationManager $navigationManager,
- protected IURLGenerator $urlGenerator,
- protected IUserSession $userSession,
- protected ContextService $contextService,
+ protected IUserSession $userSession,
+ protected ContextService $contextService,
) {
}
@@ -41,27 +36,6 @@ public function handle(Event $event): void {
return;
}
- $contexts = $this->contextService->findForNavigation($user->getUID());
- foreach ($contexts as $context) {
- $this->navigationManager->add(function () use ($context) {
- $iconRelPath = 'material/' . $context->getIcon() . '.svg';
- if (file_exists(__DIR__ . '/../../img/' . $iconRelPath)) {
- $iconUrl = $this->urlGenerator->imagePath(Application::APP_ID, $iconRelPath);
- } else {
- $iconUrl = $this->urlGenerator->imagePath('core', 'places/default-app-icon.svg');
- }
-
- $contextUrl = $this->urlGenerator->linkToRoute('tables.page.context', ['contextId' => $context->getId()]);
-
- return [
- 'id' => Application::APP_ID . '_application_' . $context->getId(),
- 'name' => $context->getName(),
- 'href' => $contextUrl,
- 'icon' => $iconUrl,
- 'order' => 500,
- 'type' => 'link',
- ];
- });
- }
+ $this->contextService->addToNavigation($user->getUID());
}
}
diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php
index 41f7eaac0..07b102f26 100644
--- a/lib/Service/ContextService.php
+++ b/lib/Service/ContextService.php
@@ -27,49 +27,31 @@
use OCP\DB\Exception;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IDBConnection;
+use OCP\INavigationManager;
+use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Log\Audit\CriticalActionPerformedEvent;
use Psr\Log\LoggerInterface;
class ContextService {
- private ContextMapper $contextMapper;
- private bool $isCLI;
- private LoggerInterface $logger;
- private ContextNodeRelationMapper $contextNodeRelMapper;
- private PageMapper $pageMapper;
- private PageContentMapper $pageContentMapper;
- private PermissionsService $permissionsService;
- private IUserManager $userManager;
- private IEventDispatcher $eventDispatcher;
- private IDBConnection $dbc;
- private ShareService $shareService;
-
public function __construct(
- ContextMapper $contextMapper,
- ContextNodeRelationMapper $contextNodeRelationMapper,
- PageMapper $pageMapper,
- PageContentMapper $pageContentMapper,
- LoggerInterface $logger,
- PermissionsService $permissionsService,
- IUserManager $userManager,
- IEventDispatcher $eventDispatcher,
- IDBConnection $dbc,
- ShareService $shareService,
- bool $isCLI,
+ private ContextMapper $contextMapper,
+ private ContextNodeRelationMapper $contextNodeRelMapper,
+ private PageMapper $pageMapper,
+ private PageContentMapper $pageContentMapper,
+ private LoggerInterface $logger,
+ private PermissionsService $permissionsService,
+ private IUserManager $userManager,
+ private IEventDispatcher $eventDispatcher,
+ private IDBConnection $dbc,
+ private ShareService $shareService,
+ private bool $isCLI,
+ protected INavigationManager $navigationManager,
+ protected IURLGenerator $urlGenerator,
) {
- $this->contextMapper = $contextMapper;
- $this->isCLI = $isCLI;
- $this->logger = $logger;
- $this->contextNodeRelMapper = $contextNodeRelationMapper;
- $this->pageMapper = $pageMapper;
- $this->pageContentMapper = $pageContentMapper;
- $this->permissionsService = $permissionsService;
- $this->userManager = $userManager;
- $this->eventDispatcher = $eventDispatcher;
- $this->dbc = $dbc;
- $this->shareService = $shareService;
}
+
use TTransactional;
/**
@@ -93,6 +75,31 @@ public function findForNavigation(string $userId): array {
return $this->contextMapper->findForNavBar($userId);
}
+ public function addToNavigation(string $userId): void {
+ $contexts = $this->findForNavigation($userId);
+ foreach ($contexts as $context) {
+ $this->navigationManager->add(function () use ($context) {
+ $iconRelPath = 'material/' . $context->getIcon() . '.svg';
+ if (file_exists(__DIR__ . '/../../img/' . $iconRelPath)) {
+ $iconUrl = $this->urlGenerator->imagePath(Application::APP_ID, $iconRelPath);
+ } else {
+ $iconUrl = $this->urlGenerator->imagePath('core', 'places/default-app-icon.svg');
+ }
+
+ $contextUrl = $this->urlGenerator->linkToRoute('tables.page.context', ['contextId' => $context->getId()]);
+
+ return [
+ 'id' => Application::APP_ID . '_application_' . $context->getId(),
+ 'name' => $context->getName(),
+ 'href' => $contextUrl,
+ 'icon' => $iconUrl,
+ 'order' => 500,
+ 'type' => 'link',
+ ];
+ });
+ }
+ }
+
/**
* @throws Exception
* @throws InternalError
diff --git a/lib/Service/ShareService.php b/lib/Service/ShareService.php
index d4780fd24..566355cd5 100644
--- a/lib/Service/ShareService.php
+++ b/lib/Service/ShareService.php
@@ -339,7 +339,7 @@ public function updateDisplayMode(int $shareId, int $displayMode, string $userId
}
} else {
// setting user display mode override only requires access
- if (!$this->permissionsService->canAccessContextById($item->getId())) {
+ if (!$this->permissionsService->canAccessContextById($item->getNodeId(), $userId)) {
throw new PermissionError(sprintf('PermissionError: can not update share with id %d', $shareId));
}
}
diff --git a/openapi.json b/openapi.json
index fddafc065..9ac287457 100644
--- a/openapi.json
+++ b/openapi.json
@@ -10074,5 +10074,10 @@
}
}
},
- "tags": []
+ "tags": [
+ {
+ "name": "navigation",
+ "description": "This is a workaround until https://github.com/nextcloud/server/pull/49904 is settled in all covered NC versions; expected >= 31."
+ }
+ ]
}
diff --git a/src/modules/modals/CreateContext.vue b/src/modules/modals/CreateContext.vue
index 04df5de6a..457b00d92 100644
--- a/src/modules/modals/CreateContext.vue
+++ b/src/modules/modals/CreateContext.vue
@@ -42,6 +42,14 @@