Skip to content

Commit db1a648

Browse files
committed
feat: update cards on federated boards
Signed-off-by: grnd-alt <git@belakkaf.net>
1 parent 1923cc8 commit db1a648

11 files changed

Lines changed: 120 additions & 20 deletions

File tree

appinfo/routes.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
['name' => 'board_ocs#addAcl', 'url' => '/api/v{apiVersion}/boards/{boardId}/acl', 'verb' => 'POST'],
141141

142142
['name' => 'card_ocs#create', 'url' => '/api/v{apiVersion}/cards', 'verb' => 'POST'],
143+
['name' => 'card_ocs#update', 'url' => '/api/v{apiVersion}/cards/{cardId}', 'verb' => 'PUT'],
143144

144145
['name' => 'stack_ocs#create', 'url' => '/api/v{apiVersion}/stacks', 'verb' => 'POST'],
145146
['name' => 'stack_ocs#delete', 'url' => '/api/v{apiVersion}/stacks/{stackId}/{boardId}', 'verb' => 'DELETE', 'defaults' => ['boardId' => null]],

cypress/e2e/cardFeatures.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ describe('Card', function () {
194194

195195
it('Shows the modal with the editor', () => {
196196
cy.get('.card:contains("Hello world")').should('be.visible').click()
197-
cy.intercept({ method: 'PUT', url: '**/apps/deck/cards/*' }).as('save')
197+
cy.intercept({ method: 'PUT', url: '**/ocs/v2.php/apps/deck/api/v1.0/cards/*' }).as('save')
198198
cy.get('.modal__card').should('be.visible')
199199
cy.get('.app-sidebar-header__mainname').contains('Hello world')
200200
cy.get('.modal__card .ProseMirror h1').contains('Hello world').should('be.visible')

cypress/e2e/deckDashboard.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ describe('Deck dashboard', function() {
4141
}).then((board) => {
4242
cy.visit(`/apps/deck/#/board/${board.id}`)
4343

44-
cy.intercept({ method: 'PUT', url: '**/apps/deck/cards/**' }).as('updateCard')
44+
cy.intercept({ method: 'PUT', url: '**/ocs/v2.php/apps/deck/api/v1.0/cards/**' }).as('updateCard')
4545

4646
const newCardTitle = 'Hello world'
4747
cy.get(`.card:contains("${newCardTitle}")`).should('be.visible').click()

lib/Activity/ActivityManager.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ public function triggerUpdateEvents($objectType, ChangeSet $changeSet, $subject)
270270
];
271271
if ($changes['before'] !== $changes['after']) {
272272
try {
273-
$event = $this->createEvent($objectType, $entity, $subjectComplete, $changes);
273+
$event = $this->createEvent($objectType, $entity, $subjectComplete, $changes, $this->userId);
274274
if ($event !== null) {
275275
$events[] = $event;
276276
}
@@ -300,6 +300,11 @@ public function triggerUpdateEvents($objectType, ChangeSet $changeSet, $subject)
300300
* @throws \Exception
301301
*/
302302
private function createEvent($objectType, $entity, $subject, $additionalParams = [], $author = null) {
303+
// @TODO implement actual activities for federated users
304+
// this case only happens for federated activities if the author is not provided
305+
if ($author === null && $this->userId === null) {
306+
return;
307+
}
303308
try {
304309
$object = $this->findObjectForEntity($objectType, $entity);
305310
} catch (DoesNotExistException $e) {

lib/Controller/CardOcsController.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace OCA\Deck\Controller;
99

10+
use OCA\Deck\Model\OptionalNullableValue;
1011
use OCA\Deck\Service\BoardService;
1112
use OCA\Deck\Service\CardService;
1213
use OCA\Deck\Service\ExternalBoardService;
@@ -61,4 +62,51 @@ public function create(string $title, int $stackId, ?int $boardId = null, ?strin
6162
return new DataResponse($card);
6263
}
6364

65+
#[NoAdminRequired]
66+
#[PublicPage]
67+
#[NoCSRFRequired]
68+
#[RequestHeader(name: 'x-nextcloud-federation', description: 'Set to 1 when the request is performed by another Nextcloud Server to indicate a federation request', indirect: true)]
69+
public function update(int $id, string $title, int $stackId, string $type, int $order, string $description, $duedate, $deletedAt, int $boardId, array|string|null $owner = null, $archived = null): DataResponse {
70+
$done = array_key_exists('done', $this->request->getParams())
71+
? new OptionalNullableValue($this->request->getParam('done', null))
72+
: null;
73+
if (!$owner) {
74+
$owner = $this->userId;
75+
} else {
76+
if (!is_string($owner)) {
77+
$owner = $owner['uid'];
78+
}
79+
}
80+
81+
$localBoard = $this->boardService->find($boardId, false);
82+
if ($localBoard->getExternalId()) {
83+
return new DataResponse($this->externalBoardService->updateCardOnRemote(
84+
$localBoard,
85+
$id,
86+
$title,
87+
$stackId,
88+
$type,
89+
$owner,
90+
$description,
91+
$order,
92+
$duedate,
93+
$deletedAt,
94+
$archived,
95+
$done
96+
));
97+
}
98+
99+
return new DataResponse($this->cardService->update($id,
100+
$title,
101+
$stackId,
102+
$type,
103+
$owner,
104+
$description,
105+
$order,
106+
$duedate,
107+
$deletedAt,
108+
$archived,
109+
$done
110+
));
111+
}
64112
}

lib/Federation/DeckFederationProxy.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ public function get(string $cloudId, string $shareToken, string $url, array $par
110110
public function post(string $cloudId, string $shareToken, string $url, array $params = []): IResponse {
111111
return $this->request('post', $cloudId, $shareToken, $url, $params);
112112
}
113+
public function put(string $cloudId, string $shareToken, string $url, array $params = []): IResponse {
114+
return $this->request('put', $cloudId, $shareToken, $url, $params);
115+
}
113116
public function delete(string $cloudId, string $shareToken, string $url, array $params = []): IResponse {
114117
return $this->request('delete', $cloudId, $shareToken, $url, $params);
115118
}

lib/Middleware/FederationMiddleware.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ public function __construct(
2323
}
2424

2525
public function beforeController($controller, $methodName): void {
26-
if (!$this->configService->get('federationEnabled')) {
26+
try {
27+
$this->configService->ensureFederationEnabled();
28+
} catch (\Exception $e) {
2729
return;
2830
}
2931
$accessToken = $this->request->getHeader('deck-federation-accesstoken');

lib/Service/ExternalBoardService.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use OCA\Deck\Db\Board;
1212
use OCA\Deck\Db\BoardMapper;
1313
use OCA\Deck\Federation\DeckFederationProxy;
14+
use OCA\Deck\Model\OptionalNullableValue;
1415
use OCP\AppFramework\Http\DataResponse;
1516
use OCP\Federation\ICloudIdManager;
1617
use OCP\IUserManager;
@@ -74,7 +75,6 @@ public function createCardOnRemote(
7475
?string $description = '',
7576
$duedate = null,
7677
?array $users = [],
77-
?int $boardId = null,
7878
): array {
7979
$this->configService->ensureFederationEnabled();
8080
$this->permissionService->checkPermission($this->boardMapper, $localBoard->getId(), Acl::PERMISSION_EDIT, $this->userId, false, false);
@@ -97,6 +97,44 @@ public function createCardOnRemote(
9797
return $this->proxy->getOcsData($resp);
9898
}
9999

100+
public function updateCardOnRemote(
101+
Board $localBoard,
102+
int $cardId,
103+
string $title,
104+
int $stackId,
105+
string $type,
106+
string $owner,
107+
string $description = '',
108+
int $order = 0,
109+
?string $duedate = null,
110+
?int $deletedAt = null,
111+
?bool $archived = null,
112+
?OptionalNullableValue $done = null,
113+
): array {
114+
$this->configService->ensureFederationEnabled();
115+
$this->permissionService->checkPermission($this->boardMapper, $localBoard->getId(), Acl::PERMISSION_EDIT, $this->userId, false, false);
116+
$shareToken = $localBoard->getShareToken();
117+
$participantCloudId = $this->cloudIdManager->getCloudId($this->userId, null);
118+
$ownerCloudId = $this->cloudIdManager->resolveCloudId($localBoard->getOwner());
119+
$url = $ownerCloudId->getRemote() . '/ocs/v2.php/apps/deck/api/v1.0/cards/' . $cardId;
120+
$params = [
121+
'id' => $cardId,
122+
'title' => $title,
123+
'stackId' => $stackId,
124+
'type' => $type,
125+
'owner' => $owner,
126+
'description' => $description,
127+
'order' => $order,
128+
'duedate' => $duedate,
129+
'deletedAt' => $deletedAt,
130+
'archived' => $archived,
131+
'done' => $done->getValue() ?? null,
132+
'boardId' => $localBoard->getExternalId(),
133+
];
134+
$resp = $this->proxy->put($participantCloudId->getId(), $shareToken, $url, $params);
135+
return $this->proxy->getOcsData($resp);
136+
}
137+
100138
public function createStackOnRemote(
101139
Board $localBoard,
102140
string $title,

src/CardMoveDialog.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
<script>
3636
import { NcDialog, NcSelect, NcButton } from '@nextcloud/vue'
37-
import { generateUrl } from '@nextcloud/router'
37+
import { generateOcsUrl } from '@nextcloud/router'
3838
import axios from '@nextcloud/axios'
3939
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
4040
import { mapGetters } from 'vuex'
@@ -85,17 +85,17 @@ export default {
8585
},
8686
async loadStacksFromBoard(board) {
8787
try {
88-
const url = generateUrl('/apps/deck/stacks/' + board.id)
88+
const url = generateOcsUrl(`/apps/deck/api/v1.0/stacks/${board.id}`)
8989
const response = await axios.get(url)
90-
this.stacksFromBoard = response.data
90+
this.stacksFromBoard = response.data.ocs.data
9191
} catch (err) {
9292
return err
9393
}
9494
},
9595
async moveCard() {
9696
this.copiedCard = Object.assign({}, this.card)
9797
this.copiedCard.stackId = this.selectedStack.id
98-
this.$store.dispatch('moveCard', this.copiedCard)
98+
this.$store.dispatch('moveCard', { card: this.copiedCard, oldBoardId: this.selectedBoard.id })
9999
if (parseInt(this.selectedBoard.id) === parseInt(this.selectedStack.boardId)) {
100100
await this.$store.commit('addNewCard', { ...this.copiedCard })
101101
}

src/services/CardApi.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ export class CardApi {
8080
})
8181
}
8282

83-
updateCard(card) {
84-
return axios.put(this.url(`/cards/${card.id}`), card)
83+
updateCard(card, boardId) {
84+
return axios.put(this.ocsUrl(`/cards/${card.id}`), { ...card, boardId })
8585
.then(
8686
(response) => {
87-
return Promise.resolve(response.data)
87+
return Promise.resolve(response.data.ocs.data)
8888
},
8989
(err) => {
9090
return Promise.reject(err)

0 commit comments

Comments
 (0)