Skip to content

Commit 1453717

Browse files
committed
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>
1 parent d07e479 commit 1453717

File tree

4 files changed

+93
-47
lines changed

4 files changed

+93
-47
lines changed

apps/files/src/newMenu/newFromTemplate.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { TemplateFile } from '../types.ts'
99

1010
import { Folder, Node, Permission, addNewFileMenuEntry } from '@nextcloud/files'
1111
import { loadState } from '@nextcloud/initial-state'
12+
import { isPublicShare } from '@nextcloud/sharing/public'
1213
import { newNodeName } from '../utils/newNodeDialog'
1314
import { translate as t } from '@nextcloud/l10n'
1415
import Vue, { defineAsyncComponent } from 'vue'
@@ -46,7 +47,12 @@ const getTemplatePicker = async (context: Folder) => {
4647
* Register all new-file-menu entries for all template providers
4748
*/
4849
export function registerTemplateEntries() {
49-
const templates = loadState<TemplateFile[]>('files', 'templates', [])
50+
let templates: TemplateFile[]
51+
if (isPublicShare()) {
52+
templates = loadState<TemplateFile[]>('files_sharing', 'templates', [])
53+
} else {
54+
templates = loadState<TemplateFile[]>('files', 'templates', [])
55+
}
5056

5157
// Init template files menu
5258
templates.forEach((provider, index) => {

apps/files/src/views/TemplatePicker.vue

Lines changed: 78 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ import type { TemplateFile } from '../types.ts'
5050
import { getCurrentUser } from '@nextcloud/auth'
5151
import { showError, spawnDialog } from '@nextcloud/dialogs'
5252
import { emit } from '@nextcloud/event-bus'
53-
import { File } from '@nextcloud/files'
53+
import { File, Node } from '@nextcloud/files'
54+
import { getClient, getRootPath, resultToNode, getDefaultPropfind } from '@nextcloud/files/dav'
5455
import { translate as t } from '@nextcloud/l10n'
5556
import { generateRemoteUrl } from '@nextcloud/router'
5657
import { normalize, extname, join } from 'path'
@@ -62,6 +63,7 @@ import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
6263
import TemplatePreview from '../components/TemplatePreview.vue'
6364
import TemplateFiller from '../components/TemplateFiller.vue'
6465
import logger from '../logger.ts'
66+
import type { FileStat, ResponseDataDetailed } from 'webdav'
6567
6668
const border = 2
6769
const margin = 8
@@ -165,6 +167,12 @@ export default defineComponent({
165167
this.name = name
166168
this.provider = provider
167169
170+
// Skip templates logic for external users.
171+
if (getCurrentUser() === null) {
172+
this.onSubmit()
173+
return
174+
}
175+
168176
const templates = await getTemplates()
169177
const fetchedProvider = templates.find((fetchedProvider) => fetchedProvider.app === provider.app && fetchedProvider.label === provider.label)
170178
if (fetchedProvider === null) {
@@ -216,56 +224,80 @@ export default defineComponent({
216224
this.name = `${this.name}${this.provider?.extension ?? ''}`
217225
}
218226
219-
try {
220-
const fileInfo = await createFromTemplate(
221-
normalize(`${currentDirectory}/${this.name}`),
222-
this.selectedTemplate?.filename as string ?? '',
223-
this.selectedTemplate?.templateType as string ?? '',
224-
templateFields,
225-
)
226-
logger.debug('Created new file', fileInfo)
227-
228-
const owner = getCurrentUser()?.uid || null
229-
const node = new File({
230-
id: fileInfo.fileid,
231-
source: generateRemoteUrl(join(`dav/files/${owner}`, fileInfo.filename)),
232-
root: `/files/${owner}`,
233-
mime: fileInfo.mime,
234-
mtime: new Date(fileInfo.lastmod * 1000),
235-
owner,
236-
size: fileInfo.size,
237-
permissions: fileInfo.permissions,
238-
attributes: {
239-
// Inherit some attributes from parent folder like the mount type and real owner
240-
'mount-type': this.parent?.attributes?.['mount-type'],
241-
'owner-id': this.parent?.attributes?.['owner-id'],
242-
'owner-display-name': this.parent?.attributes?.['owner-display-name'],
243-
...fileInfo,
244-
'has-preview': fileInfo.hasPreview,
245-
},
246-
})
227+
// Create a blank file for external users as we can't use the templates.
228+
if (getCurrentUser() === null) {
229+
const client = getClient()
230+
const filename = join(getRootPath(), currentDirectory, this.name ?? '')
231+
232+
await client.putFileContents(filename, '')
233+
const response = await client.stat(filename, { data: getDefaultPropfind(), details: true }) as ResponseDataDetailed<FileStat>
234+
logger.debug('Created new file', { fileInfo: response.data })
235+
236+
const node = resultToNode(response.data)
247237
248-
// Update files list
249-
emit('files:node:created', node)
250-
251-
// Open the new file
252-
window.OCP.Files.Router.goToRoute(
253-
null, // use default route
254-
{ view: 'files', fileid: node.fileid },
255-
{ dir: node.dirname, openfile: 'true' },
256-
)
257-
258-
// Close the picker
259-
this.close()
260-
} catch (error) {
261-
logger.error('Error while creating the new file from template', { error })
262-
showError(t('files', 'Unable to create new file from template'))
263-
} finally {
264-
this.loading = false
238+
this.handleFileCreation(node)
239+
} else {
240+
try {
241+
const fileInfo = await createFromTemplate(
242+
normalize(`${currentDirectory}/${this.name}`),
243+
this.selectedTemplate?.filename as string ?? '',
244+
this.selectedTemplate?.templateType as string ?? '',
245+
templateFields,
246+
)
247+
logger.debug('Created new file', { fileInfo })
248+
249+
const owner = getCurrentUser()?.uid || null
250+
const node = new File({
251+
id: fileInfo.fileid,
252+
source: generateRemoteUrl(join(`dav/files/${owner}`, fileInfo.filename)),
253+
root: `/files/${owner}`,
254+
mime: fileInfo.mime,
255+
mtime: new Date(fileInfo.lastmod * 1000),
256+
owner,
257+
size: fileInfo.size,
258+
permissions: fileInfo.permissions,
259+
attributes: {
260+
// Inherit some attributes from parent folder like the mount type and real owner
261+
'mount-type': this.parent?.attributes?.['mount-type'],
262+
'owner-id': this.parent?.attributes?.['owner-id'],
263+
'owner-display-name': this.parent?.attributes?.['owner-display-name'],
264+
...fileInfo,
265+
'has-preview': fileInfo.hasPreview,
266+
},
267+
})
268+
269+
this.handleFileCreation(node)
270+
271+
// Close the picker
272+
this.close()
273+
} catch (error) {
274+
logger.error('Error while creating the new file from template', { error })
275+
showError(t('files', 'Unable to create new file from template'))
276+
} finally {
277+
this.loading = false
278+
}
265279
}
266280
},
267281
282+
handleFileCreation(node: Node) {
283+
// Update files list
284+
emit('files:node:created', node)
285+
286+
// Open the new file
287+
window.OCP.Files.Router.goToRoute(
288+
null, // use default route
289+
{ view: 'files', fileid: node.fileid },
290+
{ dir: node.dirname, openfile: 'true' },
291+
)
292+
},
293+
268294
async onSubmit() {
295+
// Skip templates logic for external users.
296+
if (getCurrentUser() === null) {
297+
this.loading = true
298+
return this.createFile()
299+
}
300+
269301
if (this.selectedTemplate?.fields?.length > 0) {
270302
spawnDialog(TemplateFiller, {
271303
fields: this.selectedTemplate.fields,

apps/files_sharing/lib/DefaultPublicShareTemplateProvider.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use OCP\EventDispatcher\IEventDispatcher;
2626
use OCP\Files\FileInfo;
2727
use OCP\Files\Folder;
28+
use OCP\Files\Template\ITemplateManager;
2829
use OCP\IConfig;
2930
use OCP\IL10N;
3031
use OCP\IPreview;
@@ -50,6 +51,7 @@ public function __construct(
5051
private Defaults $defaults,
5152
private IConfig $config,
5253
private IRequest $request,
54+
private ITemplateManager $templateManager,
5355
private IInitialState $initialState,
5456
) {
5557
}
@@ -219,6 +221,8 @@ public function renderPage(IShare $share, string $token, string $path): Template
219221
Util::addHeader('meta', ['property' => 'og:type', 'content' => 'object']);
220222
Util::addHeader('meta', ['property' => 'og:image', 'content' => $ogPreview]);
221223

224+
$this->initialState->provideInitialState('templates', $this->templateManager->listCreators());
225+
222226
$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
223227

224228
$csp = new ContentSecurityPolicy();

apps/files_sharing/tests/Controller/ShareControllerTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use OCP\Files\IRootFolder;
3232
use OCP\Files\NotFoundException;
3333
use OCP\Files\Storage;
34+
use OCP\Files\Template\ITemplateManager;
3435
use OCP\IConfig;
3536
use OCP\IL10N;
3637
use OCP\IPreview;
@@ -72,6 +73,7 @@ class ShareControllerTest extends \Test\TestCase {
7273
private $shareManager;
7374
/** @var IUserManager|MockObject */
7475
private $userManager;
76+
private ITemplateManager&MockObject $templateManager;
7577
/** @var FederatedShareProvider|MockObject */
7678
private $federatedShareProvider;
7779
/** @var IAccountManager|MockObject */
@@ -123,6 +125,7 @@ protected function setUp(): void {
123125
$this->defaults,
124126
$this->config,
125127
$this->createMock(IRequest::class),
128+
$this->templateManager,
126129
$this->createMock(IInitialState::class)
127130
)
128131
);
@@ -356,6 +359,7 @@ public function testShowShare() {
356359
'showgridview' => false,
357360
'label' => '',
358361
'filename' => $filename,
362+
'templates' => [],
359363
];
360364

361365
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();

0 commit comments

Comments
 (0)