diff --git a/lib/Controller/FolderController.php b/lib/Controller/FolderController.php index 61e4b4358..33c08720c 100644 --- a/lib/Controller/FolderController.php +++ b/lib/Controller/FolderController.php @@ -113,6 +113,7 @@ private function getRootFolderStorageId(): ?int { /** * @RequireGroupFolderAdmin * @NoAdminRequired + * @PasswordConfirmationRequired */ public function addFolder(string $mountpoint): DataResponse { $id = $this->manager->createFolder($mountpoint); @@ -122,6 +123,7 @@ public function addFolder(string $mountpoint): DataResponse { /** * @NoAdminRequired * @RequireGroupFolderAdmin + * @PasswordConfirmationRequired */ public function removeFolder(int $id): DataResponse { $response = $this->checkFolderExists($id); @@ -137,6 +139,7 @@ public function removeFolder(int $id): DataResponse { /** * @NoAdminRequired * @RequireGroupFolderAdmin + * @PasswordConfirmationRequired */ public function setMountPoint(int $id, string $mountPoint): DataResponse { $this->manager->setMountPoint($id, $mountPoint); @@ -146,6 +149,7 @@ public function setMountPoint(int $id, string $mountPoint): DataResponse { /** * @NoAdminRequired * @RequireGroupFolderAdmin + * @PasswordConfirmationRequired */ public function addGroup(int $id, string $group): DataResponse { $response = $this->checkFolderExists($id); @@ -159,6 +163,7 @@ public function addGroup(int $id, string $group): DataResponse { /** * @NoAdminRequired * @RequireGroupFolderAdmin + * @PasswordConfirmationRequired */ public function removeGroup(int $id, string $group): DataResponse { $response = $this->checkFolderExists($id); @@ -172,6 +177,7 @@ public function removeGroup(int $id, string $group): DataResponse { /** * @NoAdminRequired * @RequireGroupFolderAdmin + * @PasswordConfirmationRequired */ public function setPermissions(int $id, string $group, int $permissions): DataResponse { $response = $this->checkFolderExists($id); @@ -185,6 +191,7 @@ public function setPermissions(int $id, string $group, int $permissions): DataRe /** * @NoAdminRequired * @RequireGroupFolderAdmin + * @PasswordConfirmationRequired * @throws \OCP\DB\Exception */ public function setManageACL(int $id, string $mappingType, string $mappingId, bool $manageAcl): DataResponse { @@ -199,6 +206,7 @@ public function setManageACL(int $id, string $mappingType, string $mappingId, bo /** * @NoAdminRequired * @RequireGroupFolderAdmin + * @PasswordConfirmationRequired */ public function setQuota(int $id, int $quota): DataResponse { $response = $this->checkFolderExists($id); @@ -212,6 +220,7 @@ public function setQuota(int $id, int $quota): DataResponse { /** * @NoAdminRequired * @RequireGroupFolderAdmin + * @PasswordConfirmationRequired */ public function setACL(int $id, bool $acl): DataResponse { $response = $this->checkFolderExists($id); @@ -225,6 +234,7 @@ public function setACL(int $id, bool $acl): DataResponse { /** * @NoAdminRequired * @RequireGroupFolderAdmin + * @PasswordConfirmationRequired */ public function renameFolder(int $id, string $mountpoint): DataResponse { $response = $this->checkFolderExists($id); diff --git a/package-lock.json b/package-lock.json index caa9a1bf3..f6e1a3072 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "dependencies": { "@nextcloud/axios": "^2.3.0", "@nextcloud/event-bus": "^3.0.2", + "@nextcloud/password-confirmation": "4.0.4", "@nextcloud/router": "^2.0.1", "@nextcloud/vue": "^7.7.1", "nextcloud-server": "^0.15.10", @@ -30,7 +31,6 @@ "@nextcloud/stylelint-config": "^2.3.0", "@nextcloud/webpack-vue-config": "^5.4.0", "@types/bootstrap": "^5.2.6", - "@types/jquery": "^3.5.16", "@types/react": "^17.0.43", "@types/react-dom": "^18.0.3", "@types/webpack": "^4.41.26", @@ -2367,6 +2367,44 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/@nextcloud/password-confirmation": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@nextcloud/password-confirmation/-/password-confirmation-4.0.4.tgz", + "integrity": "sha512-CdCOWwKU4ejKv0uABn3dfigwPH+tZKUOA38MzZDM4YyL1q9TgKOK90mnrJBvz6EBnlleZEvKlX94jjwPfOdvKw==", + "license": "MIT", + "dependencies": { + "@nextcloud/axios": "^2.0.0", + "@nextcloud/l10n": "^1.6.0", + "@nextcloud/router": "^2.0.0", + "@nextcloud/vue": "^7.0.0-beta.5", + "vue": "^2.7.10" + }, + "engines": { + "node": "^16.0.0", + "npm": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@nextcloud/password-confirmation/node_modules/@nextcloud/l10n": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@nextcloud/l10n/-/l10n-1.6.0.tgz", + "integrity": "sha512-aKGlgrwN9OiafN791sYus0shfwNeU3PlrH6Oi9ISma6iJSvN6a8aJM8WGKCJ9pqBaTR5PrDuckuM/WnybBWb6A==", + "license": "GPL-3.0-or-later", + "dependencies": { + "core-js": "^3.6.4", + "node-gettext": "^3.0.0" + } + }, + "node_modules/@nextcloud/password-confirmation/node_modules/core-js": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", + "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/@nextcloud/router": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-2.2.1.tgz", @@ -14741,6 +14779,34 @@ } } }, + "@nextcloud/password-confirmation": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@nextcloud/password-confirmation/-/password-confirmation-4.0.4.tgz", + "integrity": "sha512-CdCOWwKU4ejKv0uABn3dfigwPH+tZKUOA38MzZDM4YyL1q9TgKOK90mnrJBvz6EBnlleZEvKlX94jjwPfOdvKw==", + "requires": { + "@nextcloud/axios": "^2.0.0", + "@nextcloud/l10n": "^1.6.0", + "@nextcloud/router": "^2.0.0", + "@nextcloud/vue": "^7.0.0-beta.5", + "vue": "^2.7.10" + }, + "dependencies": { + "@nextcloud/l10n": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@nextcloud/l10n/-/l10n-1.6.0.tgz", + "integrity": "sha512-aKGlgrwN9OiafN791sYus0shfwNeU3PlrH6Oi9ISma6iJSvN6a8aJM8WGKCJ9pqBaTR5PrDuckuM/WnybBWb6A==", + "requires": { + "core-js": "^3.6.4", + "node-gettext": "^3.0.0" + } + }, + "core-js": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", + "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==" + } + } + }, "@nextcloud/router": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-2.2.1.tgz", diff --git a/package.json b/package.json index 55ac05b68..62605878e 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "@nextcloud/stylelint-config": "^2.3.0", "@nextcloud/webpack-vue-config": "^5.4.0", "@types/bootstrap": "^5.2.6", - "@types/jquery": "^3.5.16", "@types/react": "^17.0.43", "@types/react-dom": "^18.0.3", "@types/webpack": "^4.41.26", @@ -35,6 +34,7 @@ "dependencies": { "@nextcloud/axios": "^2.3.0", "@nextcloud/event-bus": "^3.0.2", + "@nextcloud/password-confirmation": "4.0.4", "@nextcloud/router": "^2.0.1", "@nextcloud/vue": "^7.7.1", "nextcloud-server": "^0.15.10", diff --git a/src/settings/Api.ts b/src/settings/Api.ts index 5d82c10d6..7897ea928 100644 --- a/src/settings/Api.ts +++ b/src/settings/Api.ts @@ -1,8 +1,8 @@ -import {OCSResult, AxiosOCSResult} from "NC"; -import Thenable = JQuery.Thenable; -import {FolderGroupsProps} from "./FolderGroups"; import axios from '@nextcloud/axios' import { generateUrl } from "@nextcloud/router"; +import { confirmPassword } from '@nextcloud/password-confirmation' +// eslint-disable-next-line n/no-unpublished-import +import type { OCSResponse } from '@nextcloud/typings/lib/ocs' export interface Group { gid: string; @@ -25,7 +25,6 @@ export interface ManageRuleProps { displayname: string; } - export interface Folder { id: number; mount_point: string; @@ -42,113 +41,113 @@ export class Api { return OC.generateUrl(`apps/groupfolders/${endpoint}`); } - listFolders(): Thenable { - return $.getJSON(this.getUrl('folders')) - .then((data: OCSResult) => Object.keys(data.ocs.data).map(id => data.ocs.data[id])); + async listFolders(): Promise { + const response = await axios.get>(this.getUrl('folders')) + return Object.keys(response.data.ocs.data).map(id => response.data.ocs.data[id]) } // Returns all NC groups - listGroups(): Thenable { - return $.getJSON(this.getUrl('delegation/groups')) - .then((data: OCSResult) => data.ocs.data) + async listGroups(): Promise { + const response = await axios.get>(this.getUrl('delegation/groups')) + return response.data.ocs.data } // Returns all groups that have been granted delegated admin or subadmin rights on groupfolders - listDelegatedGroups(classname: string): Thenable { - return axios.get(this.getUrl('/delegation/authorized-groups'), { params: { classname } }) - .then((data: AxiosOCSResult) => { - // The admin group is always there. We don't want the user to remove it - const groups = data.data.ocs.data.filter(g => g.gid !== 'admin') - return groups - }) + async listDelegatedGroups(classname: string): Promise { + const response = await axios.get>(this.getUrl('/delegation/authorized-groups'), { params: { classname } }) + return response.data.ocs.data.filter(g => g.gid !== 'admin') } // Updates the list of groups that have been granted delegated admin or subadmin rights on groupfolders - updateDelegatedGroups(newGroups: Group[], classname: string): Thenable { - return axios.post(generateUrl('/apps/settings/') + '/settings/authorizedgroups/saveSettings', { + async updateDelegatedGroups(newGroups: Group[], classname: string): Promise { + await confirmPassword() + + await axios.post(generateUrl('/apps/settings/') + '/settings/authorizedgroups/saveSettings', { newGroups, class: classname, }) - .then((data) => data.data) } - createFolder(mountPoint: string): Thenable { - return $.post(this.getUrl('folders'), { - mountpoint: mountPoint - }, null, 'json').then((data: OCSResult<{ id: number; }>) => data.ocs.data.id); + async createFolder(mountPoint: string): Promise { + await confirmPassword() + + const response = await axios.post>(this.getUrl('folders'), { mountpoint: mountPoint }) + return response.data.ocs.data } - deleteFolder(id: number): Thenable { - return $.ajax({ - url: this.getUrl(`folders/${id}`), - type: 'DELETE' - }); + async deleteFolder(id: number): Promise { + await confirmPassword() + + await axios.delete(this.getUrl(`folders/${id}`)) } - addGroup(folderId: number, group: string): Thenable { - return $.post(this.getUrl(`folders/${folderId}/groups`), { - group - }); + async addGroup(folderId: number, group: string): Promise { + await confirmPassword() + + await axios.post(this.getUrl(`folders/${folderId}/groups`), { group }) } - removeGroup(folderId: number, group: string): Thenable { - return $.ajax({ - url: this.getUrl(`folders/${folderId}/groups/${group}`), - type: 'DELETE' - }); + async removeGroup(folderId: number, group: string): Promise { + await confirmPassword() + + await axios.delete(this.getUrl(`folders/${folderId}/groups/${group}`)) } - setPermissions(folderId: number, group: string, permissions: number): Thenable { - return $.post(this.getUrl(`folders/${folderId}/groups/${group}`), { - permissions - }); + async setPermissions(folderId: number, group: string, permissions: number): Promise { + await confirmPassword() + + await axios.post(this.getUrl(`folders/${folderId}/groups/${group}`), { permissions }) } - setManageACL(folderId: number, type: string, id: string, manageACL: boolean): Thenable { - return $.post(this.getUrl(`folders/${folderId}/manageACL`), { + async setManageACL(folderId: number, type: string, id: string, manageACL: boolean): Promise { + await confirmPassword() + + await axios.post(this.getUrl(`folders/${folderId}/manageACL`), { mappingType: type, mappingId: id, - manageAcl: manageACL ? 1 : 0 - }); + manageAcl: manageACL ? 1 : 0, + }) } - setQuota(folderId: number, quota: number): Thenable { - return $.post(this.getUrl(`folders/${folderId}/quota`), { - quota - }); + async setQuota(folderId: number, quota: number): Promise { + await confirmPassword() + + await axios.post(this.getUrl(`folders/${folderId}/quota`), { quota }) } - setACL(folderId: number, acl: boolean): Thenable { - return $.post(this.getUrl(`folders/${folderId}/acl`), { - acl: acl ? 1 : 0 - }); + async setACL(folderId: number, acl: boolean): Promise { + await confirmPassword() + + await axios.post(this.getUrl(`folders/${folderId}/acl`), { acl: acl ? 1 : 0 }) } - renameFolder(folderId: number, mountpoint: string): Thenable { - return $.post(this.getUrl(`folders/${folderId}/mountpoint`), { - mountpoint - }); + async renameFolder(folderId: number, mountpoint: string): Promise { + await confirmPassword() + + await axios.post(this.getUrl(`folders/${folderId}/mountpoint`), { mountpoint }) } - aclMappingSearch(folderId: number, search: string): Thenable<{groups: OCSGroup[], users: OCSUser[]}> { - return $.getJSON(this.getUrl(`folders/${folderId}/search?format=json&search=${search}`)) - .then((data: OCSResult<{ groups: OCSGroup[]; users: OCSUser[]; }>) => { + async aclMappingSearch(folderId: number, search: string): Promise<{ + groups: ManageRuleProps[], + users: ManageRuleProps[] + }> { + const response = await axios.get>(this.getUrl(`folders/${folderId}/search`), { params: { search } }) + return { + groups: Object.values(response.data.ocs.data.groups).map((item) => { return { - groups: Object.values(data.ocs.data.groups).map((item) => { - return { - type: 'group', - id: item.gid, - displayname: item.displayname - } - }), - users: Object.values(data.ocs.data.users).map((item) => { - return { - type: 'user', - id: item.uid, - displayname: item.displayname - } - }) + type: 'group', + id: item.gid, + displayname: item.displayname, } - }); + }), + users: Object.values(response.data.ocs.data.users).map((item) => { + return { + type: 'user', + id: item.uid, + displayname: item.displayname, + } + }), + } } + } diff --git a/src/settings/Nextcloud.d.ts b/src/settings/Nextcloud.d.ts index 175fc1932..6dab658ae 100644 --- a/src/settings/Nextcloud.d.ts +++ b/src/settings/Nextcloud.d.ts @@ -72,35 +72,3 @@ declare namespace OC { } declare function t(app: string, string: string, vars?: { [key: string]: string }, count?: number, options?: EscapeOptions): string; - -declare module 'NC' { - export interface OCSResult { - ocs: { - data: T; - meta: { - status: 'ok' | 'failure'; - message: string; - statuscode: number; - totalitems: number; - itemsperpage: number; - } - } - } -} - -declare module 'NC' { - export interface AxiosOCSResult { - data: { - ocs: { - data: T; - meta: { - status: 'ok' | 'failure'; - message: string; - statuscode: number; - totalitems: number; - itemsperpage: number; - } - } - } - } -} \ No newline at end of file