aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/dav/appinfo/v1/publicwebdav.php1
-rw-r--r--apps/dav/appinfo/v2/publicremote.php1
-rw-r--r--apps/dav/lib/Files/Sharing/FilesDropPlugin.php53
-rw-r--r--apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php15
-rw-r--r--apps/files_sharing/composer/composer/autoload_classmap.php1
-rw-r--r--apps/files_sharing/composer/composer/autoload_static.php1
-rw-r--r--apps/files_sharing/js/files_drop.js6
-rw-r--r--apps/files_sharing/lib/AppInfo/Application.php7
-rw-r--r--apps/files_sharing/lib/DefaultPublicShareTemplateProvider.php49
-rw-r--r--apps/files_sharing/lib/Listener/LoadPublicFileRequestAuthListener.php59
-rw-r--r--apps/files_sharing/src/components/NewFileRequestDialog.vue14
-rw-r--r--apps/files_sharing/src/public-file-request.ts23
-rw-r--r--apps/files_sharing/src/views/PublicAuthPrompt.vue136
-rw-r--r--apps/files_sharing/templates/public.php12
-rw-r--r--apps/files_sharing/tests/Controller/ShareControllerTest.php14
-rw-r--r--webpack.modules.js1
16 files changed, 332 insertions, 61 deletions
diff --git a/apps/dav/appinfo/v1/publicwebdav.php b/apps/dav/appinfo/v1/publicwebdav.php
index 5ef383e1dd5..38753374150 100644
--- a/apps/dav/appinfo/v1/publicwebdav.php
+++ b/apps/dav/appinfo/v1/publicwebdav.php
@@ -87,6 +87,7 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, funct
$view = new \OC\Files\View($node->getPath());
$filesDropPlugin->setView($view);
+ $filesDropPlugin->setShare($share);
return $view;
});
diff --git a/apps/dav/appinfo/v2/publicremote.php b/apps/dav/appinfo/v2/publicremote.php
index bdc4169dd4e..44cf4214505 100644
--- a/apps/dav/appinfo/v2/publicremote.php
+++ b/apps/dav/appinfo/v2/publicremote.php
@@ -116,6 +116,7 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, funct
$view = new View($node->getPath());
$filesDropPlugin->setView($view);
+ $filesDropPlugin->setShare($share);
return $view;
});
diff --git a/apps/dav/lib/Files/Sharing/FilesDropPlugin.php b/apps/dav/lib/Files/Sharing/FilesDropPlugin.php
index c4d1957c67e..b364c4ebbfc 100644
--- a/apps/dav/lib/Files/Sharing/FilesDropPlugin.php
+++ b/apps/dav/lib/Files/Sharing/FilesDropPlugin.php
@@ -6,6 +6,7 @@
namespace OCA\DAV\Files\Sharing;
use OC\Files\View;
+use OCP\Share\IShare;
use Sabre\DAV\Exception\MethodNotAllowed;
use Sabre\DAV\ServerPlugin;
use Sabre\HTTP\RequestInterface;
@@ -16,17 +17,19 @@ use Sabre\HTTP\ResponseInterface;
*/
class FilesDropPlugin extends ServerPlugin {
- /** @var View */
- private $view;
+ private ?View $view = null;
+ private ?IShare $share = null;
+ private bool $enabled = false;
- /** @var bool */
- private $enabled = false;
-
- public function setView(View $view) {
+ public function setView(View $view): void {
$this->view = $view;
}
- public function enable() {
+ public function setShare(IShare $share): void {
+ $this->share = $share;
+ }
+
+ public function enable(): void {
$this->enabled = true;
}
@@ -39,25 +42,53 @@ class FilesDropPlugin extends ServerPlugin {
* @return void
* @throws MethodNotAllowed
*/
- public function initialize(\Sabre\DAV\Server $server) {
+ public function initialize(\Sabre\DAV\Server $server): void {
$server->on('beforeMethod:*', [$this, 'beforeMethod'], 999);
$this->enabled = false;
}
- public function beforeMethod(RequestInterface $request, ResponseInterface $response) {
- if (!$this->enabled) {
+ public function beforeMethod(RequestInterface $request, ResponseInterface $response): void {
+ if (!$this->enabled || $this->share === null || $this->view === null) {
return;
}
- if ($request->getMethod() !== 'PUT' && $request->getMethod() !== 'MKCOL') {
+ // Only allow file drop
+ if ($request->getMethod() !== 'PUT') {
throw new MethodNotAllowed('Only PUT is allowed on files drop');
}
+ // Always upload at the root level
$path = explode('/', $request->getPath());
$path = array_pop($path);
+ // Extract the attributes for the file request
+ $attributes = $this->share->getAttributes();
+ if ($attributes === null) {
+ return;
+ }
+
+ // Prepare file request
+ $nickName = $request->getHeader('X-NC-Nickname');
+ $isFileRequest = $attributes->getAttribute('fileRequest', 'enabled') === true;
+
+ // We need a valid nickname for file requests
+ if ($isFileRequest && ($nickName == null || trim($nickName) === '')) {
+ throw new MethodNotAllowed('Nickname is required for file requests');
+ }
+
+ // If this is a file request we need to create a folder for the user
+ if ($isFileRequest) {
+ // Check if the folder already exists
+ if (!($this->view->file_exists($nickName) === true)) {
+ $this->view->mkdir($nickName);
+ }
+ // Put all files in the subfolder
+ $path = $nickName . '/' . $path;
+ }
+
$newName = \OC_Helper::buildNotExistingFileNameForView('/', $path, $this->view);
$url = $request->getBaseUrl() . $newName;
$request->setUrl($url);
}
+
}
diff --git a/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php b/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
index 9a077e35076..7264119f8c6 100644
--- a/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
+++ b/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
@@ -7,6 +7,8 @@ namespace OCA\DAV\Tests\Files\Sharing;
use OC\Files\View;
use OCA\DAV\Files\Sharing\FilesDropPlugin;
+use OCP\Share\IAttributes;
+use OCP\Share\IShare;
use Sabre\DAV\Exception\MethodNotAllowed;
use Sabre\DAV\Server;
use Sabre\HTTP\RequestInterface;
@@ -18,6 +20,9 @@ class FilesDropPluginTest extends TestCase {
/** @var View|\PHPUnit\Framework\MockObject\MockObject */
private $view;
+ /** @var IShare|\PHPUnit\Framework\MockObject\MockObject */
+ private $share;
+
/** @var Server|\PHPUnit\Framework\MockObject\MockObject */
private $server;
@@ -34,6 +39,7 @@ class FilesDropPluginTest extends TestCase {
parent::setUp();
$this->view = $this->createMock(View::class);
+ $this->share = $this->createMock(IShare::class);
$this->server = $this->createMock(Server::class);
$this->plugin = new FilesDropPlugin();
@@ -42,6 +48,11 @@ class FilesDropPluginTest extends TestCase {
$this->response->expects($this->never())
->method($this->anything());
+
+ $attributes = $this->createMock(IAttributes::class);
+ $this->share->expects($this->any())
+ ->method('getAttributes')
+ ->willReturn($attributes);
}
public function testInitialize(): void {
@@ -69,6 +80,7 @@ class FilesDropPluginTest extends TestCase {
public function testValid(): void {
$this->plugin->enable();
$this->plugin->setView($this->view);
+ $this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('PUT');
@@ -93,6 +105,7 @@ class FilesDropPluginTest extends TestCase {
public function testFileAlreadyExistsValid(): void {
$this->plugin->enable();
$this->plugin->setView($this->view);
+ $this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('PUT');
@@ -122,6 +135,7 @@ class FilesDropPluginTest extends TestCase {
public function testNoMKCOL(): void {
$this->plugin->enable();
$this->plugin->setView($this->view);
+ $this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('MKCOL');
@@ -134,6 +148,7 @@ class FilesDropPluginTest extends TestCase {
public function testNoSubdirPut(): void {
$this->plugin->enable();
$this->plugin->setView($this->view);
+ $this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('PUT');
diff --git a/apps/files_sharing/composer/composer/autoload_classmap.php b/apps/files_sharing/composer/composer/autoload_classmap.php
index e1abddb3a64..b7a931a6228 100644
--- a/apps/files_sharing/composer/composer/autoload_classmap.php
+++ b/apps/files_sharing/composer/composer/autoload_classmap.php
@@ -59,6 +59,7 @@ return array(
'OCA\\Files_Sharing\\Listener\\BeforeDirectFileDownloadListener' => $baseDir . '/../lib/Listener/BeforeDirectFileDownloadListener.php',
'OCA\\Files_Sharing\\Listener\\BeforeZipCreatedListener' => $baseDir . '/../lib/Listener/BeforeZipCreatedListener.php',
'OCA\\Files_Sharing\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php',
+ 'OCA\\Files_Sharing\\Listener\\LoadPublicFileRequestAuthListener' => $baseDir . '/../lib/Listener/LoadPublicFileRequestAuthListener.php',
'OCA\\Files_Sharing\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php',
'OCA\\Files_Sharing\\Listener\\ShareInteractionListener' => $baseDir . '/../lib/Listener/ShareInteractionListener.php',
'OCA\\Files_Sharing\\Listener\\UserAddedToGroupListener' => $baseDir . '/../lib/Listener/UserAddedToGroupListener.php',
diff --git a/apps/files_sharing/composer/composer/autoload_static.php b/apps/files_sharing/composer/composer/autoload_static.php
index 5d2fb3bac2a..70dc7be7cdf 100644
--- a/apps/files_sharing/composer/composer/autoload_static.php
+++ b/apps/files_sharing/composer/composer/autoload_static.php
@@ -74,6 +74,7 @@ class ComposerStaticInitFiles_Sharing
'OCA\\Files_Sharing\\Listener\\BeforeDirectFileDownloadListener' => __DIR__ . '/..' . '/../lib/Listener/BeforeDirectFileDownloadListener.php',
'OCA\\Files_Sharing\\Listener\\BeforeZipCreatedListener' => __DIR__ . '/..' . '/../lib/Listener/BeforeZipCreatedListener.php',
'OCA\\Files_Sharing\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php',
+ 'OCA\\Files_Sharing\\Listener\\LoadPublicFileRequestAuthListener' => __DIR__ . '/..' . '/../lib/Listener/LoadPublicFileRequestAuthListener.php',
'OCA\\Files_Sharing\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php',
'OCA\\Files_Sharing\\Listener\\ShareInteractionListener' => __DIR__ . '/..' . '/../lib/Listener/ShareInteractionListener.php',
'OCA\\Files_Sharing\\Listener\\UserAddedToGroupListener' => __DIR__ . '/..' . '/../lib/Listener/UserAddedToGroupListener.php',
diff --git a/apps/files_sharing/js/files_drop.js b/apps/files_sharing/js/files_drop.js
index fd9b796ee2c..450af078af2 100644
--- a/apps/files_sharing/js/files_drop.js
+++ b/apps/files_sharing/js/files_drop.js
@@ -22,7 +22,7 @@
// note: password not be required, the endpoint
// will recognize previous validation from the session
root: OC.getRootPath() + '/public.php/dav/files/' + $('#sharingToken').val() + '/',
- useHTTPS: OC.getProtocol() === 'https'
+ useHTTPS: OC.getProtocol() === 'https',
});
// We only process one file at a time 🤷‍♀️
@@ -47,6 +47,10 @@
data.headers = {};
}
+ if (localStorage.getItem('nick') !== null) {
+ data.headers['X-NC-Nickname'] = localStorage.getItem('nick')
+ }
+
$('#drop-upload-done-indicator').addClass('hidden');
$('#drop-upload-progress-indicator').removeClass('hidden');
diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php
index 82a5981febf..98c2d280856 100644
--- a/apps/files_sharing/lib/AppInfo/Application.php
+++ b/apps/files_sharing/lib/AppInfo/Application.php
@@ -18,6 +18,7 @@ use OCA\Files_Sharing\Helper;
use OCA\Files_Sharing\Listener\BeforeDirectFileDownloadListener;
use OCA\Files_Sharing\Listener\BeforeZipCreatedListener;
use OCA\Files_Sharing\Listener\LoadAdditionalListener;
+use OCA\Files_Sharing\Listener\LoadPublicFileRequestAuthListener;
use OCA\Files_Sharing\Listener\LoadSidebarListener;
use OCA\Files_Sharing\Listener\ShareInteractionListener;
use OCA\Files_Sharing\Listener\UserAddedToGroupListener;
@@ -34,6 +35,7 @@ use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
+use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent as ResourcesLoadAdditionalScriptsEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudIdManager;
@@ -85,7 +87,7 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(GroupChangedEvent::class, GroupDisplayNameCache::class);
$context->registerEventListener(GroupDeletedEvent::class, GroupDisplayNameCache::class);
- // sidebar and files scripts
+ // Sidebar and files scripts
$context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class);
$context->registerEventListener(LoadSidebar::class, LoadSidebarListener::class);
$context->registerEventListener(ShareCreatedEvent::class, ShareInteractionListener::class);
@@ -95,6 +97,9 @@ class Application extends App implements IBootstrap {
// Handle download events for view only checks
$context->registerEventListener(BeforeZipCreatedEvent::class, BeforeZipCreatedListener::class);
$context->registerEventListener(BeforeDirectFileDownloadEvent::class, BeforeDirectFileDownloadListener::class);
+
+ // File request auth
+ $context->registerEventListener(BeforeTemplateRenderedEvent::class, LoadPublicFileRequestAuthListener::class);
}
public function boot(IBootContext $context): void {
diff --git a/apps/files_sharing/lib/DefaultPublicShareTemplateProvider.php b/apps/files_sharing/lib/DefaultPublicShareTemplateProvider.php
index e125100eb68..477bc9f82ce 100644
--- a/apps/files_sharing/lib/DefaultPublicShareTemplateProvider.php
+++ b/apps/files_sharing/lib/DefaultPublicShareTemplateProvider.php
@@ -19,6 +19,7 @@ use OCP\AppFramework\Http\Template\LinkMenuAction;
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
use OCP\AppFramework\Http\Template\SimpleMenuAction;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\Services\IInitialState;
use OCP\Constants;
use OCP\Defaults;
use OCP\EventDispatcher\IEventDispatcher;
@@ -37,39 +38,20 @@ use OCP\Template;
use OCP\Util;
class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider {
- private IUserManager $userManager;
- private IAccountManager $accountManager;
- private IPreview $previewManager;
- protected FederatedShareProvider $federatedShareProvider;
- private IURLGenerator $urlGenerator;
- private IEventDispatcher $eventDispatcher;
- private IL10N $l10n;
- private Defaults $defaults;
- private IConfig $config;
- private IRequest $request;
public function __construct(
- IUserManager $userManager,
- IAccountManager $accountManager,
- IPreview $previewManager,
- FederatedShareProvider $federatedShareProvider,
- IUrlGenerator $urlGenerator,
- IEventDispatcher $eventDispatcher,
- IL10N $l10n,
- Defaults $defaults,
- IConfig $config,
- IRequest $request
+ private IUserManager $userManager,
+ private IAccountManager $accountManager,
+ private IPreview $previewManager,
+ protected FederatedShareProvider $federatedShareProvider,
+ private IUrlGenerator $urlGenerator,
+ private IEventDispatcher $eventDispatcher,
+ private IL10N $l10n,
+ private Defaults $defaults,
+ private IConfig $config,
+ private IRequest $request,
+ private IInitialState $initialState,
) {
- $this->userManager = $userManager;
- $this->accountManager = $accountManager;
- $this->previewManager = $previewManager;
- $this->federatedShareProvider = $federatedShareProvider;
- $this->urlGenerator = $urlGenerator;
- $this->eventDispatcher = $eventDispatcher;
- $this->l10n = $l10n;
- $this->defaults = $defaults;
- $this->config = $config;
- $this->request = $request;
}
public function shouldRespond(IShare $share): bool {
@@ -91,9 +73,16 @@ class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider
if ($ownerName->getScope() === IAccountManager::SCOPE_PUBLISHED) {
$shareTmpl['owner'] = $owner->getUID();
$shareTmpl['shareOwner'] = $owner->getDisplayName();
+ $this->initialState->provideInitialState('owner', $shareTmpl['owner']);
+ $this->initialState->provideInitialState('ownerDisplayName', $shareTmpl['shareOwner']);
}
}
+ // Provide initial state
+ $this->initialState->provideInitialState('label', $share->getLabel());
+ $this->initialState->provideInitialState('note', $share->getNote());
+ $this->initialState->provideInitialState('filename', $shareNode->getName());
+
$shareTmpl['filename'] = $shareNode->getName();
$shareTmpl['directory_path'] = $share->getTarget();
$shareTmpl['label'] = $share->getLabel();
diff --git a/apps/files_sharing/lib/Listener/LoadPublicFileRequestAuthListener.php b/apps/files_sharing/lib/Listener/LoadPublicFileRequestAuthListener.php
new file mode 100644
index 00000000000..f1e054c7ee5
--- /dev/null
+++ b/apps/files_sharing/lib/Listener/LoadPublicFileRequestAuthListener.php
@@ -0,0 +1,59 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_Sharing\Listener;
+
+use OCA\Files_Sharing\AppInfo\Application;
+use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Share\IManager;
+use OCP\Util;
+
+/** @template-implements IEventListener<BeforeTemplateRenderedEvent> */
+class LoadPublicFileRequestAuthListener implements IEventListener {
+ public function __construct(
+ private IManager $shareManager,
+ ) {
+ }
+
+ public function handle(Event $event): void {
+ if (!$event instanceof BeforeTemplateRenderedEvent) {
+ return;
+ }
+
+ // Make sure we are on a public page rendering
+ if ($event->getResponse()->getRenderAs() !== TemplateResponse::RENDER_AS_PUBLIC) {
+ return;
+ }
+
+ $token = $event->getResponse()->getParams()['sharingToken'] ?? null;
+ if ($token === null || $token === '') {
+ return;
+ }
+
+ // Check if the share is a file request
+ $isFileRequest = false;
+ try {
+ $share = $this->shareManager->getShareByToken($token);
+ $attributes = $share->getAttributes();
+ if ($attributes === null) {
+ return;
+ }
+
+ $isFileRequest = $attributes->getAttribute('fileRequest', 'enabled') === true;
+ } catch (\Exception $e) {
+ // Ignore, this is not a file request or the share does not exist
+ }
+
+ if ($isFileRequest) {
+ // Add the script to the public page
+ Util::addScript(Application::APP_ID, 'public-file-request');
+ }
+ }
+}
diff --git a/apps/files_sharing/src/components/NewFileRequestDialog.vue b/apps/files_sharing/src/components/NewFileRequestDialog.vue
index 398fd976f02..4c476af9bc8 100644
--- a/apps/files_sharing/src/components/NewFileRequestDialog.vue
+++ b/apps/files_sharing/src/components/NewFileRequestDialog.vue
@@ -107,7 +107,7 @@
@click="onFinish">
<template #icon>
<NcLoadingIcon v-if="loading" />
- <IconCheck v-else-if="success" :size="20" />
+ <IconCheck v-else :size="20" />
</template>
{{ finishButtonLabel }}
</NcButton>
@@ -193,7 +193,6 @@ export default defineComponent({
return {
currentStep: STEP.FIRST,
loading: false,
- success: false,
destination: this.context.path || '/',
label: '',
@@ -264,11 +263,7 @@ export default defineComponent({
showSuccess(t('files_sharing', 'File request created'))
}
- // Show success then close
- this.success = true
- setTimeout(() => {
- this.$emit('close')
- }, 3000)
+ this.$emit('close')
},
async createShare() {
@@ -343,6 +338,11 @@ export default defineComponent({
value: this.emails,
key: 'emails',
scope: 'shareWith',
+ },
+ {
+ value: true,
+ key: 'enabled',
+ scope: 'fileRequest',
}]),
})
diff --git a/apps/files_sharing/src/public-file-request.ts b/apps/files_sharing/src/public-file-request.ts
new file mode 100644
index 00000000000..763c4f60624
--- /dev/null
+++ b/apps/files_sharing/src/public-file-request.ts
@@ -0,0 +1,23 @@
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { spawnDialog } from '@nextcloud/dialogs'
+import { defineAsyncComponent } from 'vue'
+import logger from './services/logger'
+
+const nick = localStorage.getItem('nick')
+const publicAuthPromptShown = localStorage.getItem('publicAuthPromptShown')
+
+// If we don't have a nickname or the public auth prompt hasn't been shown yet, show it
+// We still show the prompt if the user has a nickname to double check
+if (!nick || !publicAuthPromptShown) {
+ spawnDialog(
+ defineAsyncComponent(() => import('./views/PublicAuthPrompt.vue')),
+ {},
+ () => localStorage.setItem('publicAuthPromptShown', 'true'),
+ )
+} else {
+ logger.debug(`Public auth prompt already shown. Current nickname is '${nick}'`)
+}
diff --git a/apps/files_sharing/src/views/PublicAuthPrompt.vue b/apps/files_sharing/src/views/PublicAuthPrompt.vue
new file mode 100644
index 00000000000..a929afffefb
--- /dev/null
+++ b/apps/files_sharing/src/views/PublicAuthPrompt.vue
@@ -0,0 +1,136 @@
+<!--
+ - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+
+<template>
+ <NcDialog class="public-auth-prompt"
+ dialog-classes="public-auth-prompt__dialog"
+ :can-close="false"
+ :name="dialogName">
+ <h3 v-if="owner" class="public-auth-prompt__subtitle">
+ {{ t('files_sharing', '{ownerDisplayName} shared a folder with you.', { ownerDisplayName }) }}
+ </h3>
+
+ <!-- Header -->
+ <NcNoteCard type="info" class="public-auth-prompt__header">
+ <p id="public-auth-prompt-dialog-description" class="public-auth-prompt__description">
+ {{ t('files_sharing', 'To upload files, you need to provide your name first.') }}
+ </p>
+ </NcNoteCard>
+
+ <!-- Form -->
+ <form ref="form"
+ aria-describedby="public-auth-prompt-dialog-description"
+ class="public-auth-prompt__form"
+ @submit.prevent.stop="">
+ <NcTextField ref="input"
+ class="public-auth-prompt__input"
+ :label="t('files_sharing', 'Enter your name')"
+ name="name"
+ :required="true"
+ :minlength="2"
+ :value.sync="name" />
+ </form>
+
+ <!-- Submit -->
+ <template #actions>
+ <NcButton ref="submit"
+ :disabled="name.trim() === ''"
+ @click="onSubmit">
+ {{ t('files_sharing', 'Submit name') }}
+ </NcButton>
+ </template>
+ </NcDialog>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue'
+import { t } from '@nextcloud/l10n'
+
+import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
+import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
+import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
+import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
+import { loadState } from '@nextcloud/initial-state'
+
+export default defineComponent({
+ name: 'PublicAuthPrompt',
+
+ components: {
+ NcButton,
+ NcDialog,
+ NcNoteCard,
+ NcTextField,
+ },
+
+ setup() {
+ return {
+ t,
+
+ owner: loadState('files_sharing', 'owner', ''),
+ ownerDisplayName: loadState('files_sharing', 'ownerDisplayName', ''),
+ label: loadState('files_sharing', 'label', ''),
+ note: loadState('files_sharing', 'note', ''),
+ filename: loadState('files_sharing', 'filename', ''),
+ }
+ },
+
+ data() {
+ return {
+ name: '',
+ }
+ },
+
+ computed: {
+ dialogName() {
+ return this.t('files_sharing', 'Upload files to {folder}', { folder: this.label || this.filename })
+ },
+ },
+
+ beforeMount() {
+ // Pre-load the name from local storage if already set by another app
+ // like Talk, Colabora or Text...
+ const talkNick = localStorage.getItem('nick')
+ if (talkNick) {
+ this.name = talkNick
+ }
+ },
+
+ methods: {
+ onSubmit() {
+ const form = this.$refs.form as HTMLFormElement
+ if (!form.checkValidity()) {
+ form.reportValidity()
+ return
+ }
+
+ if (this.name.trim() === '') {
+ return
+ }
+
+ localStorage.setItem('nick', this.name)
+ this.$emit('close')
+ },
+ },
+})
+</script>
+<style lang="scss">
+.public-auth-prompt {
+ &__subtitle {
+ // Smaller than dialog title
+ font-size: 16px;
+ margin-block: 12px;
+ }
+
+ &__header {
+ // Fix extra margin generating an unwanted gap
+ margin-block: 12px;
+ }
+
+ &__form {
+ // Double the margin of the header
+ margin-block: 24px;
+ }
+}
+</style>
diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php
index 109eaf2e9da..7620d309ff6 100644
--- a/apps/files_sharing/templates/public.php
+++ b/apps/files_sharing/templates/public.php
@@ -27,6 +27,7 @@
<input type="hidden" name="mimetypeIcon" value="<?php p(\OC::$server->getMimeTypeDetector()->mimeTypeIcon($_['mimetype'])); ?>" id="mimetypeIcon">
<input type="hidden" name="hideDownload" value="<?php p($_['hideDownload'] ? 'true' : 'false'); ?>" id="hideDownload">
<input type="hidden" id="disclaimerText" value="<?php p($_['disclaimer']) ?>">
+
<?php
$upload_max_filesize = OC::$server->get(\bantu\IniGetWrapper\IniGetWrapper::class)->getBytes('upload_max_filesize');
$post_max_size = OC::$server->get(\bantu\IniGetWrapper\IniGetWrapper::class)->getBytes('post_max_size');
@@ -102,14 +103,11 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size);
class="emptycontent <?php if (!empty($_['note'])) { ?>has-note<?php } ?>">
<?php if ($_['shareOwner']) { ?>
<div id="displayavatar"><div class="avatardiv"></div></div>
- <h2><?php p($l->t('Upload files to %s', [$_['shareOwner']])) ?></h2>
- <p><span class="icon-folder"></span> <?php p($_['filename']) ?></p>
- <?php } else if ($_['label']) { ?>
- <div id="displayavatar"><span class="icon-folder"></span></div>
- <h2><?php p($l->t('Upload files to %s', [$_['label']])) ?></h2>
- <?php } else{ ?>
+ <h2><?php p($l->t('Upload files to %s', [$_['label'] ?: $_['filename']])) ?></h2>
+ <p><?php p($l->t('%s shared a folder with you.', [$_['shareOwner']])) ?></p>
+ <?php } else { ?>
<div id="displayavatar"><span class="icon-folder"></span></div>
- <h2><?php p($l->t('Upload files to %s', [$_['filename']])) ?></h2>
+ <h2><?php p($l->t('Upload files to %s', [$_['label'] ?: $_['filename']])) ?></h2>
<?php } ?>
<?php if (empty($_['note']) === false) { ?>
diff --git a/apps/files_sharing/tests/Controller/ShareControllerTest.php b/apps/files_sharing/tests/Controller/ShareControllerTest.php
index 493ac10a24b..79b90d8a156 100644
--- a/apps/files_sharing/tests/Controller/ShareControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareControllerTest.php
@@ -22,6 +22,7 @@ use OCP\AppFramework\Http\Template\ExternalShareMenuAction;
use OCP\AppFramework\Http\Template\LinkMenuAction;
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
use OCP\AppFramework\Http\Template\SimpleMenuAction;
+use OCP\AppFramework\Services\IInitialState;
use OCP\Constants;
use OCP\Defaults;
use OCP\EventDispatcher\IEventDispatcher;
@@ -121,6 +122,7 @@ class ShareControllerTest extends \Test\TestCase {
$this->defaults,
$this->config,
$this->createMock(IRequest::class),
+ $this->createMock(IInitialState::class)
)
);
@@ -350,7 +352,8 @@ class ShareControllerTest extends \Test\TestCase {
'previewURL' => 'downloadURL',
'note' => $note,
'hideDownload' => false,
- 'showgridview' => false
+ 'showgridview' => false,
+ 'label' => ''
];
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
@@ -511,7 +514,8 @@ class ShareControllerTest extends \Test\TestCase {
'previewURL' => 'downloadURL',
'note' => $note,
'hideDownload' => false,
- 'showgridview' => false
+ 'showgridview' => false,
+ 'label' => ''
];
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
@@ -672,7 +676,8 @@ class ShareControllerTest extends \Test\TestCase {
'previewURL' => 'downloadURL',
'note' => $note,
'hideDownload' => true,
- 'showgridview' => false
+ 'showgridview' => false,
+ 'label' => ''
];
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
@@ -798,7 +803,8 @@ class ShareControllerTest extends \Test\TestCase {
'previewURL' => '',
'note' => '',
'hideDownload' => false,
- 'showgridview' => false
+ 'showgridview' => false,
+ 'label' => ''
];
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
diff --git a/webpack.modules.js b/webpack.modules.js
index d13ad284bab..887d8dc75a0 100644
--- a/webpack.modules.js
+++ b/webpack.modules.js
@@ -54,6 +54,7 @@ module.exports = {
init: path.join(__dirname, 'apps/files_sharing/src', 'init.ts'),
main: path.join(__dirname, 'apps/files_sharing/src', 'main.ts'),
'personal-settings': path.join(__dirname, 'apps/files_sharing/src', 'personal-settings.js'),
+ 'public-file-request': path.join(__dirname, 'apps/files_sharing/src', 'public-file-request.ts'),
},
files_trashbin: {
init: path.join(__dirname, 'apps/files_trashbin/src', 'files-init.ts'),