Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Extract logic into separate files
Signed-off-by: Louis Chemineau <[email protected]>
  • Loading branch information
artonge committed Nov 28, 2022
commit a32c25e1c8870bf751ed5b3fb7efe94a2d0302d6
34 changes: 34 additions & 0 deletions apps/files_versions/src/utils/davClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @copyright 2022 Louis Chemineau <[email protected]>
*
* @author Louis Chemineau <[email protected]>
*
* @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 { createClient, getPatcher } from 'webdav'
import { generateRemoteUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios'

const rootPath = 'dav'

// force our axios
const patcher = getPatcher()
patcher.patch('request', axios)

// init webdav client on default dav endpoint
const remote = generateRemoteUrl(rootPath)
export default createClient(remote)
33 changes: 33 additions & 0 deletions apps/files_versions/src/utils/davRequest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @copyright Copyright (c) 2019 Louis Chmn <[email protected]>
*
* @author Louis Chmn <[email protected]>
*
* @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/>.
*
*/

export default `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:"
xmlns:oc="http://owncloud.org/ns"
xmlns:nc="http://nextcloud.org/ns"
xmlns:ocs="http://open-collaboration-services.org/ns">
<d:prop>
<d:getcontentlength />
<d:getcontenttype />
<d:getlastmodified />
</d:prop>
</d:propfind>`
27 changes: 27 additions & 0 deletions apps/files_versions/src/utils/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @copyright 2022 Louis Chemineau <[email protected]>
*
* @author Louis Chemineau <[email protected]>
*
* @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 { getLoggerBuilder } from '@nextcloud/logger'

export default getLoggerBuilder()
.setApp('files_version')
.detectUser()
.build()
124 changes: 124 additions & 0 deletions apps/files_versions/src/utils/versions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/**
* @copyright 2022 Louis Chemineau <[email protected]>
*
* @author Louis Chemineau <[email protected]>
*
* @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 { getCurrentUser } from '@nextcloud/auth'
import client from '../utils/davClient.js'
import davRequest from '../utils/davRequest.js'
import logger from '../utils/logger.js'
import { basename, joinPaths } from '@nextcloud/paths'
import { generateUrl } from '@nextcloud/router'
import { translate } from '@nextcloud/l10n'
import moment from '@nextcloud/moment'

/**
* @typedef {Object} Version
* @property {string} title - 'Current version' or ''
* @property {string} fileName - File name relative to the version DAV endpoint
* @property {string} mimeType - Empty for the current version, else the actual mime type of the version
* @property {string} size - Human readable size
* @property {string} type - 'file'
* @property {number} mtime - Version creation date as a timestamp
* @property {string} preview - Preview URL of the version
* @property {string} url - Download URL of the version
* @property {string|null} fileVersion - The version id, null for the current version
* @property {boolean} isCurrent - Whether this is the current version of the file
*/

/**
* @param fileInfo
* @return {Promise<Version[]>}
*/
export async function fetchVersions(fileInfo) {
const path = `/versions/${getCurrentUser()?.uid}/versions/${fileInfo.id}`

try {
/** @type {import('webdav').FileStat[]} */
const response = await client.getDirectoryContents(path, {
data: davRequest,
})
return response.map(version => formatVersion(version, fileInfo))
} catch (exception) {
logger.error('Could not fetch version', { exception })
throw exception
}
}

/**
* Restore the given version
*
* @param {Version} version
* @param {object} fileInfo
*/
export async function restoreVersion(version, fileInfo) {
try {
logger.debug('Restoring version', { url: version.url })
await client.moveFile(
`/versions/${getCurrentUser()?.uid}/versions/${fileInfo.id}/${version.fileVersion}`,
`/versions/${getCurrentUser()?.uid}/restore/target`
)
} catch (exception) {
logger.error('Could not restore version', { exception })
throw exception
}
}

/**
* Format version
*
* @param {object} version - raw version received from the versions DAV endpoint
* @param {object} fileInfo - file properties received from the files DAV endpoint
* @return {Version}
*/
function formatVersion(version, fileInfo) {
const isCurrent = version.mime === ''
const fileVersion = isCurrent ? null : basename(version.filename)

let url = null
let preview = null

if (isCurrent) {
// https://nextcloud_server2.test/remote.php/webdav/welcome.txt?downloadStartSecret=hl5awd7tbzg
url = joinPaths('/remote.php/webdav', fileInfo.path, fileInfo.name)
preview = generateUrl('/core/preview?fileId={fileId}&c={fileEtag}&x=250&y=250&forceIcon=0&a=0', {
fileId: fileInfo.id,
fileEtag: fileInfo.etag,
})
} else {
url = joinPaths('/remote.php/dav', version.filename)
preview = generateUrl('/apps/files_versions/preview?file={file}&version={fileVersion}', {
file: joinPaths(fileInfo.path, fileInfo.name),
fileVersion,
})
}

return {
title: isCurrent ? translate('files_versions', 'Current version') : '',
fileName: version.filename,
mimeType: version.mime,
size: isCurrent ? fileInfo.size : version.size,
type: version.type,
mtime: moment(isCurrent ? fileInfo.mtime : version.lastmod).unix(),
preview,
url,
fileVersion,
isCurrent,
}
}
Loading