Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions .github/workflows/integration-federation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: Federation integration tests

on:
pull_request:
paths:
- '.github/workflows/integration-federation.yml'
- 'appinfo/**'
- 'lib/**'
- 'templates/**'
- 'tests/**'
- 'composer.json'
- 'composer.lock'
push:
branches:
- main
- master
- stable*

permissions:
contents: read

env:
APP_NAME: deck

jobs:
federation:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
php-versions: ['8.2']
server-versions: ['master']

name: php${{ matrix.php-versions }}-${{ matrix.server-versions }}

steps:
- name: Checkout server
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
repository: nextcloud/server
ref: ${{ matrix.server-versions }}
submodules: true

- name: Checkout app
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
path: apps/${{ env.APP_NAME }}

- name: Checkout activity
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
repository: nextcloud/activity
ref: ${{ matrix.server-versions }}
path: apps/activity

- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.36.0
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, apcu, gd
ini-values:
apc.enable_cli=on
coverage: none

- name: Set up dependencies
working-directory: apps/${{ env.APP_NAME }}
run: composer i --no-dev

- name: Set up Nextcloud
run: |
mkdir data
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --admin-user admin --admin-pass admin
./occ config:system:set hashing_default_password --value=true --type=boolean
./occ config:system:set memcache.local --value="\\OC\\Memcache\\APCu"
./occ config:system:set memcache.distributed --value="\\OC\\Memcache\\APCu"
cat config/config.php
./occ app:enable --force ${{ env.APP_NAME }}

- name: Run federation behat tests
working-directory: apps/${{ env.APP_NAME }}/tests/integration
run: ./run-federation.sh

- name: Print log
if: always()
run: |
if [ -f data/nextcloud.log ]; then
cat data/nextcloud.log
else
echo "Log file not found"
fi
14 changes: 7 additions & 7 deletions lib/Db/BoardMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ public function findAllByUser(string $userId, ?int $limit = null, ?int $offset =
// FIXME this used to be a UNION to get boards owned by $userId and the user shares in one single query
// Is it possible with the query builder?
$qb = $this->db->getQueryBuilder();
$qb->select('id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
$qb->select('id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified', 'external_id', 'share_token')
// this does not work in MySQL/PostgreSQL
//->selectAlias('0', 'shared')
->from('deck_boards', 'b')
Expand Down Expand Up @@ -230,7 +230,7 @@ public function findAllByUser(string $userId, ?int $limit = null, ?int $offset =

// shared with user
$qb = $this->db->getQueryBuilder();
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified', 'external_id', 'share_token')
//->selectAlias('1', 'shared')
->from('deck_boards', 'b')
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
Expand Down Expand Up @@ -298,7 +298,7 @@ public function findAllByGroups(string $userId, array $groups, ?int $limit = nul
return [];
}
$qb = $this->db->getQueryBuilder();
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified', 'external_id', 'share_token')
//->selectAlias('2', 'shared')
->from('deck_boards', 'b')
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
Expand Down Expand Up @@ -354,7 +354,7 @@ public function findAllByCircles(string $userId, ?int $limit = null, ?int $offse
}

$qb = $this->db->getQueryBuilder();
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified', 'external_id', 'share_token')
//->selectAlias('2', 'shared')
->from('deck_boards', 'b')
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
Expand Down Expand Up @@ -404,7 +404,7 @@ public function findAllByCircles(string $userId, ?int $limit = null, ?int $offse

public function findAllByTeam(string $teamId): array {
$qb = $this->db->getQueryBuilder();
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified', 'external_id', 'share_token')
->from('deck_boards', 'b')
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
->where($qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)))
Expand Down Expand Up @@ -432,7 +432,7 @@ public function findTeamsForBoard(int $boardId): array {

public function isSharedWithTeam(int $boardId, string $teamId): bool {
$qb = $this->db->getQueryBuilder();
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified', 'external_id', 'share_token')
->from('deck_boards', 'b')
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
->where($qb->expr()->eq('b.id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
Expand All @@ -458,7 +458,7 @@ public function findToDelete() {
// add buffer of 5 min
$timeLimit = time() - (60 * 5);
$qb = $this->db->getQueryBuilder();
$qb->select('id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
$qb->select('id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified', 'external_id', 'share_token')
->from('deck_boards')
->where($qb->expr()->gt('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->lt('deleted_at', $qb->createNamedParameter($timeLimit, IQueryBuilder::PARAM_INT)));
Expand Down
2 changes: 2 additions & 0 deletions lib/Db/Stack.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
* @method \int getOrder()
* @method void setOrder(int $order)
* @method Card[] getCards()
* @method bool getIsDoneColumn()
* @method void setIsDoneColumn(bool $isDoneColumn)
*/
class Stack extends RelationalEntity {
protected $title;
Expand Down
12 changes: 12 additions & 0 deletions lib/Service/BoardService.php
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,18 @@ public function addAcl(int $boardId, int $type, $participant, bool $edit, bool $

$this->eventDispatcher->dispatchTyped(new AclCreatedEvent($acl));

// Sync permissions to remote server since shareReceived() creates ACL with no permissions
if ($type === Acl::PERMISSION_TYPE_REMOTE && ($edit || $share || $manage)) {
$notification = $this->federationFactory->getCloudFederationNotification();
$payload = [
$newAcl->jsonSerialize(),
'sharedSecret' => $newAcl->getToken(),
];
$notification->setMessage('update-permissions', 'deck', (string)$boardId, $payload);
$url = $this->cloudIdManager->resolveCloudId($participant);
$this->cloudFederationProviderManager->sendCloudNotification($url->getRemote(), $notification);
}

return $newAcl;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Service/ExternalBoardService.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public function createStackOnRemote(
int $order = 0,
): array {
$this->configService->ensureFederationEnabled();
$this->permissionService->checkPermission($this->boardMapper, $localBoard->getId(), Acl::PERMISSION_EDIT, $this->userId, false, false);
$this->permissionService->checkPermission($this->boardMapper, $localBoard->getId(), Acl::PERMISSION_MANAGE, $this->userId, false, false);
$shareToken = $localBoard->getShareToken();
$participantCloudId = $this->cloudIdManager->getCloudId($this->userId, null);
$ownerCloudId = $this->cloudIdManager->resolveCloudId($localBoard->getOwner());
Expand Down
7 changes: 7 additions & 0 deletions tests/integration/config/behat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ default:
test:
paths:
- '%paths.base%/../features/'
filters:
tags: '~@federation'
contexts:
- ServerContext:
baseUrl: http://localhost:8080/
Expand All @@ -16,3 +18,8 @@ default:
- AttachmentContext
- SearchContext
- SessionContext
federation:
paths:
- '%paths.base%/../features/federation/'
contexts:
- FederationContext
Loading
Loading