From 577733311eaa0469c6d83ece3cd3726f59bc872d Mon Sep 17 00:00:00 2001 From: enjeck Date: Wed, 13 Dec 2023 20:05:17 +0100 Subject: [PATCH 01/14] feat: transfer table ownership backend Signed-off-by: Cleopatra Enjeck M --- appinfo/routes.php | 1 + lib/Controller/Api1Controller.php | 27 ++++++++++++++++++++++ lib/Service/TableService.php | 37 +++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/appinfo/routes.php b/appinfo/routes.php index 2a09cd157..1b8ee9e35 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -18,6 +18,7 @@ ['name' => 'api1#index', 'url' => '/api/1/tables', 'verb' => 'GET'], ['name' => 'api1#createTable', 'url' => '/api/1/tables', 'verb' => 'POST'], ['name' => 'api1#updateTable', 'url' => '/api/1/tables/{tableId}', 'verb' => 'PUT'], + ['name' => 'api1#transferTable', 'url' => '/api/1/tables/{tableId}', 'verb' => 'PUT'], ['name' => 'api1#getTable', 'url' => '/api/1/tables/{tableId}', 'verb' => 'GET'], ['name' => 'api1#deleteTable', 'url' => '/api/1/tables/{tableId}', 'verb' => 'DELETE'], // -> views diff --git a/lib/Controller/Api1Controller.php b/lib/Controller/Api1Controller.php index 13d1f7bff..1c8ef25a5 100644 --- a/lib/Controller/Api1Controller.php +++ b/lib/Controller/Api1Controller.php @@ -196,6 +196,33 @@ public function updateTable(int $tableId, string $title = null, string $emoji = } } + /** + * Transfer table from one user to another + * + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * + * @param int $tableId Table ID + * @param string $newOwnerUserId New user ID + * @param string $userId Current user ID + * @return DataResponse|DataResponse + * + */ + public function transferTable(int $tableId, int $newOwnerUserId, int $userId): DataResponse { + try { + return new DataResponse($this->tableService->transfer($tableId, $newOwnerUserId, $userId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } + } + /** * Delete a table * diff --git a/lib/Service/TableService.php b/lib/Service/TableService.php index 3f5e8df9e..bb9f08482 100644 --- a/lib/Service/TableService.php +++ b/lib/Service/TableService.php @@ -328,6 +328,43 @@ public function setOwner(int $id, string $newOwnerUserId, ?string $userId = null } } + /** + * @param int $id + * @param null|string $userId + * @return Table + * @throws InternalError + * @throws NotFoundError + * @throws PermissionError + */ + public function transfer(int $id, string $newOwnerUserId, string $userId): Table { + $userId = $this->permissionsService->preCheckUserId($userId); + + try { + $table = $this->mapper->find($id); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } + + try { + $this->setOwner($id, $newOwnerUserId, $userId); + } + catch(PermissionError|InternalError $e){ + throw new PermissionError('PermissionError: can not transfer table with id '.$id); + } + catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } + return $table; + } + /** * @param int $id * @param null|string $userId From e422055982439ffadd0c3792d427d9fff5108046 Mon Sep 17 00:00:00 2001 From: enjeck Date: Wed, 13 Dec 2023 20:07:02 +0100 Subject: [PATCH 02/14] feat: transfer table ownership frontend Signed-off-by: Cleopatra Enjeck M --- src/modules/main/sections/DataTable.vue | 16 ++ src/modules/modals/Modals.vue | 6 + src/modules/modals/TransferTable.vue | 107 ++++++++++ .../partials/NavigationTableItem.vue | 8 + src/modules/sidebar/partials/TransferForm.vue | 187 ++++++++++++++++++ .../ncTable/mixins/permissionsMixin.js | 3 + src/store/store.js | 2 + 7 files changed, 329 insertions(+) create mode 100644 src/modules/modals/TransferTable.vue create mode 100644 src/modules/sidebar/partials/TransferForm.vue diff --git a/src/modules/main/sections/DataTable.vue b/src/modules/main/sections/DataTable.vue index bd7632cd3..cf7fb4a26 100644 --- a/src/modules/main/sections/DataTable.vue +++ b/src/modules/main/sections/DataTable.vue @@ -17,6 +17,14 @@ {{ t('tables', 'Edit table') }} + + + {{ t('tables', 'Transfer table') }} + @@ -92,6 +100,14 @@ {{ t('tables', 'Edit table') }} + + + {{ t('tables', 'Transfer table') }} + diff --git a/src/modules/modals/Modals.vue b/src/modules/modals/Modals.vue index 63987d1f2..b6377dc99 100644 --- a/src/modules/modals/Modals.vue +++ b/src/modules/modals/Modals.vue @@ -32,6 +32,7 @@ @close="importToElement = null" /> + @@ -50,6 +51,7 @@ import DeleteTable from './DeleteTable.vue' import CreateTable from './CreateTable.vue' import DeleteView from './DeleteView.vue' import EditTable from './EditTable.vue' +import TransferTable from './TransferTable.vue' export default { components: { @@ -65,6 +67,7 @@ export default { DeleteColumn, CreateRow, DeleteTable, + TransferTable, }, data() { @@ -82,6 +85,7 @@ export default { tableToDelete: null, viewToDelete: null, editTable: null, + tableToTransfer: null, } }, @@ -90,6 +94,7 @@ export default { subscribe('tables:table:create', () => { this.showModalCreateTable = true }) subscribe('tables:table:delete', table => { this.tableToDelete = table }) subscribe('tables:table:edit', tableId => { this.editTable = tableId }) + subscribe('tables:table:transfer', table => { this.tableToTransfer = table }) // views subscribe('tables:view:reload', () => { this.reload(true) }) @@ -136,6 +141,7 @@ export default { unsubscribe('tables:modal:import', element => { this.importToElement = element }) unsubscribe('tables:table:delete', table => { this.tableToDelete = table }) unsubscribe('tables:table:edit', tableId => { this.editTable = tableId }) + unsubscribe('tables:table:transfer', table => { this.tableToTransfer = table }) }, } diff --git a/src/modules/modals/TransferTable.vue b/src/modules/modals/TransferTable.vue new file mode 100644 index 000000000..7a63fd892 --- /dev/null +++ b/src/modules/modals/TransferTable.vue @@ -0,0 +1,107 @@ + + + diff --git a/src/modules/navigation/partials/NavigationTableItem.vue b/src/modules/navigation/partials/NavigationTableItem.vue index 799fe0f85..620dc78f2 100644 --- a/src/modules/navigation/partials/NavigationTableItem.vue +++ b/src/modules/navigation/partials/NavigationTableItem.vue @@ -34,6 +34,14 @@ {{ t('tables', 'Edit table') }} + + + {{ t('tables', 'Transfer table') }} + diff --git a/src/modules/sidebar/partials/TransferForm.vue b/src/modules/sidebar/partials/TransferForm.vue new file mode 100644 index 000000000..cc1ec1ed4 --- /dev/null +++ b/src/modules/sidebar/partials/TransferForm.vue @@ -0,0 +1,187 @@ + + + + + diff --git a/src/shared/components/ncTable/mixins/permissionsMixin.js b/src/shared/components/ncTable/mixins/permissionsMixin.js index 72b4cbdd5..ed3d6801f 100644 --- a/src/shared/components/ncTable/mixins/permissionsMixin.js +++ b/src/shared/components/ncTable/mixins/permissionsMixin.js @@ -2,6 +2,9 @@ import { getCurrentUser } from '@nextcloud/auth' export default { methods: { + ownsTable(element) { + return element?.ownership === getCurrentUser().uid + }, // views have the flag manageTable set if the user has manage rights for the corresponding table canManageTable(element) { if (!element.isShared) { diff --git a/src/store/store.js b/src/store/store.js index e1338d604..d7101cdd4 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -234,6 +234,8 @@ export default new Vuex.Store({ commit('setTables', [...tables]) return true }, + async transferTable({ state, commit, dispatch }, { tableId, newOwnerUserId, userId}) { + }, async removeTable({ state, commit }, { tableId }) { try { await axios.delete(generateUrl('/apps/tables/table/' + tableId)) From 11b50d69c0e09d48e5db5b83691fc27c8d998c8b Mon Sep 17 00:00:00 2001 From: Florian Steffens Date: Thu, 14 Dec 2023 10:53:22 +0100 Subject: [PATCH 03/14] Fix unrelated bugs and update dependencies Signed-off-by: Florian Steffens --- composer.lock | 2 +- src/shared/components/ncTable/mixins/columnClass.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.lock b/composer.lock index 395139c4c..c35495786 100644 --- a/composer.lock +++ b/composer.lock @@ -2864,4 +2864,4 @@ "php": "8.0" }, "plugin-api-version": "2.6.0" -} +} \ No newline at end of file diff --git a/src/shared/components/ncTable/mixins/columnClass.js b/src/shared/components/ncTable/mixins/columnClass.js index 76074f4ec..f106de6a8 100644 --- a/src/shared/components/ncTable/mixins/columnClass.js +++ b/src/shared/components/ncTable/mixins/columnClass.js @@ -54,7 +54,7 @@ export class AbstractColumn { /** * parse an input value * - * @param value + * @param {*} value Value to parse * @return {*} */ parseValue(value) { From 0e33075a016999cb412ff521498afe3347782759 Mon Sep 17 00:00:00 2001 From: Florian Steffens Date: Thu, 14 Dec 2023 10:55:44 +0100 Subject: [PATCH 04/14] Cleanup and restructure vue components - add suggestion for UI - move user lookup to a shared component as it could be used elsewhere - logic to request users and groups is missing, should be exchanged with new api endpoint Signed-off-by: Florian Steffens --- src/modules/modals/EditTable.vue | 67 +++++++++++++++---- src/modules/modals/TransferTable.vue | 25 +++---- .../NcUserAndGroupPicker.vue} | 30 +++++++-- src/store/store.js | 3 +- 4 files changed, 89 insertions(+), 36 deletions(-) rename src/{modules/sidebar/partials/TransferForm.vue => shared/components/ncUserAndGroupPicker/NcUserAndGroupPicker.vue} (91%) diff --git a/src/modules/modals/EditTable.vue b/src/modules/modals/EditTable.vue index c8a73d44f..35d7d9bf7 100644 --- a/src/modules/modals/EditTable.vue +++ b/src/modules/modals/EditTable.vue @@ -28,19 +28,36 @@
-
- - {{ t('tables', 'Delete') }} - - - {{ t('tables', 'I really want to delete this table!') }} - - - {{ t('tables', 'Save') }} - +
+ {{ t('tables', 'Owner') }} +
+
+ +
+
+
+ + {{ t('tables', 'Delete') }} + + + {{ t('tables', 'I really want to delete this table!') }} + +
+ + {{ t('tables', 'Change owner') }} + + + {{ t('tables', 'Save') }} + +
+
@@ -48,10 +65,12 @@ + diff --git a/src/modules/modals/TransferTable.vue b/src/modules/modals/TransferTable.vue index 7a63fd892..5d85ce137 100644 --- a/src/modules/modals/TransferTable.vue +++ b/src/modules/modals/TransferTable.vue @@ -5,11 +5,14 @@