diff options
Diffstat (limited to 'apps/comments/src/services')
-rw-r--r-- | apps/comments/src/services/CommentsInstance.js | 58 | ||||
-rw-r--r-- | apps/comments/src/services/DavClient.js | 49 | ||||
-rw-r--r-- | apps/comments/src/services/DeleteComment.js | 31 | ||||
-rw-r--r-- | apps/comments/src/services/EditComment.js | 31 | ||||
-rw-r--r-- | apps/comments/src/services/GetComments.js | 104 | ||||
-rw-r--r-- | apps/comments/src/services/GetComments.ts | 67 | ||||
-rw-r--r-- | apps/comments/src/services/NewComment.js | 49 | ||||
-rw-r--r-- | apps/comments/src/services/ReadComments.ts | 38 |
8 files changed, 180 insertions, 247 deletions
diff --git a/apps/comments/src/services/CommentsInstance.js b/apps/comments/src/services/CommentsInstance.js index f5263f35c3d..cc45d0cbea7 100644 --- a/apps/comments/src/services/CommentsInstance.js +++ b/apps/comments/src/services/CommentsInstance.js @@ -1,34 +1,18 @@ /** - * @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { getLoggerBuilder } from '@nextcloud/logger' -import { translate as t, translatePlural as n } from '@nextcloud/l10n' -import CommentsApp from '../views/Comments' +import { getCSPNonce } from '@nextcloud/auth' +import { t, n } from '@nextcloud/l10n' +import { PiniaVuePlugin, createPinia } from 'pinia' import Vue from 'vue' +import CommentsApp from '../views/Comments.vue' +import logger from '../logger.js' -const logger = getLoggerBuilder() - .setApp('comments') - .detectUser() - .build() +Vue.use(PiniaVuePlugin) +// eslint-disable-next-line camelcase +__webpack_nonce__ = getCSPNonce() // Add translates functions Vue.mixin({ @@ -48,19 +32,21 @@ export default class CommentInstance { /** * Initialize a new Comments instance for the desired type * - * @param {string} commentsType the comments endpoint type + * @param {string} resourceType the comments endpoint type * @param {object} options the vue options (propsData, parent, el...) */ - constructor(commentsType = 'files', options) { - // Add comments type as a global mixin - Vue.mixin({ - data() { - return { - commentsType, - } - }, - }) + constructor(resourceType = 'files', options = {}) { + const pinia = createPinia() + // Merge options and set `resourceType` property + options = { + ...options, + propsData: { + ...(options.propsData ?? {}), + resourceType, + }, + pinia, + } // Init Comments component const View = Vue.extend(CommentsApp) return new View(options) diff --git a/apps/comments/src/services/DavClient.js b/apps/comments/src/services/DavClient.js index ee5aec129c1..3e9a529283f 100644 --- a/apps/comments/src/services/DavClient.js +++ b/apps/comments/src/services/DavClient.js @@ -1,38 +1,27 @@ /** - * @copyright Copyright (c) 2021 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { createClient, getPatcher } from 'webdav' -import axios from '@nextcloud/axios' - -import { getRootPath } from '../utils/davUtils' - -// Add this so the server knows it is an request from the browser -axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest' - -// force our axios -const patcher = getPatcher() -patcher.patch('request', axios) +import { createClient } from 'webdav' +import { getRootPath } from '../utils/davUtils.js' +import { getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth' // init webdav client const client = createClient(getRootPath()) +// set CSRF token header +const setHeaders = (token) => { + client.setHeaders({ + // Add this so the server knows it is an request from the browser + 'X-Requested-With': 'XMLHttpRequest', + // Inject user auth + requesttoken: token ?? '', + }) +} + +// refresh headers when request token changes +onRequestTokenUpdate(setHeaders) +setHeaders(getRequestToken()) + export default client diff --git a/apps/comments/src/services/DeleteComment.js b/apps/comments/src/services/DeleteComment.js index 871f6b6c5b8..1ed63d7836a 100644 --- a/apps/comments/src/services/DeleteComment.js +++ b/apps/comments/src/services/DeleteComment.js @@ -1,36 +1,19 @@ /** - * @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ -import client from './DavClient' +import client from './DavClient.js' /** * Delete a comment * - * @param {string} commentsType the ressource type - * @param {number} ressourceId the ressource ID + * @param {string} resourceType the resource type + * @param {number} resourceId the resource ID * @param {number} commentId the comment iD */ -export default async function(commentsType, ressourceId, commentId) { - const commentPath = ['', commentsType, ressourceId, commentId].join('/') +export default async function(resourceType, resourceId, commentId) { + const commentPath = ['', resourceType, resourceId, commentId].join('/') // Fetch newly created comment data await client.deleteFile(commentPath) diff --git a/apps/comments/src/services/EditComment.js b/apps/comments/src/services/EditComment.js index f3a2d857356..4ec33415a72 100644 --- a/apps/comments/src/services/EditComment.js +++ b/apps/comments/src/services/EditComment.js @@ -1,37 +1,20 @@ /** - * @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ -import client from './DavClient' +import client from './DavClient.js' /** * Edit an existing comment * - * @param {string} commentsType the ressource type - * @param {number} ressourceId the ressource ID + * @param {string} resourceType the resource type + * @param {number} resourceId the resource ID * @param {number} commentId the comment iD * @param {string} message the message content */ -export default async function(commentsType, ressourceId, commentId, message) { - const commentPath = ['', commentsType, ressourceId, commentId].join('/') +export default async function(resourceType, resourceId, commentId, message) { + const commentPath = ['', resourceType, resourceId, commentId].join('/') return await client.customRequest(commentPath, Object.assign({ method: 'PROPPATCH', diff --git a/apps/comments/src/services/GetComments.js b/apps/comments/src/services/GetComments.js deleted file mode 100644 index 4d1f7b022ae..00000000000 --- a/apps/comments/src/services/GetComments.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -import { parseXML, prepareFileFromProps } from 'webdav/dist/node/tools/dav' -import { processResponsePayload } from 'webdav/dist/node/response' -import client from './DavClient' - -export const DEFAULT_LIMIT = 20 -/** - * Retrieve the comments list - * - * @param {object} data destructuring object - * @param {string} data.commentsType the ressource type - * @param {number} data.ressourceId the ressource ID - * @param {object} [options] optional options for axios - * @return {object[]} the comments list - */ -export default async function({ commentsType, ressourceId }, options = {}) { - let response = null - const ressourcePath = ['', commentsType, ressourceId].join('/') - - return await client.customRequest(ressourcePath, Object.assign({ - method: 'REPORT', - data: `<?xml version="1.0"?> - <oc:filter-comments - xmlns:d="DAV:" - xmlns:oc="http://owncloud.org/ns" - xmlns:nc="http://nextcloud.org/ns" - xmlns:ocs="http://open-collaboration-services.org/ns"> - <oc:limit>${DEFAULT_LIMIT}</oc:limit> - <oc:offset>${options.offset || 0}</oc:offset> - </oc:filter-comments>`, - }, options)) - // See example on how it's done normaly - // https://github.com/perry-mitchell/webdav-client/blob/9de2da4a2599e06bd86c2778145b7ade39fe0b3c/source/interface/stat.js#L19 - // Waiting for proper REPORT integration https://github.com/perry-mitchell/webdav-client/issues/207 - .then(res => { - response = res - return res.data - }) - .then(parseXML) - .then(xml => processMultistatus(xml, true)) - .then(comments => processResponsePayload(response, comments, true)) - .then(response => response.data) -} - -// https://github.com/perry-mitchell/webdav-client/blob/9de2da4a2599e06bd86c2778145b7ade39fe0b3c/source/interface/directoryContents.js#L32 -/** - * @param {any} result - - * @param {any} isDetailed - - */ -function processMultistatus(result, isDetailed = false) { - // Extract the response items (directory contents) - const { - multistatus: { response: responseItems }, - } = result - return responseItems.map(item => { - // Each item should contain a stat object - const { - propstat: { prop: props }, - } = item - // Decode HTML entities - const decodedProps = { - ...props, - // Decode twice to handle potentially double-encoded entities - // FIXME Remove this once https://github.com/nextcloud/server/issues/29306 is resolved - actorDisplayName: decodeHtmlEntities(props.actorDisplayName, 2), - message: decodeHtmlEntities(props.message, 2), - } - return prepareFileFromProps(decodedProps, decodedProps.id.toString(), isDetailed) - }) -} - -/** - * @param {any} value - - * @param {any} passes - - */ -function decodeHtmlEntities(value, passes = 1) { - const parser = new DOMParser() - let decoded = value - for (let i = 0; i < passes; i++) { - decoded = parser.parseFromString(decoded, 'text/html').documentElement.textContent - } - return decoded -} diff --git a/apps/comments/src/services/GetComments.ts b/apps/comments/src/services/GetComments.ts new file mode 100644 index 00000000000..c42aa21d6cb --- /dev/null +++ b/apps/comments/src/services/GetComments.ts @@ -0,0 +1,67 @@ +/** + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { parseXML, type DAVResult, type FileStat, type ResponseDataDetailed } from 'webdav' + +// https://github.com/perry-mitchell/webdav-client/issues/339 +import { processResponsePayload } from 'webdav/dist/node/response.js' +import { prepareFileFromProps } from 'webdav/dist/node/tools/dav.js' +import client from './DavClient.js' + +export const DEFAULT_LIMIT = 20 + +/** + * Retrieve the comments list + * + * @param {object} data destructuring object + * @param {string} data.resourceType the resource type + * @param {number} data.resourceId the resource ID + * @param {object} [options] optional options for axios + * @param {number} [options.offset] the pagination offset + * @param {number} [options.limit] the pagination limit, defaults to 20 + * @param {Date} [options.datetime] optional date to query + * @return {{data: object[]}} the comments list + */ +export const getComments = async function({ resourceType, resourceId }, options: { offset: number, limit?: number, datetime?: Date }) { + const resourcePath = ['', resourceType, resourceId].join('/') + const datetime = options.datetime ? `<oc:datetime>${options.datetime.toISOString()}</oc:datetime>` : '' + const response = await client.customRequest(resourcePath, Object.assign({ + method: 'REPORT', + data: `<?xml version="1.0"?> + <oc:filter-comments + xmlns:d="DAV:" + xmlns:oc="http://owncloud.org/ns" + xmlns:nc="http://nextcloud.org/ns" + xmlns:ocs="http://open-collaboration-services.org/ns"> + <oc:limit>${options.limit ?? DEFAULT_LIMIT}</oc:limit> + <oc:offset>${options.offset || 0}</oc:offset> + ${datetime} + </oc:filter-comments>`, + }, options)) + + const responseData = await response.text() + const result = await parseXML(responseData) + const stat = getDirectoryFiles(result, true) + return processResponsePayload(response, stat, true) as ResponseDataDetailed<FileStat[]> +} + +// https://github.com/perry-mitchell/webdav-client/blob/8d9694613c978ce7404e26a401c39a41f125f87f/source/operations/directoryContents.ts +const getDirectoryFiles = function( + result: DAVResult, + isDetailed = false, +): Array<FileStat> { + // Extract the response items (directory contents) + const { + multistatus: { response: responseItems }, + } = result + + // Map all items to a consistent output structure (results) + return responseItems.map(item => { + // Each item should contain a stat object + const props = item.propstat!.prop! + + return prepareFileFromProps(props, props.id!.toString(), isDetailed) + }) +} diff --git a/apps/comments/src/services/NewComment.js b/apps/comments/src/services/NewComment.js index eaf08cc10b9..663b4d72e02 100644 --- a/apps/comments/src/services/NewComment.js +++ b/apps/comments/src/services/NewComment.js @@ -1,59 +1,50 @@ /** - * @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ import { getCurrentUser } from '@nextcloud/auth' -import { getRootPath } from '../utils/davUtils' +import { getRootPath } from '../utils/davUtils.js' +import { decodeHtmlEntities } from '../utils/decodeHtmlEntities.js' import axios from '@nextcloud/axios' -import client from './DavClient' +import client from './DavClient.js' /** * Retrieve the comments list * - * @param {string} commentsType the ressource type - * @param {number} ressourceId the ressource ID + * @param {string} resourceType the resource type + * @param {number} resourceId the resource ID * @param {string} message the message * @return {object} the new comment */ -export default async function(commentsType, ressourceId, message) { - const ressourcePath = ['', commentsType, ressourceId].join('/') +export default async function(resourceType, resourceId, message) { + const resourcePath = ['', resourceType, resourceId].join('/') - const response = await axios.post(getRootPath() + ressourcePath, { + const response = await axios.post(getRootPath() + resourcePath, { actorDisplayName: getCurrentUser().displayName, actorId: getCurrentUser().uid, actorType: 'users', creationDateTime: (new Date()).toUTCString(), message, - objectType: 'files', + objectType: resourceType, verb: 'comment', }) - // Retrieve comment id from ressource location + // Retrieve comment id from resource location const commentId = parseInt(response.headers['content-location'].split('/').pop()) - const commentPath = ressourcePath + '/' + commentId + const commentPath = resourcePath + '/' + commentId // Fetch newly created comment data const comment = await client.stat(commentPath, { details: true, }) + const props = comment.data.props + // Decode twice to handle potentially double-encoded entities + // FIXME Remove this once https://github.com/nextcloud/server/issues/29306 + // is resolved + props.actorDisplayName = decodeHtmlEntities(props.actorDisplayName, 2) + props.message = decodeHtmlEntities(props.message, 2) + return comment.data } diff --git a/apps/comments/src/services/ReadComments.ts b/apps/comments/src/services/ReadComments.ts new file mode 100644 index 00000000000..73682e21d95 --- /dev/null +++ b/apps/comments/src/services/ReadComments.ts @@ -0,0 +1,38 @@ +/** + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import client from './DavClient.js' + +import type { Response } from 'webdav' + +/** + * Mark comments older than the date timestamp as read + * + * @param resourceType the resource type + * @param resourceId the resource ID + * @param date the date object + */ +export const markCommentsAsRead = ( + resourceType: string, + resourceId: number, + date: Date, +): Promise<Response> => { + const resourcePath = ['', resourceType, resourceId].join('/') + const readMarker = date.toUTCString() + + return client.customRequest(resourcePath, { + method: 'PROPPATCH', + data: `<?xml version="1.0"?> + <d:propertyupdate + xmlns:d="DAV:" + xmlns:oc="http://owncloud.org/ns"> + <d:set> + <d:prop> + <oc:readMarker>${readMarker}</oc:readMarker> + </d:prop> + </d:set> + </d:propertyupdate>`, + }) +} |