mirror of
https://github.com/nextcloud/server.git
synced 2026-05-28 04:32:30 -04:00
fix(encryption): Correctly set encrypted to 0 when copying
If encryption got disabled, copying should set encrypted to 0 for the new unencrypted copy. For instance when using encryption:decrypt-all Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com> Signed-off-by: Louis Chemineau <louis@chmn.me>
This commit is contained in:
parent
186e725910
commit
6d672c4cba
4 changed files with 92 additions and 44 deletions
|
|
@ -9,6 +9,7 @@ import type { TemplateFile } from '../types.ts'
|
|||
|
||||
import { Folder, Node, Permission, addNewFileMenuEntry } from '@nextcloud/files'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import { isPublicShare } from '@nextcloud/sharing/public'
|
||||
import { newNodeName } from '../utils/newNodeDialog'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import Vue, { defineAsyncComponent } from 'vue'
|
||||
|
|
@ -46,7 +47,12 @@ const getTemplatePicker = async (context: Folder) => {
|
|||
* Register all new-file-menu entries for all template providers
|
||||
*/
|
||||
export function registerTemplateEntries() {
|
||||
const templates = loadState<TemplateFile[]>('files', 'templates', [])
|
||||
let templates: TemplateFile[]
|
||||
if (isPublicShare()) {
|
||||
templates = loadState<TemplateFile[]>('files_sharing', 'templates', [])
|
||||
} else {
|
||||
templates = loadState<TemplateFile[]>('files', 'templates', [])
|
||||
}
|
||||
|
||||
// Init template files menu
|
||||
templates.forEach((provider, index) => {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ import type { TemplateFile } from '../types.ts'
|
|||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
import { showError, spawnDialog } from '@nextcloud/dialogs'
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
import { File } from '@nextcloud/files'
|
||||
import { File, Node } from '@nextcloud/files'
|
||||
import { getClient, getRootPath, resultToNode, getDefaultPropfind } from '@nextcloud/files/dav'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import { generateRemoteUrl } from '@nextcloud/router'
|
||||
import { normalize, extname, join } from 'path'
|
||||
|
|
@ -64,6 +65,7 @@ import NcModal from '@nextcloud/vue/components/NcModal'
|
|||
import TemplatePreview from '../components/TemplatePreview.vue'
|
||||
import TemplateFiller from '../components/TemplateFiller.vue'
|
||||
import logger from '../logger.ts'
|
||||
import type { FileStat, ResponseDataDetailed } from 'webdav'
|
||||
|
||||
const border = 2
|
||||
const margin = 8
|
||||
|
|
@ -167,6 +169,12 @@ export default defineComponent({
|
|||
this.name = name
|
||||
this.provider = provider
|
||||
|
||||
// Skip templates logic for external users.
|
||||
if (getCurrentUser() === null) {
|
||||
this.onSubmit()
|
||||
return
|
||||
}
|
||||
|
||||
const templates = await getTemplates()
|
||||
const fetchedProvider = templates.find((fetchedProvider) => fetchedProvider.app === provider.app && fetchedProvider.label === provider.label)
|
||||
if (fetchedProvider === null) {
|
||||
|
|
@ -224,56 +232,80 @@ export default defineComponent({
|
|||
this.name = `${this.name}${this.provider?.extension ?? ''}`
|
||||
}
|
||||
|
||||
try {
|
||||
const fileInfo = await createFromTemplate(
|
||||
normalize(`${currentDirectory}/${this.name}`),
|
||||
this.selectedTemplate?.filename as string ?? '',
|
||||
this.selectedTemplate?.templateType as string ?? '',
|
||||
templateFields,
|
||||
)
|
||||
logger.debug('Created new file', fileInfo)
|
||||
// Create a blank file for external users as we can't use the templates.
|
||||
if (getCurrentUser() === null) {
|
||||
const client = getClient()
|
||||
const filename = join(getRootPath(), currentDirectory, this.name ?? '')
|
||||
|
||||
const owner = getCurrentUser()?.uid || null
|
||||
const node = new File({
|
||||
id: fileInfo.fileid,
|
||||
source: generateRemoteUrl(join(`dav/files/${owner}`, fileInfo.filename)),
|
||||
root: `/files/${owner}`,
|
||||
mime: fileInfo.mime,
|
||||
mtime: new Date(fileInfo.lastmod * 1000),
|
||||
owner,
|
||||
size: fileInfo.size,
|
||||
permissions: fileInfo.permissions,
|
||||
attributes: {
|
||||
// Inherit some attributes from parent folder like the mount type and real owner
|
||||
'mount-type': this.parent?.attributes?.['mount-type'],
|
||||
'owner-id': this.parent?.attributes?.['owner-id'],
|
||||
'owner-display-name': this.parent?.attributes?.['owner-display-name'],
|
||||
...fileInfo,
|
||||
'has-preview': fileInfo.hasPreview,
|
||||
},
|
||||
})
|
||||
await client.putFileContents(filename, '')
|
||||
const response = await client.stat(filename, { data: getDefaultPropfind(), details: true }) as ResponseDataDetailed<FileStat>
|
||||
logger.debug('Created new file', { fileInfo: response.data })
|
||||
|
||||
// Update files list
|
||||
emit('files:node:created', node)
|
||||
const node = resultToNode(response.data)
|
||||
|
||||
// Open the new file
|
||||
window.OCP.Files.Router.goToRoute(
|
||||
null, // use default route
|
||||
{ view: 'files', fileid: node.fileid },
|
||||
{ dir: node.dirname, openfile: 'true' },
|
||||
)
|
||||
this.handleFileCreation(node)
|
||||
} else {
|
||||
try {
|
||||
const fileInfo = await createFromTemplate(
|
||||
normalize(`${currentDirectory}/${this.name}`),
|
||||
this.selectedTemplate?.filename as string ?? '',
|
||||
this.selectedTemplate?.templateType as string ?? '',
|
||||
templateFields,
|
||||
)
|
||||
logger.debug('Created new file', { fileInfo })
|
||||
|
||||
// Close the picker
|
||||
this.close()
|
||||
} catch (error) {
|
||||
logger.error('Error while creating the new file from template', { error })
|
||||
showError(t('files', 'Unable to create new file from template'))
|
||||
} finally {
|
||||
this.loading = false
|
||||
const owner = getCurrentUser()?.uid || null
|
||||
const node = new File({
|
||||
id: fileInfo.fileid,
|
||||
source: generateRemoteUrl(join(`dav/files/${owner}`, fileInfo.filename)),
|
||||
root: `/files/${owner}`,
|
||||
mime: fileInfo.mime,
|
||||
mtime: new Date(fileInfo.lastmod * 1000),
|
||||
owner,
|
||||
size: fileInfo.size,
|
||||
permissions: fileInfo.permissions,
|
||||
attributes: {
|
||||
// Inherit some attributes from parent folder like the mount type and real owner
|
||||
'mount-type': this.parent?.attributes?.['mount-type'],
|
||||
'owner-id': this.parent?.attributes?.['owner-id'],
|
||||
'owner-display-name': this.parent?.attributes?.['owner-display-name'],
|
||||
...fileInfo,
|
||||
'has-preview': fileInfo.hasPreview,
|
||||
},
|
||||
})
|
||||
|
||||
this.handleFileCreation(node)
|
||||
|
||||
// Close the picker
|
||||
this.close()
|
||||
} catch (error) {
|
||||
logger.error('Error while creating the new file from template', { error })
|
||||
showError(t('files', 'Unable to create new file from template'))
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleFileCreation(node: Node) {
|
||||
// Update files list
|
||||
emit('files:node:created', node)
|
||||
|
||||
// Open the new file
|
||||
window.OCP.Files.Router.goToRoute(
|
||||
null, // use default route
|
||||
{ view: 'files', fileid: node.fileid },
|
||||
{ dir: node.dirname, openfile: 'true' },
|
||||
)
|
||||
},
|
||||
|
||||
async onSubmit() {
|
||||
// Skip templates logic for external users.
|
||||
if (getCurrentUser() === null) {
|
||||
this.loading = true
|
||||
return this.createFile()
|
||||
}
|
||||
|
||||
const fileId = this.selectedTemplate?.fileid
|
||||
|
||||
// Only request field extraction if there is a valid template
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ use OCP\Constants;
|
|||
use OCP\Defaults;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Template\ITemplateManager;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
|
|
@ -49,6 +50,7 @@ class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider
|
|||
private Defaults $defaults,
|
||||
private IConfig $config,
|
||||
private IRequest $request,
|
||||
private ITemplateManager $templateManager,
|
||||
private IInitialState $initialState,
|
||||
private IAppConfig $appConfig,
|
||||
) {
|
||||
|
|
@ -119,6 +121,8 @@ class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider
|
|||
$this->eventDispatcher->dispatchTyped(new LoadViewer());
|
||||
}
|
||||
|
||||
$this->initialState->provideInitialState('templates', $this->templateManager->listCreators());
|
||||
|
||||
// Allow external apps to register their scripts
|
||||
$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use OCP\EventDispatcher\IEventDispatcher;
|
|||
use OCP\Files\File;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\Template\ITemplateManager;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
|
|
@ -68,6 +69,7 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
private Manager&MockObject $shareManager;
|
||||
private IPreview&MockObject $previewManager;
|
||||
private IUserManager&MockObject $userManager;
|
||||
private ITemplateManager&MockObject $templateManager;
|
||||
private IInitialState&MockObject $initialState;
|
||||
private IURLGenerator&MockObject $urlGenerator;
|
||||
private ISecureRandom&MockObject $secureRandom;
|
||||
|
|
@ -87,6 +89,7 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->appConfig = $this->createMock(IAppConfig::class);
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
$this->templateManager = $this->createMock(ITemplateManager::class);
|
||||
$this->initialState = $this->createMock(IInitialState::class);
|
||||
$this->federatedShareProvider = $this->createMock(FederatedShareProvider::class);
|
||||
$this->federatedShareProvider->expects($this->any())
|
||||
|
|
@ -114,6 +117,7 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
$this->defaults,
|
||||
$this->config,
|
||||
$this->createMock(IRequest::class),
|
||||
$this->templateManager,
|
||||
$this->initialState,
|
||||
$this->appConfig,
|
||||
)
|
||||
|
|
@ -338,6 +342,7 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
'owner' => 'ownerUID',
|
||||
'ownerDisplayName' => 'ownerDisplay',
|
||||
'isFileRequest' => false,
|
||||
'templates' => [],
|
||||
];
|
||||
|
||||
$response = $this->shareController->showShare();
|
||||
|
|
@ -485,6 +490,7 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
'isFileRequest' => false,
|
||||
'note' => 'The note',
|
||||
'label' => 'A label',
|
||||
'templates' => [],
|
||||
];
|
||||
|
||||
$response = $this->shareController->showShare();
|
||||
|
|
|
|||
Loading…
Reference in a new issue