]> source.dussan.org Git - nextcloud-server.git/commitdiff
feat(files_sharing): add public name prompt for files requests
authorskjnldsv <skjnldsv@protonmail.com>
Wed, 17 Jul 2024 14:48:47 +0000 (16:48 +0200)
committerskjnldsv <skjnldsv@protonmail.com>
Thu, 18 Jul 2024 18:15:39 +0000 (20:15 +0200)
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
16 files changed:
apps/dav/appinfo/v1/publicwebdav.php
apps/dav/appinfo/v2/publicremote.php
apps/dav/lib/Files/Sharing/FilesDropPlugin.php
apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
apps/files_sharing/composer/composer/autoload_classmap.php
apps/files_sharing/composer/composer/autoload_static.php
apps/files_sharing/js/files_drop.js
apps/files_sharing/lib/AppInfo/Application.php
apps/files_sharing/lib/DefaultPublicShareTemplateProvider.php
apps/files_sharing/lib/Listener/LoadPublicFileRequestAuthListener.php [new file with mode: 0644]
apps/files_sharing/src/components/NewFileRequestDialog.vue
apps/files_sharing/src/public-file-request.ts [new file with mode: 0644]
apps/files_sharing/src/views/PublicAuthPrompt.vue [new file with mode: 0644]
apps/files_sharing/templates/public.php
apps/files_sharing/tests/Controller/ShareControllerTest.php
webpack.modules.js

index 5ef383e1dd5d78bf7e252df473270eda3cf46f27..38753374150045ef94a2dea48c5cf5c0ebc8b2f0 100644 (file)
@@ -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;
 });
index bdc4169dd4ebec9622990b87402434a518cbd0c8..44cf4214505da5f1263c4959dea2e0a18ce9da2b 100644 (file)
@@ -116,6 +116,7 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, funct
 
        $view = new View($node->getPath());
        $filesDropPlugin->setView($view);
+       $filesDropPlugin->setShare($share);
 
        return $view;
 });
index c4d1957c67e4c7acde95d7d888e2a8648c9c069b..b364c4ebbfc10e732f093ba9eb35f09c33a86ed7 100644 (file)
@@ -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);
        }
+
 }
index 9a077e35076aaf22606483dbd4d0e86c32d1836b..7264119f8c6882da11bdd57063b7136447bc72b8 100644 (file)
@@ -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');
index e1abddb3a6450adf5e899ac25bc6c0d016b0f394..b7a931a622895434b14a3b26d1a0a2cec87d8f3e 100644 (file)
@@ -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',
index 5d2fb3bac2a478db3bedc89a519e6540004ecf9c..70dc7be7cdf693b3cc036a30a1bc6403d593b597 100644 (file)
@@ -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',
index fd9b796ee2c043fd9181275cdeb0bf16a5eb5923..450af078af269916ce86b08631515f59c7ec4443 100644 (file)
@@ -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 🤷‍♀️
                                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');
 
index 82a5981febf8542bc3f60bda93ad9add7263ece5..98c2d280856e0b334bc6b354c79bbb55a84dea5f 100644 (file)
@@ -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 {
index e125100eb686454b9b6a24925a839f5e92352339..477bc9f82ce7d655546dc2129a884e861295307b 100644 (file)
@@ -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 (file)
index 0000000..f1e054c
--- /dev/null
@@ -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');
+               }
+       }
+}
index 398fd976f02dd513c02b5219a32b046c3f5df330..4c476af9bc894199641bb26b0b5e1c4166063707 100644 (file)
                                @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 (file)
index 0000000..763c4f6
--- /dev/null
@@ -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 (file)
index 0000000..a929aff
--- /dev/null
@@ -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>
index 109eaf2e9da154615cb7e3417d0dc03c2bf37aa3..7620d309ff605ea80ce2ce082d902ad09a37c319 100644 (file)
@@ -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) { ?>
index 493ac10a24bea63e48e55ade275f104039eb33a8..79b90d8a1568206a850fe9f5becbdaa5239f70af 100644 (file)
@@ -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();
index d13ad284bab3ee33e7b4d7eb3cd1f161dd4dd822..887d8dc75a0895225e82e3aa136d1affbf15aa4f 100644 (file)
@@ -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'),