Completed
Push — master ( 27149b...5734ff )
by
unknown
33:48 queued 16s
created
apps/files_sharing/lib/DefaultPublicShareTemplateProvider.php 1 patch
Indentation   +196 added lines, -196 removed lines patch added patch discarded remove patch
@@ -38,225 +38,225 @@
 block discarded – undo
38 38
 
39 39
 class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider {
40 40
 
41
-	public function __construct(
42
-		private IUserManager $userManager,
43
-		private IAccountManager $accountManager,
44
-		private IPreview $previewManager,
45
-		protected FederatedShareProvider $federatedShareProvider,
46
-		private IUrlGenerator $urlGenerator,
47
-		private IEventDispatcher $eventDispatcher,
48
-		private IL10N $l10n,
49
-		private Defaults $defaults,
50
-		private IConfig $config,
51
-		private IRequest $request,
52
-		private IInitialState $initialState,
53
-		private IAppConfig $appConfig,
54
-	) {
55
-	}
41
+    public function __construct(
42
+        private IUserManager $userManager,
43
+        private IAccountManager $accountManager,
44
+        private IPreview $previewManager,
45
+        protected FederatedShareProvider $federatedShareProvider,
46
+        private IUrlGenerator $urlGenerator,
47
+        private IEventDispatcher $eventDispatcher,
48
+        private IL10N $l10n,
49
+        private Defaults $defaults,
50
+        private IConfig $config,
51
+        private IRequest $request,
52
+        private IInitialState $initialState,
53
+        private IAppConfig $appConfig,
54
+    ) {
55
+    }
56 56
 
57
-	public function shouldRespond(IShare $share): bool {
58
-		return true;
59
-	}
57
+    public function shouldRespond(IShare $share): bool {
58
+        return true;
59
+    }
60 60
 
61
-	public function renderPage(IShare $share, string $token, string $path): TemplateResponse {
62
-		$shareNode = $share->getNode();
63
-		$ownerName = '';
64
-		$ownerId = '';
61
+    public function renderPage(IShare $share, string $token, string $path): TemplateResponse {
62
+        $shareNode = $share->getNode();
63
+        $ownerName = '';
64
+        $ownerId = '';
65 65
 
66
-		// Only make the share owner public if they allowed to show their name
67
-		$owner = $this->userManager->get($share->getShareOwner());
68
-		if ($owner instanceof IUser) {
69
-			$ownerAccount = $this->accountManager->getAccount($owner);
66
+        // Only make the share owner public if they allowed to show their name
67
+        $owner = $this->userManager->get($share->getShareOwner());
68
+        if ($owner instanceof IUser) {
69
+            $ownerAccount = $this->accountManager->getAccount($owner);
70 70
 
71
-			$ownerNameProperty = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
72
-			if ($ownerNameProperty->getScope() === IAccountManager::SCOPE_PUBLISHED) {
73
-				$ownerId = $owner->getUID();
74
-				$ownerName = $owner->getDisplayName();
75
-				$this->initialState->provideInitialState('owner', $ownerId);
76
-				$this->initialState->provideInitialState('ownerDisplayName', $ownerName);
77
-			}
78
-		}
71
+            $ownerNameProperty = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
72
+            if ($ownerNameProperty->getScope() === IAccountManager::SCOPE_PUBLISHED) {
73
+                $ownerId = $owner->getUID();
74
+                $ownerName = $owner->getDisplayName();
75
+                $this->initialState->provideInitialState('owner', $ownerId);
76
+                $this->initialState->provideInitialState('ownerDisplayName', $ownerName);
77
+            }
78
+        }
79 79
 
80
-		$view = 'public-share';
81
-		if ($shareNode instanceof File) {
82
-			$view = 'public-file-share';
83
-			$this->initialState->provideInitialState('fileId', $shareNode->getId());
84
-		} elseif (($share->getPermissions() & Constants::PERMISSION_CREATE)
85
-			&& !($share->getPermissions() & Constants::PERMISSION_READ)
86
-		) {
87
-			// share is a folder with create but no read permissions -> file drop only
88
-			$view = 'public-file-drop';
89
-			// Only needed for file drops
90
-			$this->initialState->provideInitialState(
91
-				'disclaimer',
92
-				$this->appConfig->getValueString('core', 'shareapi_public_link_disclaimertext'),
93
-			);
94
-			// file drops do not request the root folder so we need to provide label and note if available
95
-			$this->initialState->provideInitialState('label', $share->getLabel());
96
-			$this->initialState->provideInitialState('note', $share->getNote());
97
-		}
98
-		// Set up initial state
99
-		$this->initialState->provideInitialState('isPublic', true);
100
-		$this->initialState->provideInitialState('sharingToken', $token);
101
-		$this->initialState->provideInitialState('sharePermissions', $share->getPermissions());
102
-		$this->initialState->provideInitialState('filename', $shareNode->getName());
103
-		$this->initialState->provideInitialState('view', $view);
80
+        $view = 'public-share';
81
+        if ($shareNode instanceof File) {
82
+            $view = 'public-file-share';
83
+            $this->initialState->provideInitialState('fileId', $shareNode->getId());
84
+        } elseif (($share->getPermissions() & Constants::PERMISSION_CREATE)
85
+            && !($share->getPermissions() & Constants::PERMISSION_READ)
86
+        ) {
87
+            // share is a folder with create but no read permissions -> file drop only
88
+            $view = 'public-file-drop';
89
+            // Only needed for file drops
90
+            $this->initialState->provideInitialState(
91
+                'disclaimer',
92
+                $this->appConfig->getValueString('core', 'shareapi_public_link_disclaimertext'),
93
+            );
94
+            // file drops do not request the root folder so we need to provide label and note if available
95
+            $this->initialState->provideInitialState('label', $share->getLabel());
96
+            $this->initialState->provideInitialState('note', $share->getNote());
97
+        }
98
+        // Set up initial state
99
+        $this->initialState->provideInitialState('isPublic', true);
100
+        $this->initialState->provideInitialState('sharingToken', $token);
101
+        $this->initialState->provideInitialState('sharePermissions', $share->getPermissions());
102
+        $this->initialState->provideInitialState('filename', $shareNode->getName());
103
+        $this->initialState->provideInitialState('view', $view);
104 104
 
105
-		// Load scripts and styles for UI
106
-		Util::addInitScript('files', 'init');
107
-		Util::addInitScript(Application::APP_ID, 'init');
108
-		Util::addInitScript(Application::APP_ID, 'init-public');
109
-		Util::addScript('files', 'main');
105
+        // Load scripts and styles for UI
106
+        Util::addInitScript('files', 'init');
107
+        Util::addInitScript(Application::APP_ID, 'init');
108
+        Util::addInitScript(Application::APP_ID, 'init-public');
109
+        Util::addScript('files', 'main');
110 110
 
111
-		// Add file-request script if needed
112
-		$attributes = $share->getAttributes();
113
-		$isFileRequest = $attributes?->getAttribute('fileRequest', 'enabled') === true;
114
-		if ($isFileRequest) {
115
-			Util::addScript(Application::APP_ID, 'public-file-request');
116
-		}
111
+        // Add file-request script if needed
112
+        $attributes = $share->getAttributes();
113
+        $isFileRequest = $attributes?->getAttribute('fileRequest', 'enabled') === true;
114
+        if ($isFileRequest) {
115
+            Util::addScript(Application::APP_ID, 'public-file-request');
116
+        }
117 117
 
118
-		// Load Viewer scripts
119
-		if (class_exists(LoadViewer::class)) {
120
-			$this->eventDispatcher->dispatchTyped(new LoadViewer());
121
-		}
118
+        // Load Viewer scripts
119
+        if (class_exists(LoadViewer::class)) {
120
+            $this->eventDispatcher->dispatchTyped(new LoadViewer());
121
+        }
122 122
 
123
-		// Allow external apps to register their scripts
124
-		$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
123
+        // Allow external apps to register their scripts
124
+        $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
125 125
 
126
-		$this->addMetaHeaders($share);
126
+        $this->addMetaHeaders($share);
127 127
 
128
-		// CSP to allow office
129
-		$csp = new ContentSecurityPolicy();
130
-		$csp->addAllowedFrameDomain('\'self\'');
128
+        // CSP to allow office
129
+        $csp = new ContentSecurityPolicy();
130
+        $csp->addAllowedFrameDomain('\'self\'');
131 131
 
132
-		$response = new PublicTemplateResponse(
133
-			'files',
134
-			'index',
135
-		);
136
-		$response->setContentSecurityPolicy($csp);
132
+        $response = new PublicTemplateResponse(
133
+            'files',
134
+            'index',
135
+        );
136
+        $response->setContentSecurityPolicy($csp);
137 137
 
138
-		// If the share has a label, use it as the title
139
-		if ($share->getLabel() !== '') {
140
-			$response->setHeaderTitle($share->getLabel());
141
-			$response->setParams(['pageTitle' => $share->getLabel()]);
142
-		} else {
143
-			$response->setHeaderTitle($shareNode->getName());
144
-			$response->setParams(['pageTitle' => $shareNode->getName()]);
145
-		}
138
+        // If the share has a label, use it as the title
139
+        if ($share->getLabel() !== '') {
140
+            $response->setHeaderTitle($share->getLabel());
141
+            $response->setParams(['pageTitle' => $share->getLabel()]);
142
+        } else {
143
+            $response->setHeaderTitle($shareNode->getName());
144
+            $response->setParams(['pageTitle' => $shareNode->getName()]);
145
+        }
146 146
 
147
-		if ($ownerName !== '') {
148
-			$response->setHeaderDetails($this->l10n->t('shared by %s', [$ownerName]));
149
-		}
147
+        if ($ownerName !== '') {
148
+            $response->setHeaderDetails($this->l10n->t('shared by %s', [$ownerName]));
149
+        }
150 150
 
151
-		// Create the header action menu
152
-		$headerActions = [];
153
-		if ($view !== 'public-file-drop' && !$share->getHideDownload()) {
154
-			// The download URL is used for the "download" header action as well as in some cases for the direct link
155
-			$downloadUrl = $this->urlGenerator->getAbsoluteURL('/public.php/dav/files/' . $token . '/?accept=zip');
151
+        // Create the header action menu
152
+        $headerActions = [];
153
+        if ($view !== 'public-file-drop' && !$share->getHideDownload()) {
154
+            // The download URL is used for the "download" header action as well as in some cases for the direct link
155
+            $downloadUrl = $this->urlGenerator->getAbsoluteURL('/public.php/dav/files/' . $token . '/?accept=zip');
156 156
 
157
-			// If not a file drop, then add the download header action
158
-			$headerActions[] = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $downloadUrl, 0, (string)$shareNode->getSize());
157
+            // If not a file drop, then add the download header action
158
+            $headerActions[] = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $downloadUrl, 0, (string)$shareNode->getSize());
159 159
 
160
-			// If remote sharing is enabled also add the remote share action to the menu
161
-			if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
162
-				$headerActions[] = new ExternalShareMenuAction(
163
-					// TRANSLATORS The placeholder refers to the software product name as in 'Add to your Nextcloud'
164
-					$this->l10n->t('Add to your %s', [$this->defaults->getProductName()]),
165
-					'icon-external',
166
-					$ownerId,
167
-					$ownerName,
168
-					$shareNode->getName(),
169
-				);
170
-			}
171
-		}
160
+            // If remote sharing is enabled also add the remote share action to the menu
161
+            if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
162
+                $headerActions[] = new ExternalShareMenuAction(
163
+                    // TRANSLATORS The placeholder refers to the software product name as in 'Add to your Nextcloud'
164
+                    $this->l10n->t('Add to your %s', [$this->defaults->getProductName()]),
165
+                    'icon-external',
166
+                    $ownerId,
167
+                    $ownerName,
168
+                    $shareNode->getName(),
169
+                );
170
+            }
171
+        }
172 172
 
173
-		$shareUrl = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $token]);
174
-		// By default use the share link as the direct link
175
-		$directLink = $shareUrl;
176
-		// Add the direct link header actions
177
-		if ($shareNode->getMimePart() === 'image') {
178
-			// If this is a file and especially an image directly point to the image preview
179
-			$directLink = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $token]);
180
-		} elseif (($share->getPermissions() & Constants::PERMISSION_READ) && !$share->getHideDownload()) {
181
-			// Can read and no download restriction, so just download it
182
-			$directLink = $downloadUrl ?? $shareUrl;
183
-		}
184
-		$headerActions[] = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $directLink);
185
-		$response->setHeaderActions($headerActions);
173
+        $shareUrl = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $token]);
174
+        // By default use the share link as the direct link
175
+        $directLink = $shareUrl;
176
+        // Add the direct link header actions
177
+        if ($shareNode->getMimePart() === 'image') {
178
+            // If this is a file and especially an image directly point to the image preview
179
+            $directLink = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $token]);
180
+        } elseif (($share->getPermissions() & Constants::PERMISSION_READ) && !$share->getHideDownload()) {
181
+            // Can read and no download restriction, so just download it
182
+            $directLink = $downloadUrl ?? $shareUrl;
183
+        }
184
+        $headerActions[] = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $directLink);
185
+        $response->setHeaderActions($headerActions);
186 186
 
187
-		return $response;
188
-	}
187
+        return $response;
188
+    }
189 189
 
190
-	/**
191
-	 * Add OpenGraph headers to response for preview
192
-	 * @param IShare $share The share for which to add the headers
193
-	 */
194
-	protected function addMetaHeaders(IShare $share): void {
195
-		$shareNode = $share->getNode();
196
-		$token = $share->getToken();
197
-		$shareUrl = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $token]);
190
+    /**
191
+     * Add OpenGraph headers to response for preview
192
+     * @param IShare $share The share for which to add the headers
193
+     */
194
+    protected function addMetaHeaders(IShare $share): void {
195
+        $shareNode = $share->getNode();
196
+        $token = $share->getToken();
197
+        $shareUrl = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $token]);
198 198
 
199
-		// Handle preview generation for OpenGraph
200
-		$hasImagePreview = false;
201
-		if ($this->previewManager->isMimeSupported($shareNode->getMimetype())) {
202
-			// For images we can use direct links
203
-			if ($shareNode->getMimePart() === 'image') {
204
-				$hasImagePreview = true;
205
-				$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $token]);
206
-				// Whatsapp is kind of picky about their size requirements
207
-				if ($this->request->isUserAgent(['/^WhatsApp/'])) {
208
-					$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
209
-						'token' => $token,
210
-						'x' => 256,
211
-						'y' => 256,
212
-						'a' => true,
213
-					]);
214
-				}
215
-			} else {
216
-				// For normal files use preview API
217
-				$ogPreview = $this->urlGenerator->linkToRouteAbsolute(
218
-					'files_sharing.PublicPreview.getPreview',
219
-					[
220
-						'x' => 256,
221
-						'y' => 256,
222
-						'file' => $share->getTarget(),
223
-						'token' => $token,
224
-					],
225
-				);
226
-			}
227
-		} else {
228
-			// No preview supported, so we just add the favicon
229
-			$ogPreview = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
230
-		}
199
+        // Handle preview generation for OpenGraph
200
+        $hasImagePreview = false;
201
+        if ($this->previewManager->isMimeSupported($shareNode->getMimetype())) {
202
+            // For images we can use direct links
203
+            if ($shareNode->getMimePart() === 'image') {
204
+                $hasImagePreview = true;
205
+                $ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $token]);
206
+                // Whatsapp is kind of picky about their size requirements
207
+                if ($this->request->isUserAgent(['/^WhatsApp/'])) {
208
+                    $ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
209
+                        'token' => $token,
210
+                        'x' => 256,
211
+                        'y' => 256,
212
+                        'a' => true,
213
+                    ]);
214
+                }
215
+            } else {
216
+                // For normal files use preview API
217
+                $ogPreview = $this->urlGenerator->linkToRouteAbsolute(
218
+                    'files_sharing.PublicPreview.getPreview',
219
+                    [
220
+                        'x' => 256,
221
+                        'y' => 256,
222
+                        'file' => $share->getTarget(),
223
+                        'token' => $token,
224
+                    ],
225
+                );
226
+            }
227
+        } else {
228
+            // No preview supported, so we just add the favicon
229
+            $ogPreview = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
230
+        }
231 231
 
232
-		$title = $shareNode->getName();
233
-		$siteName = $this->defaults->getName();
234
-		$description = $siteName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '');
232
+        $title = $shareNode->getName();
233
+        $siteName = $this->defaults->getName();
234
+        $description = $siteName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '');
235 235
 
236
-		// OpenGraph Support: http://ogp.me/
237
-		Util::addHeader('meta', ['property' => 'og:title', 'content' => $title]);
238
-		Util::addHeader('meta', ['property' => 'og:description', 'content' => $description]);
239
-		Util::addHeader('meta', ['property' => 'og:site_name', 'content' => $siteName]);
240
-		Util::addHeader('meta', ['property' => 'og:url', 'content' => $shareUrl]);
241
-		Util::addHeader('meta', ['property' => 'og:type', 'content' => 'website']);
242
-		Util::addHeader('meta', ['property' => 'og:image', 'content' => $ogPreview]); // recommended to always have the image
243
-		if ($shareNode->getMimePart() === 'image') {
244
-			Util::addHeader('meta', ['property' => 'og:image:type', 'content' => $shareNode->getMimeType()]);
245
-		} elseif ($shareNode->getMimePart() === 'audio') {
246
-			$audio = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadshare', ['token' => $token]);
247
-			Util::addHeader('meta', ['property' => 'og:audio', 'content' => $audio]);
248
-			Util::addHeader('meta', ['property' => 'og:audio:type', 'content' => $shareNode->getMimeType()]);
249
-		} elseif ($shareNode->getMimePart() === 'video') {
250
-			$video = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadshare', ['token' => $token]);
251
-			Util::addHeader('meta', ['property' => 'og:video', 'content' => $video]);
252
-			Util::addHeader('meta', ['property' => 'og:video:type', 'content' => $shareNode->getMimeType()]);
253
-		}
236
+        // OpenGraph Support: http://ogp.me/
237
+        Util::addHeader('meta', ['property' => 'og:title', 'content' => $title]);
238
+        Util::addHeader('meta', ['property' => 'og:description', 'content' => $description]);
239
+        Util::addHeader('meta', ['property' => 'og:site_name', 'content' => $siteName]);
240
+        Util::addHeader('meta', ['property' => 'og:url', 'content' => $shareUrl]);
241
+        Util::addHeader('meta', ['property' => 'og:type', 'content' => 'website']);
242
+        Util::addHeader('meta', ['property' => 'og:image', 'content' => $ogPreview]); // recommended to always have the image
243
+        if ($shareNode->getMimePart() === 'image') {
244
+            Util::addHeader('meta', ['property' => 'og:image:type', 'content' => $shareNode->getMimeType()]);
245
+        } elseif ($shareNode->getMimePart() === 'audio') {
246
+            $audio = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadshare', ['token' => $token]);
247
+            Util::addHeader('meta', ['property' => 'og:audio', 'content' => $audio]);
248
+            Util::addHeader('meta', ['property' => 'og:audio:type', 'content' => $shareNode->getMimeType()]);
249
+        } elseif ($shareNode->getMimePart() === 'video') {
250
+            $video = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadshare', ['token' => $token]);
251
+            Util::addHeader('meta', ['property' => 'og:video', 'content' => $video]);
252
+            Util::addHeader('meta', ['property' => 'og:video:type', 'content' => $shareNode->getMimeType()]);
253
+        }
254 254
 
255 255
 
256
-		// Twitter Support: https://developer.x.com/en/docs/x-for-websites/cards/overview/markup
257
-		Util::addHeader('meta', ['property' => 'twitter:title', 'content' => $title]);
258
-		Util::addHeader('meta', ['property' => 'twitter:description', 'content' => $description]);
259
-		Util::addHeader('meta', ['property' => 'twitter:card', 'content' => $hasImagePreview ? 'summary_large_image' : 'summary']);
260
-		Util::addHeader('meta', ['property' => 'twitter:image', 'content' => $ogPreview]);
261
-	}
256
+        // Twitter Support: https://developer.x.com/en/docs/x-for-websites/cards/overview/markup
257
+        Util::addHeader('meta', ['property' => 'twitter:title', 'content' => $title]);
258
+        Util::addHeader('meta', ['property' => 'twitter:description', 'content' => $description]);
259
+        Util::addHeader('meta', ['property' => 'twitter:card', 'content' => $hasImagePreview ? 'summary_large_image' : 'summary']);
260
+        Util::addHeader('meta', ['property' => 'twitter:image', 'content' => $ogPreview]);
261
+    }
262 262
 }
Please login to merge, or discard this patch.
apps/files_sharing/tests/Controller/ShareControllerTest.php 1 patch
Indentation   +762 added lines, -762 removed lines patch added patch discarded remove patch
@@ -54,766 +54,766 @@
 block discarded – undo
54 54
  */
55 55
 class ShareControllerTest extends \Test\TestCase {
56 56
 
57
-	private string $user;
58
-	private string $oldUser;
59
-	private string $appName = 'files_sharing';
60
-	private ShareController $shareController;
61
-
62
-	private IL10N&MockObject $l10n;
63
-	private IConfig&MockObject $config;
64
-	private ISession&MockObject $session;
65
-	private Defaults&MockObject $defaults;
66
-	private IAppConfig&MockObject $appConfig;
67
-	private Manager&MockObject $shareManager;
68
-	private IPreview&MockObject $previewManager;
69
-	private IUserManager&MockObject $userManager;
70
-	private IInitialState&MockObject $initialState;
71
-	private IURLGenerator&MockObject $urlGenerator;
72
-	private ISecureRandom&MockObject $secureRandom;
73
-	private IAccountManager&MockObject $accountManager;
74
-	private IEventDispatcher&MockObject $eventDispatcher;
75
-	private FederatedShareProvider&MockObject $federatedShareProvider;
76
-	private IPublicShareTemplateFactory&MockObject $publicShareTemplateFactory;
77
-
78
-	protected function setUp(): void {
79
-		parent::setUp();
80
-		$this->appName = 'files_sharing';
81
-
82
-		$this->shareManager = $this->createMock(Manager::class);
83
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
84
-		$this->session = $this->createMock(ISession::class);
85
-		$this->previewManager = $this->createMock(IPreview::class);
86
-		$this->config = $this->createMock(IConfig::class);
87
-		$this->appConfig = $this->createMock(IAppConfig::class);
88
-		$this->userManager = $this->createMock(IUserManager::class);
89
-		$this->initialState = $this->createMock(IInitialState::class);
90
-		$this->federatedShareProvider = $this->createMock(FederatedShareProvider::class);
91
-		$this->federatedShareProvider->expects($this->any())
92
-			->method('isOutgoingServer2serverShareEnabled')->willReturn(true);
93
-		$this->federatedShareProvider->expects($this->any())
94
-			->method('isIncomingServer2serverShareEnabled')->willReturn(true);
95
-		$this->accountManager = $this->createMock(IAccountManager::class);
96
-		$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
97
-		$this->l10n = $this->createMock(IL10N::class);
98
-		$this->secureRandom = $this->createMock(ISecureRandom::class);
99
-		$this->defaults = $this->createMock(Defaults::class);
100
-		$this->publicShareTemplateFactory = $this->createMock(IPublicShareTemplateFactory::class);
101
-		$this->publicShareTemplateFactory
102
-			->expects($this->any())
103
-			->method('getProvider')
104
-			->willReturn(
105
-				new DefaultPublicShareTemplateProvider(
106
-					$this->userManager,
107
-					$this->accountManager,
108
-					$this->previewManager,
109
-					$this->federatedShareProvider,
110
-					$this->urlGenerator,
111
-					$this->eventDispatcher,
112
-					$this->l10n,
113
-					$this->defaults,
114
-					$this->config,
115
-					$this->createMock(IRequest::class),
116
-					$this->initialState,
117
-					$this->appConfig,
118
-				)
119
-			);
120
-
121
-		$this->shareController = new ShareController(
122
-			$this->appName,
123
-			$this->createMock(IRequest::class),
124
-			$this->config,
125
-			$this->urlGenerator,
126
-			$this->userManager,
127
-			$this->createMock(IManager::class),
128
-			$this->shareManager,
129
-			$this->session,
130
-			$this->previewManager,
131
-			$this->createMock(IRootFolder::class),
132
-			$this->federatedShareProvider,
133
-			$this->accountManager,
134
-			$this->eventDispatcher,
135
-			$this->l10n,
136
-			$this->secureRandom,
137
-			$this->defaults,
138
-			$this->publicShareTemplateFactory,
139
-		);
140
-
141
-
142
-		// Store current user
143
-		$this->oldUser = \OC_User::getUser();
144
-
145
-		// Create a dummy user
146
-		$this->user = Server::get(ISecureRandom::class)->generate(12, ISecureRandom::CHAR_LOWER);
147
-
148
-		Server::get(IUserManager::class)->createUser($this->user, $this->user);
149
-		\OC_Util::tearDownFS();
150
-		$this->loginAsUser($this->user);
151
-	}
152
-
153
-	protected function tearDown(): void {
154
-		\OC_Util::tearDownFS();
155
-		\OC_User::setUserId('');
156
-		Filesystem::tearDown();
157
-		$user = Server::get(IUserManager::class)->get($this->user);
158
-		if ($user !== null) {
159
-			$user->delete();
160
-		}
161
-		\OC_User::setIncognitoMode(false);
162
-
163
-		Server::get(ISession::class)->set('public_link_authenticated', '');
164
-
165
-		// Set old user
166
-		\OC_User::setUserId($this->oldUser);
167
-		\OC_Util::setupFS($this->oldUser);
168
-		parent::tearDown();
169
-	}
170
-
171
-	public function testShowShareInvalidToken(): void {
172
-		$this->shareController->setToken('invalidtoken');
173
-
174
-		$this->shareManager
175
-			->expects($this->once())
176
-			->method('getShareByToken')
177
-			->with('invalidtoken')
178
-			->will($this->throwException(new ShareNotFound()));
179
-
180
-		$this->expectException(NotFoundException::class);
181
-
182
-		// Test without a not existing token
183
-		$this->shareController->showShare();
184
-	}
185
-
186
-	public function testShowShareNotAuthenticated(): void {
187
-		$this->shareController->setToken('validtoken');
188
-
189
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
190
-		$share->setPassword('password');
191
-
192
-		$this->shareManager
193
-			->expects($this->once())
194
-			->method('getShareByToken')
195
-			->with('validtoken')
196
-			->willReturn($share);
197
-
198
-		$this->expectException(NotFoundException::class);
199
-
200
-		// Test without a not existing token
201
-		$this->shareController->showShare();
202
-	}
203
-
204
-
205
-	public function testShowShare(): void {
206
-		$note = 'personal note';
207
-		$filename = 'file1.txt';
208
-
209
-		$this->shareController->setToken('token');
210
-
211
-		$owner = $this->createMock(IUser::class);
212
-		$owner->method('getDisplayName')->willReturn('ownerDisplay');
213
-		$owner->method('getUID')->willReturn('ownerUID');
214
-		$owner->method('isEnabled')->willReturn(true);
215
-
216
-		$initiator = $this->createMock(IUser::class);
217
-		$initiator->method('getDisplayName')->willReturn('initiatorDisplay');
218
-		$initiator->method('getUID')->willReturn('initiatorUID');
219
-		$initiator->method('isEnabled')->willReturn(true);
220
-
221
-		$file = $this->createMock(File::class);
222
-		$file->method('getName')->willReturn($filename);
223
-		$file->method('getMimetype')->willReturn('text/plain');
224
-		$file->method('getSize')->willReturn(33);
225
-		$file->method('isReadable')->willReturn(true);
226
-		$file->method('isShareable')->willReturn(true);
227
-		$file->method('getId')->willReturn(111);
228
-
229
-		$accountName = $this->createMock(IAccountProperty::class);
230
-		$accountName->method('getScope')
231
-			->willReturn(IAccountManager::SCOPE_PUBLISHED);
232
-		$account = $this->createMock(IAccount::class);
233
-		$account->method('getProperty')
234
-			->with(IAccountManager::PROPERTY_DISPLAYNAME)
235
-			->willReturn($accountName);
236
-		$this->accountManager->expects($this->once())
237
-			->method('getAccount')
238
-			->with($owner)
239
-			->willReturn($account);
240
-
241
-		/** @var Manager */
242
-		$manager = Server::get(Manager::class);
243
-		$share = $manager->newShare();
244
-		$share->setId(42)
245
-			->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE)
246
-			->setPassword('password')
247
-			->setShareOwner('ownerUID')
248
-			->setSharedBy('initiatorUID')
249
-			->setNode($file)
250
-			->setNote($note)
251
-			->setTarget("/$filename")
252
-			->setToken('token');
253
-
254
-		$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
255
-		$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
256
-
257
-		$this->urlGenerator->expects(self::atLeast(2))
258
-			->method('linkToRouteAbsolute')
259
-			->willReturnMap([
260
-				// every file has the show show share url in the opengraph url prop
261
-				['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
262
-				// this share is not an image to the default preview is used
263
-				['files_sharing.PublicPreview.getPreview', ['x' => 256, 'y' => 256, 'file' => $share->getTarget(), 'token' => 'token'], 'previewUrl'],
264
-			]);
265
-
266
-		$this->urlGenerator->expects($this->once())
267
-			->method('getAbsoluteURL')
268
-			->willReturnMap([
269
-				['/public.php/dav/files/token/?accept=zip', 'downloadUrl'],
270
-			]);
271
-
272
-		$this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
273
-
274
-		$this->config->method('getSystemValue')
275
-			->willReturnMap(
276
-				[
277
-					['max_filesize_animated_gifs_public_sharing', 10, 10],
278
-					['enable_previews', true, true],
279
-					['preview_max_x', 1024, 1024],
280
-					['preview_max_y', 1024, 1024],
281
-				]
282
-			);
283
-
284
-		$this->shareManager
285
-			->expects($this->once())
286
-			->method('getShareByToken')
287
-			->with('token')
288
-			->willReturn($share);
289
-
290
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
291
-			if ($uid === 'ownerUID') {
292
-				return $owner;
293
-			}
294
-			if ($uid === 'initiatorUID') {
295
-				return $initiator;
296
-			}
297
-			return null;
298
-		});
299
-
300
-		$this->eventDispatcher->method('dispatchTyped')->with(
301
-			$this->callback(function ($event) use ($share) {
302
-				if ($event instanceof BeforeTemplateRenderedEvent) {
303
-					return $event->getShare() === $share;
304
-				} else {
305
-					return true;
306
-				}
307
-			})
308
-		);
309
-
310
-		$this->l10n->expects($this->any())
311
-			->method('t')
312
-			->willReturnCallback(function ($text, $parameters) {
313
-				return vsprintf($text, $parameters);
314
-			});
315
-
316
-		$this->defaults->expects(self::any())
317
-			->method('getProductName')
318
-			->willReturn('Nextcloud');
319
-
320
-		// Ensure the correct initial state is setup
321
-		// Shared node is a file so this is a single file share:
322
-		$view = 'public-file-share';
323
-		// Set up initial state
324
-		$initialState = [];
325
-		$this->initialState->expects(self::any())
326
-			->method('provideInitialState')
327
-			->willReturnCallback(function ($key, $value) use (&$initialState): void {
328
-				$initialState[$key] = $value;
329
-			});
330
-		$expectedInitialState = [
331
-			'isPublic' => true,
332
-			'sharingToken' => 'token',
333
-			'sharePermissions' => (Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE),
334
-			'filename' => $filename,
335
-			'view' => $view,
336
-			'fileId' => 111,
337
-			'owner' => 'ownerUID',
338
-			'ownerDisplayName' => 'ownerDisplay',
339
-		];
340
-
341
-		$response = $this->shareController->showShare();
342
-
343
-		$this->assertEquals($expectedInitialState, $initialState);
344
-
345
-		$csp = new ContentSecurityPolicy();
346
-		$csp->addAllowedFrameDomain('\'self\'');
347
-		$expectedResponse = new PublicTemplateResponse('files', 'index');
348
-		$expectedResponse->setParams(['pageTitle' => $filename]);
349
-		$expectedResponse->setContentSecurityPolicy($csp);
350
-		$expectedResponse->setHeaderTitle($filename);
351
-		$expectedResponse->setHeaderDetails('shared by ownerDisplay');
352
-		$expectedResponse->setHeaderActions([
353
-			new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', 'downloadUrl', 0, '33'),
354
-			new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', 'owner', 'ownerDisplay', $filename),
355
-			new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'downloadUrl'),
356
-		]);
357
-
358
-		$this->assertEquals($expectedResponse, $response);
359
-	}
360
-
361
-	public function testShowFileDropShare(): void {
362
-		$filename = 'folder1';
363
-
364
-		$this->shareController->setToken('token');
365
-
366
-		$owner = $this->createMock(IUser::class);
367
-		$owner->method('getDisplayName')->willReturn('ownerDisplay');
368
-		$owner->method('getUID')->willReturn('ownerUID');
369
-		$owner->method('isEnabled')->willReturn(true);
370
-
371
-		$initiator = $this->createMock(IUser::class);
372
-		$initiator->method('getDisplayName')->willReturn('initiatorDisplay');
373
-		$initiator->method('getUID')->willReturn('initiatorUID');
374
-		$initiator->method('isEnabled')->willReturn(true);
375
-
376
-		$file = $this->createMock(Folder::class);
377
-		$file->method('isReadable')->willReturn(true);
378
-		$file->method('isShareable')->willReturn(true);
379
-		$file->method('getId')->willReturn(1234);
380
-		$file->method('getName')->willReturn($filename);
381
-
382
-		$accountName = $this->createMock(IAccountProperty::class);
383
-		$accountName->method('getScope')
384
-			->willReturn(IAccountManager::SCOPE_PUBLISHED);
385
-		$account = $this->createMock(IAccount::class);
386
-		$account->method('getProperty')
387
-			->with(IAccountManager::PROPERTY_DISPLAYNAME)
388
-			->willReturn($accountName);
389
-		$this->accountManager->expects($this->once())
390
-			->method('getAccount')
391
-			->with($owner)
392
-			->willReturn($account);
393
-
394
-		/** @var Manager */
395
-		$manager = Server::get(Manager::class);
396
-		$share = $manager->newShare();
397
-		$share->setId(42)
398
-			->setPermissions(Constants::PERMISSION_CREATE)
399
-			->setPassword('password')
400
-			->setShareOwner('ownerUID')
401
-			->setSharedBy('initiatorUID')
402
-			->setNote('The note')
403
-			->setLabel('A label')
404
-			->setNode($file)
405
-			->setTarget("/$filename")
406
-			->setToken('token');
407
-
408
-		$this->appConfig
409
-			->expects($this->once())
410
-			->method('getValueString')
411
-			->with('core', 'shareapi_public_link_disclaimertext', '')
412
-			->willReturn('My disclaimer text');
413
-
414
-		$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
415
-		$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
416
-
417
-		$this->urlGenerator->expects(self::atLeastOnce())
418
-			->method('linkToRouteAbsolute')
419
-			->willReturnMap([
420
-				// every file has the show show share url in the opengraph url prop
421
-				['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
422
-				// there is no preview or folders so no other link for opengraph
423
-			]);
424
-
425
-		$this->config->method('getSystemValue')
426
-			->willReturnMap(
427
-				[
428
-					['max_filesize_animated_gifs_public_sharing', 10, 10],
429
-					['enable_previews', true, true],
430
-					['preview_max_x', 1024, 1024],
431
-					['preview_max_y', 1024, 1024],
432
-				]
433
-			);
434
-
435
-		$this->shareManager
436
-			->expects($this->once())
437
-			->method('getShareByToken')
438
-			->with('token')
439
-			->willReturn($share);
440
-
441
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
442
-			if ($uid === 'ownerUID') {
443
-				return $owner;
444
-			}
445
-			if ($uid === 'initiatorUID') {
446
-				return $initiator;
447
-			}
448
-			return null;
449
-		});
450
-
451
-		$this->eventDispatcher->method('dispatchTyped')->with(
452
-			$this->callback(function ($event) use ($share) {
453
-				if ($event instanceof BeforeTemplateRenderedEvent) {
454
-					return $event->getShare() === $share;
455
-				} else {
456
-					return true;
457
-				}
458
-			})
459
-		);
460
-
461
-		$this->l10n->expects($this->any())
462
-			->method('t')
463
-			->willReturnCallback(function ($text, $parameters) {
464
-				return vsprintf($text, $parameters);
465
-			});
466
-
467
-		// Set up initial state
468
-		$initialState = [];
469
-		$this->initialState->expects(self::any())
470
-			->method('provideInitialState')
471
-			->willReturnCallback(function ($key, $value) use (&$initialState): void {
472
-				$initialState[$key] = $value;
473
-			});
474
-		$expectedInitialState = [
475
-			'isPublic' => true,
476
-			'sharingToken' => 'token',
477
-			'sharePermissions' => Constants::PERMISSION_CREATE,
478
-			'filename' => $filename,
479
-			'view' => 'public-file-drop',
480
-			'disclaimer' => 'My disclaimer text',
481
-			'owner' => 'ownerUID',
482
-			'ownerDisplayName' => 'ownerDisplay',
483
-			'note' => 'The note',
484
-			'label' => 'A label',
485
-		];
486
-
487
-		$response = $this->shareController->showShare();
488
-
489
-		$this->assertEquals($expectedInitialState, $initialState);
490
-
491
-		$csp = new ContentSecurityPolicy();
492
-		$csp->addAllowedFrameDomain('\'self\'');
493
-		$expectedResponse = new PublicTemplateResponse('files', 'index');
494
-		$expectedResponse->setParams(['pageTitle' => 'A label']);
495
-		$expectedResponse->setContentSecurityPolicy($csp);
496
-		$expectedResponse->setHeaderTitle('A label');
497
-		$expectedResponse->setHeaderDetails('shared by ownerDisplay');
498
-		$expectedResponse->setHeaderActions([
499
-			new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'shareUrl'),
500
-		]);
501
-
502
-		$this->assertEquals($expectedResponse, $response);
503
-	}
504
-
505
-	public function testShowShareWithPrivateName(): void {
506
-		$note = 'personal note';
507
-		$filename = 'file1.txt';
508
-
509
-		$this->shareController->setToken('token');
510
-
511
-		$owner = $this->createMock(IUser::class);
512
-		$owner->method('getDisplayName')->willReturn('ownerDisplay');
513
-		$owner->method('getUID')->willReturn('ownerUID');
514
-		$owner->method('isEnabled')->willReturn(true);
515
-
516
-		$initiator = $this->createMock(IUser::class);
517
-		$initiator->method('getDisplayName')->willReturn('initiatorDisplay');
518
-		$initiator->method('getUID')->willReturn('initiatorUID');
519
-		$initiator->method('isEnabled')->willReturn(true);
520
-
521
-		$file = $this->createMock(File::class);
522
-		$file->method('getName')->willReturn($filename);
523
-		$file->method('getMimetype')->willReturn('text/plain');
524
-		$file->method('getSize')->willReturn(33);
525
-		$file->method('isReadable')->willReturn(true);
526
-		$file->method('isShareable')->willReturn(true);
527
-		$file->method('getId')->willReturn(111);
528
-
529
-		$accountName = $this->createMock(IAccountProperty::class);
530
-		$accountName->method('getScope')
531
-			->willReturn(IAccountManager::SCOPE_LOCAL);
532
-		$account = $this->createMock(IAccount::class);
533
-		$account->method('getProperty')
534
-			->with(IAccountManager::PROPERTY_DISPLAYNAME)
535
-			->willReturn($accountName);
536
-		$this->accountManager->expects($this->once())
537
-			->method('getAccount')
538
-			->with($owner)
539
-			->willReturn($account);
540
-
541
-		/** @var IShare */
542
-		$share = Server::get(Manager::class)->newShare();
543
-		$share->setId(42);
544
-		$share->setPassword('password')
545
-			->setShareOwner('ownerUID')
546
-			->setSharedBy('initiatorUID')
547
-			->setNode($file)
548
-			->setNote($note)
549
-			->setToken('token')
550
-			->setPermissions(Constants::PERMISSION_ALL & ~Constants::PERMISSION_SHARE)
551
-			->setTarget("/$filename");
552
-
553
-		$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
554
-		$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
555
-
556
-		$this->urlGenerator->expects(self::atLeast(2))
557
-			->method('linkToRouteAbsolute')
558
-			->willReturnMap([
559
-				// every file has the show show share url in the opengraph url prop
560
-				['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
561
-				// this share is not an image to the default preview is used
562
-				['files_sharing.PublicPreview.getPreview', ['x' => 256, 'y' => 256, 'file' => $share->getTarget(), 'token' => 'token'], 'previewUrl'],
563
-			]);
564
-
565
-		$this->urlGenerator->expects($this->once())
566
-			->method('getAbsoluteURL')
567
-			->willReturnMap([
568
-				['/public.php/dav/files/token/?accept=zip', 'downloadUrl'],
569
-			]);
570
-
571
-		$this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
572
-
573
-		$this->config->method('getSystemValue')
574
-			->willReturnMap(
575
-				[
576
-					['max_filesize_animated_gifs_public_sharing', 10, 10],
577
-					['enable_previews', true, true],
578
-					['preview_max_x', 1024, 1024],
579
-					['preview_max_y', 1024, 1024],
580
-				]
581
-			);
582
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
583
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
584
-
585
-		$this->shareManager
586
-			->expects($this->once())
587
-			->method('getShareByToken')
588
-			->with('token')
589
-			->willReturn($share);
590
-
591
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
592
-			if ($uid === 'ownerUID') {
593
-				return $owner;
594
-			}
595
-			if ($uid === 'initiatorUID') {
596
-				return $initiator;
597
-			}
598
-			return null;
599
-		});
600
-
601
-		$this->eventDispatcher->method('dispatchTyped')->with(
602
-			$this->callback(function ($event) use ($share) {
603
-				if ($event instanceof BeforeTemplateRenderedEvent) {
604
-					return $event->getShare() === $share;
605
-				} else {
606
-					return true;
607
-				}
608
-			})
609
-		);
610
-
611
-		$this->l10n->expects($this->any())
612
-			->method('t')
613
-			->will($this->returnCallback(function ($text, $parameters) {
614
-				return vsprintf($text, $parameters);
615
-			}));
616
-
617
-		$this->defaults->expects(self::any())
618
-			->method('getProductName')
619
-			->willReturn('Nextcloud');
620
-
621
-		$response = $this->shareController->showShare();
622
-
623
-		$csp = new ContentSecurityPolicy();
624
-		$csp->addAllowedFrameDomain('\'self\'');
625
-		$expectedResponse = new PublicTemplateResponse('files', 'index');
626
-		$expectedResponse->setParams(['pageTitle' => $filename]);
627
-		$expectedResponse->setContentSecurityPolicy($csp);
628
-		$expectedResponse->setHeaderTitle($filename);
629
-		$expectedResponse->setHeaderDetails('');
630
-		$expectedResponse->setHeaderActions([
631
-			new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', 'downloadUrl', 0, '33'),
632
-			new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', 'owner', 'ownerDisplay', $filename),
633
-			new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'downloadUrl'),
634
-		]);
635
-
636
-		$this->assertEquals($expectedResponse, $response);
637
-	}
638
-
639
-
640
-	public function testShowShareInvalid(): void {
641
-		$this->expectException(NotFoundException::class);
642
-
643
-		$filename = 'file1.txt';
644
-		$this->shareController->setToken('token');
645
-
646
-		$owner = $this->getMockBuilder(IUser::class)->getMock();
647
-		$owner->method('getDisplayName')->willReturn('ownerDisplay');
648
-		$owner->method('getUID')->willReturn('ownerUID');
649
-
650
-		$file = $this->getMockBuilder('OCP\Files\File')->getMock();
651
-		$file->method('getName')->willReturn($filename);
652
-		$file->method('getMimetype')->willReturn('text/plain');
653
-		$file->method('getSize')->willReturn(33);
654
-		$file->method('isShareable')->willReturn(false);
655
-		$file->method('isReadable')->willReturn(true);
656
-
657
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
658
-		$share->setId(42);
659
-		$share->setPassword('password')
660
-			->setShareOwner('ownerUID')
661
-			->setNode($file)
662
-			->setTarget("/$filename");
663
-
664
-		$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
665
-		$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
666
-
667
-		$this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
668
-
669
-		$this->config->method('getSystemValue')
670
-			->willReturnMap(
671
-				[
672
-					['max_filesize_animated_gifs_public_sharing', 10, 10],
673
-					['enable_previews', true, true],
674
-				]
675
-			);
676
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
677
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
678
-
679
-		$this->shareManager
680
-			->expects($this->once())
681
-			->method('getShareByToken')
682
-			->with('token')
683
-			->willReturn($share);
684
-
685
-		$this->userManager->method('get')->with('ownerUID')->willReturn($owner);
686
-
687
-		$this->shareController->showShare();
688
-	}
689
-
690
-	public function testDownloadShareWithCreateOnlyShare(): void {
691
-		$share = $this->getMockBuilder(IShare::class)->getMock();
692
-		$share->method('getPassword')->willReturn('password');
693
-		$share
694
-			->expects($this->once())
695
-			->method('getPermissions')
696
-			->willReturn(Constants::PERMISSION_CREATE);
697
-
698
-		$this->shareManager
699
-			->expects($this->once())
700
-			->method('getShareByToken')
701
-			->with('validtoken')
702
-			->willReturn($share);
703
-
704
-		// Test with a password protected share and no authentication
705
-		$response = $this->shareController->downloadShare('validtoken');
706
-		$expectedResponse = new DataResponse('Share has no read permission');
707
-		$this->assertEquals($expectedResponse, $response);
708
-	}
709
-
710
-	public function testDownloadShareWithoutDownloadPermission(): void {
711
-		$attributes = $this->createMock(IAttributes::class);
712
-		$attributes->expects(self::once())
713
-			->method('getAttribute')
714
-			->with('permissions', 'download')
715
-			->willReturn(false);
716
-
717
-		$share = $this->createMock(IShare::class);
718
-		$share->method('getPassword')->willReturn('password');
719
-		$share->expects(self::once())
720
-			->method('getPermissions')
721
-			->willReturn(Constants::PERMISSION_READ);
722
-		$share->expects(self::once())
723
-			->method('getAttributes')
724
-			->willReturn($attributes);
725
-
726
-		$this->shareManager
727
-			->expects(self::once())
728
-			->method('getShareByToken')
729
-			->with('validtoken')
730
-			->willReturn($share);
731
-
732
-		// Test with a password protected share and no authentication
733
-		$response = $this->shareController->downloadShare('validtoken');
734
-		$expectedResponse = new DataResponse('Share has no download permission');
735
-		$this->assertEquals($expectedResponse, $response);
736
-	}
737
-
738
-	public function testDisabledOwner(): void {
739
-		$this->shareController->setToken('token');
740
-
741
-		$owner = $this->getMockBuilder(IUser::class)->getMock();
742
-		$owner->method('isEnabled')->willReturn(false);
743
-
744
-		$initiator = $this->createMock(IUser::class);
745
-		$initiator->method('isEnabled')->willReturn(false);
746
-
747
-		/* @var MockObject|Folder $folder */
748
-		$folder = $this->createMock(Folder::class);
749
-
750
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
751
-		$share->setId(42);
752
-		$share->setPermissions(Constants::PERMISSION_CREATE)
753
-			->setShareOwner('ownerUID')
754
-			->setSharedBy('initiatorUID')
755
-			->setNode($folder)
756
-			->setTarget('/share');
757
-
758
-		$this->shareManager
759
-			->expects($this->once())
760
-			->method('getShareByToken')
761
-			->with('token')
762
-			->willReturn($share);
763
-
764
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
765
-			if ($uid === 'ownerUID') {
766
-				return $owner;
767
-			}
768
-			if ($uid === 'initiatorUID') {
769
-				return $initiator;
770
-			}
771
-			return null;
772
-		});
773
-
774
-		$this->expectException(NotFoundException::class);
775
-
776
-		$this->shareController->showShare();
777
-	}
778
-
779
-	public function testDisabledInitiator(): void {
780
-		$this->shareController->setToken('token');
781
-
782
-		$owner = $this->getMockBuilder(IUser::class)->getMock();
783
-		$owner->method('isEnabled')->willReturn(false);
784
-
785
-		$initiator = $this->createMock(IUser::class);
786
-		$initiator->method('isEnabled')->willReturn(true);
787
-
788
-		/* @var MockObject|Folder $folder */
789
-		$folder = $this->createMock(Folder::class);
790
-
791
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
792
-		$share->setId(42);
793
-		$share->setPermissions(Constants::PERMISSION_CREATE)
794
-			->setShareOwner('ownerUID')
795
-			->setSharedBy('initiatorUID')
796
-			->setNode($folder)
797
-			->setTarget('/share');
798
-
799
-		$this->shareManager
800
-			->expects($this->once())
801
-			->method('getShareByToken')
802
-			->with('token')
803
-			->willReturn($share);
804
-
805
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
806
-			if ($uid === 'ownerUID') {
807
-				return $owner;
808
-			}
809
-			if ($uid === 'initiatorUID') {
810
-				return $initiator;
811
-			}
812
-			return null;
813
-		});
814
-
815
-		$this->expectException(NotFoundException::class);
816
-
817
-		$this->shareController->showShare();
818
-	}
57
+    private string $user;
58
+    private string $oldUser;
59
+    private string $appName = 'files_sharing';
60
+    private ShareController $shareController;
61
+
62
+    private IL10N&MockObject $l10n;
63
+    private IConfig&MockObject $config;
64
+    private ISession&MockObject $session;
65
+    private Defaults&MockObject $defaults;
66
+    private IAppConfig&MockObject $appConfig;
67
+    private Manager&MockObject $shareManager;
68
+    private IPreview&MockObject $previewManager;
69
+    private IUserManager&MockObject $userManager;
70
+    private IInitialState&MockObject $initialState;
71
+    private IURLGenerator&MockObject $urlGenerator;
72
+    private ISecureRandom&MockObject $secureRandom;
73
+    private IAccountManager&MockObject $accountManager;
74
+    private IEventDispatcher&MockObject $eventDispatcher;
75
+    private FederatedShareProvider&MockObject $federatedShareProvider;
76
+    private IPublicShareTemplateFactory&MockObject $publicShareTemplateFactory;
77
+
78
+    protected function setUp(): void {
79
+        parent::setUp();
80
+        $this->appName = 'files_sharing';
81
+
82
+        $this->shareManager = $this->createMock(Manager::class);
83
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
84
+        $this->session = $this->createMock(ISession::class);
85
+        $this->previewManager = $this->createMock(IPreview::class);
86
+        $this->config = $this->createMock(IConfig::class);
87
+        $this->appConfig = $this->createMock(IAppConfig::class);
88
+        $this->userManager = $this->createMock(IUserManager::class);
89
+        $this->initialState = $this->createMock(IInitialState::class);
90
+        $this->federatedShareProvider = $this->createMock(FederatedShareProvider::class);
91
+        $this->federatedShareProvider->expects($this->any())
92
+            ->method('isOutgoingServer2serverShareEnabled')->willReturn(true);
93
+        $this->federatedShareProvider->expects($this->any())
94
+            ->method('isIncomingServer2serverShareEnabled')->willReturn(true);
95
+        $this->accountManager = $this->createMock(IAccountManager::class);
96
+        $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
97
+        $this->l10n = $this->createMock(IL10N::class);
98
+        $this->secureRandom = $this->createMock(ISecureRandom::class);
99
+        $this->defaults = $this->createMock(Defaults::class);
100
+        $this->publicShareTemplateFactory = $this->createMock(IPublicShareTemplateFactory::class);
101
+        $this->publicShareTemplateFactory
102
+            ->expects($this->any())
103
+            ->method('getProvider')
104
+            ->willReturn(
105
+                new DefaultPublicShareTemplateProvider(
106
+                    $this->userManager,
107
+                    $this->accountManager,
108
+                    $this->previewManager,
109
+                    $this->federatedShareProvider,
110
+                    $this->urlGenerator,
111
+                    $this->eventDispatcher,
112
+                    $this->l10n,
113
+                    $this->defaults,
114
+                    $this->config,
115
+                    $this->createMock(IRequest::class),
116
+                    $this->initialState,
117
+                    $this->appConfig,
118
+                )
119
+            );
120
+
121
+        $this->shareController = new ShareController(
122
+            $this->appName,
123
+            $this->createMock(IRequest::class),
124
+            $this->config,
125
+            $this->urlGenerator,
126
+            $this->userManager,
127
+            $this->createMock(IManager::class),
128
+            $this->shareManager,
129
+            $this->session,
130
+            $this->previewManager,
131
+            $this->createMock(IRootFolder::class),
132
+            $this->federatedShareProvider,
133
+            $this->accountManager,
134
+            $this->eventDispatcher,
135
+            $this->l10n,
136
+            $this->secureRandom,
137
+            $this->defaults,
138
+            $this->publicShareTemplateFactory,
139
+        );
140
+
141
+
142
+        // Store current user
143
+        $this->oldUser = \OC_User::getUser();
144
+
145
+        // Create a dummy user
146
+        $this->user = Server::get(ISecureRandom::class)->generate(12, ISecureRandom::CHAR_LOWER);
147
+
148
+        Server::get(IUserManager::class)->createUser($this->user, $this->user);
149
+        \OC_Util::tearDownFS();
150
+        $this->loginAsUser($this->user);
151
+    }
152
+
153
+    protected function tearDown(): void {
154
+        \OC_Util::tearDownFS();
155
+        \OC_User::setUserId('');
156
+        Filesystem::tearDown();
157
+        $user = Server::get(IUserManager::class)->get($this->user);
158
+        if ($user !== null) {
159
+            $user->delete();
160
+        }
161
+        \OC_User::setIncognitoMode(false);
162
+
163
+        Server::get(ISession::class)->set('public_link_authenticated', '');
164
+
165
+        // Set old user
166
+        \OC_User::setUserId($this->oldUser);
167
+        \OC_Util::setupFS($this->oldUser);
168
+        parent::tearDown();
169
+    }
170
+
171
+    public function testShowShareInvalidToken(): void {
172
+        $this->shareController->setToken('invalidtoken');
173
+
174
+        $this->shareManager
175
+            ->expects($this->once())
176
+            ->method('getShareByToken')
177
+            ->with('invalidtoken')
178
+            ->will($this->throwException(new ShareNotFound()));
179
+
180
+        $this->expectException(NotFoundException::class);
181
+
182
+        // Test without a not existing token
183
+        $this->shareController->showShare();
184
+    }
185
+
186
+    public function testShowShareNotAuthenticated(): void {
187
+        $this->shareController->setToken('validtoken');
188
+
189
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
190
+        $share->setPassword('password');
191
+
192
+        $this->shareManager
193
+            ->expects($this->once())
194
+            ->method('getShareByToken')
195
+            ->with('validtoken')
196
+            ->willReturn($share);
197
+
198
+        $this->expectException(NotFoundException::class);
199
+
200
+        // Test without a not existing token
201
+        $this->shareController->showShare();
202
+    }
203
+
204
+
205
+    public function testShowShare(): void {
206
+        $note = 'personal note';
207
+        $filename = 'file1.txt';
208
+
209
+        $this->shareController->setToken('token');
210
+
211
+        $owner = $this->createMock(IUser::class);
212
+        $owner->method('getDisplayName')->willReturn('ownerDisplay');
213
+        $owner->method('getUID')->willReturn('ownerUID');
214
+        $owner->method('isEnabled')->willReturn(true);
215
+
216
+        $initiator = $this->createMock(IUser::class);
217
+        $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
218
+        $initiator->method('getUID')->willReturn('initiatorUID');
219
+        $initiator->method('isEnabled')->willReturn(true);
220
+
221
+        $file = $this->createMock(File::class);
222
+        $file->method('getName')->willReturn($filename);
223
+        $file->method('getMimetype')->willReturn('text/plain');
224
+        $file->method('getSize')->willReturn(33);
225
+        $file->method('isReadable')->willReturn(true);
226
+        $file->method('isShareable')->willReturn(true);
227
+        $file->method('getId')->willReturn(111);
228
+
229
+        $accountName = $this->createMock(IAccountProperty::class);
230
+        $accountName->method('getScope')
231
+            ->willReturn(IAccountManager::SCOPE_PUBLISHED);
232
+        $account = $this->createMock(IAccount::class);
233
+        $account->method('getProperty')
234
+            ->with(IAccountManager::PROPERTY_DISPLAYNAME)
235
+            ->willReturn($accountName);
236
+        $this->accountManager->expects($this->once())
237
+            ->method('getAccount')
238
+            ->with($owner)
239
+            ->willReturn($account);
240
+
241
+        /** @var Manager */
242
+        $manager = Server::get(Manager::class);
243
+        $share = $manager->newShare();
244
+        $share->setId(42)
245
+            ->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE)
246
+            ->setPassword('password')
247
+            ->setShareOwner('ownerUID')
248
+            ->setSharedBy('initiatorUID')
249
+            ->setNode($file)
250
+            ->setNote($note)
251
+            ->setTarget("/$filename")
252
+            ->setToken('token');
253
+
254
+        $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
255
+        $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
256
+
257
+        $this->urlGenerator->expects(self::atLeast(2))
258
+            ->method('linkToRouteAbsolute')
259
+            ->willReturnMap([
260
+                // every file has the show show share url in the opengraph url prop
261
+                ['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
262
+                // this share is not an image to the default preview is used
263
+                ['files_sharing.PublicPreview.getPreview', ['x' => 256, 'y' => 256, 'file' => $share->getTarget(), 'token' => 'token'], 'previewUrl'],
264
+            ]);
265
+
266
+        $this->urlGenerator->expects($this->once())
267
+            ->method('getAbsoluteURL')
268
+            ->willReturnMap([
269
+                ['/public.php/dav/files/token/?accept=zip', 'downloadUrl'],
270
+            ]);
271
+
272
+        $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
273
+
274
+        $this->config->method('getSystemValue')
275
+            ->willReturnMap(
276
+                [
277
+                    ['max_filesize_animated_gifs_public_sharing', 10, 10],
278
+                    ['enable_previews', true, true],
279
+                    ['preview_max_x', 1024, 1024],
280
+                    ['preview_max_y', 1024, 1024],
281
+                ]
282
+            );
283
+
284
+        $this->shareManager
285
+            ->expects($this->once())
286
+            ->method('getShareByToken')
287
+            ->with('token')
288
+            ->willReturn($share);
289
+
290
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
291
+            if ($uid === 'ownerUID') {
292
+                return $owner;
293
+            }
294
+            if ($uid === 'initiatorUID') {
295
+                return $initiator;
296
+            }
297
+            return null;
298
+        });
299
+
300
+        $this->eventDispatcher->method('dispatchTyped')->with(
301
+            $this->callback(function ($event) use ($share) {
302
+                if ($event instanceof BeforeTemplateRenderedEvent) {
303
+                    return $event->getShare() === $share;
304
+                } else {
305
+                    return true;
306
+                }
307
+            })
308
+        );
309
+
310
+        $this->l10n->expects($this->any())
311
+            ->method('t')
312
+            ->willReturnCallback(function ($text, $parameters) {
313
+                return vsprintf($text, $parameters);
314
+            });
315
+
316
+        $this->defaults->expects(self::any())
317
+            ->method('getProductName')
318
+            ->willReturn('Nextcloud');
319
+
320
+        // Ensure the correct initial state is setup
321
+        // Shared node is a file so this is a single file share:
322
+        $view = 'public-file-share';
323
+        // Set up initial state
324
+        $initialState = [];
325
+        $this->initialState->expects(self::any())
326
+            ->method('provideInitialState')
327
+            ->willReturnCallback(function ($key, $value) use (&$initialState): void {
328
+                $initialState[$key] = $value;
329
+            });
330
+        $expectedInitialState = [
331
+            'isPublic' => true,
332
+            'sharingToken' => 'token',
333
+            'sharePermissions' => (Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE),
334
+            'filename' => $filename,
335
+            'view' => $view,
336
+            'fileId' => 111,
337
+            'owner' => 'ownerUID',
338
+            'ownerDisplayName' => 'ownerDisplay',
339
+        ];
340
+
341
+        $response = $this->shareController->showShare();
342
+
343
+        $this->assertEquals($expectedInitialState, $initialState);
344
+
345
+        $csp = new ContentSecurityPolicy();
346
+        $csp->addAllowedFrameDomain('\'self\'');
347
+        $expectedResponse = new PublicTemplateResponse('files', 'index');
348
+        $expectedResponse->setParams(['pageTitle' => $filename]);
349
+        $expectedResponse->setContentSecurityPolicy($csp);
350
+        $expectedResponse->setHeaderTitle($filename);
351
+        $expectedResponse->setHeaderDetails('shared by ownerDisplay');
352
+        $expectedResponse->setHeaderActions([
353
+            new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', 'downloadUrl', 0, '33'),
354
+            new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', 'owner', 'ownerDisplay', $filename),
355
+            new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'downloadUrl'),
356
+        ]);
357
+
358
+        $this->assertEquals($expectedResponse, $response);
359
+    }
360
+
361
+    public function testShowFileDropShare(): void {
362
+        $filename = 'folder1';
363
+
364
+        $this->shareController->setToken('token');
365
+
366
+        $owner = $this->createMock(IUser::class);
367
+        $owner->method('getDisplayName')->willReturn('ownerDisplay');
368
+        $owner->method('getUID')->willReturn('ownerUID');
369
+        $owner->method('isEnabled')->willReturn(true);
370
+
371
+        $initiator = $this->createMock(IUser::class);
372
+        $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
373
+        $initiator->method('getUID')->willReturn('initiatorUID');
374
+        $initiator->method('isEnabled')->willReturn(true);
375
+
376
+        $file = $this->createMock(Folder::class);
377
+        $file->method('isReadable')->willReturn(true);
378
+        $file->method('isShareable')->willReturn(true);
379
+        $file->method('getId')->willReturn(1234);
380
+        $file->method('getName')->willReturn($filename);
381
+
382
+        $accountName = $this->createMock(IAccountProperty::class);
383
+        $accountName->method('getScope')
384
+            ->willReturn(IAccountManager::SCOPE_PUBLISHED);
385
+        $account = $this->createMock(IAccount::class);
386
+        $account->method('getProperty')
387
+            ->with(IAccountManager::PROPERTY_DISPLAYNAME)
388
+            ->willReturn($accountName);
389
+        $this->accountManager->expects($this->once())
390
+            ->method('getAccount')
391
+            ->with($owner)
392
+            ->willReturn($account);
393
+
394
+        /** @var Manager */
395
+        $manager = Server::get(Manager::class);
396
+        $share = $manager->newShare();
397
+        $share->setId(42)
398
+            ->setPermissions(Constants::PERMISSION_CREATE)
399
+            ->setPassword('password')
400
+            ->setShareOwner('ownerUID')
401
+            ->setSharedBy('initiatorUID')
402
+            ->setNote('The note')
403
+            ->setLabel('A label')
404
+            ->setNode($file)
405
+            ->setTarget("/$filename")
406
+            ->setToken('token');
407
+
408
+        $this->appConfig
409
+            ->expects($this->once())
410
+            ->method('getValueString')
411
+            ->with('core', 'shareapi_public_link_disclaimertext', '')
412
+            ->willReturn('My disclaimer text');
413
+
414
+        $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
415
+        $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
416
+
417
+        $this->urlGenerator->expects(self::atLeastOnce())
418
+            ->method('linkToRouteAbsolute')
419
+            ->willReturnMap([
420
+                // every file has the show show share url in the opengraph url prop
421
+                ['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
422
+                // there is no preview or folders so no other link for opengraph
423
+            ]);
424
+
425
+        $this->config->method('getSystemValue')
426
+            ->willReturnMap(
427
+                [
428
+                    ['max_filesize_animated_gifs_public_sharing', 10, 10],
429
+                    ['enable_previews', true, true],
430
+                    ['preview_max_x', 1024, 1024],
431
+                    ['preview_max_y', 1024, 1024],
432
+                ]
433
+            );
434
+
435
+        $this->shareManager
436
+            ->expects($this->once())
437
+            ->method('getShareByToken')
438
+            ->with('token')
439
+            ->willReturn($share);
440
+
441
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
442
+            if ($uid === 'ownerUID') {
443
+                return $owner;
444
+            }
445
+            if ($uid === 'initiatorUID') {
446
+                return $initiator;
447
+            }
448
+            return null;
449
+        });
450
+
451
+        $this->eventDispatcher->method('dispatchTyped')->with(
452
+            $this->callback(function ($event) use ($share) {
453
+                if ($event instanceof BeforeTemplateRenderedEvent) {
454
+                    return $event->getShare() === $share;
455
+                } else {
456
+                    return true;
457
+                }
458
+            })
459
+        );
460
+
461
+        $this->l10n->expects($this->any())
462
+            ->method('t')
463
+            ->willReturnCallback(function ($text, $parameters) {
464
+                return vsprintf($text, $parameters);
465
+            });
466
+
467
+        // Set up initial state
468
+        $initialState = [];
469
+        $this->initialState->expects(self::any())
470
+            ->method('provideInitialState')
471
+            ->willReturnCallback(function ($key, $value) use (&$initialState): void {
472
+                $initialState[$key] = $value;
473
+            });
474
+        $expectedInitialState = [
475
+            'isPublic' => true,
476
+            'sharingToken' => 'token',
477
+            'sharePermissions' => Constants::PERMISSION_CREATE,
478
+            'filename' => $filename,
479
+            'view' => 'public-file-drop',
480
+            'disclaimer' => 'My disclaimer text',
481
+            'owner' => 'ownerUID',
482
+            'ownerDisplayName' => 'ownerDisplay',
483
+            'note' => 'The note',
484
+            'label' => 'A label',
485
+        ];
486
+
487
+        $response = $this->shareController->showShare();
488
+
489
+        $this->assertEquals($expectedInitialState, $initialState);
490
+
491
+        $csp = new ContentSecurityPolicy();
492
+        $csp->addAllowedFrameDomain('\'self\'');
493
+        $expectedResponse = new PublicTemplateResponse('files', 'index');
494
+        $expectedResponse->setParams(['pageTitle' => 'A label']);
495
+        $expectedResponse->setContentSecurityPolicy($csp);
496
+        $expectedResponse->setHeaderTitle('A label');
497
+        $expectedResponse->setHeaderDetails('shared by ownerDisplay');
498
+        $expectedResponse->setHeaderActions([
499
+            new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'shareUrl'),
500
+        ]);
501
+
502
+        $this->assertEquals($expectedResponse, $response);
503
+    }
504
+
505
+    public function testShowShareWithPrivateName(): void {
506
+        $note = 'personal note';
507
+        $filename = 'file1.txt';
508
+
509
+        $this->shareController->setToken('token');
510
+
511
+        $owner = $this->createMock(IUser::class);
512
+        $owner->method('getDisplayName')->willReturn('ownerDisplay');
513
+        $owner->method('getUID')->willReturn('ownerUID');
514
+        $owner->method('isEnabled')->willReturn(true);
515
+
516
+        $initiator = $this->createMock(IUser::class);
517
+        $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
518
+        $initiator->method('getUID')->willReturn('initiatorUID');
519
+        $initiator->method('isEnabled')->willReturn(true);
520
+
521
+        $file = $this->createMock(File::class);
522
+        $file->method('getName')->willReturn($filename);
523
+        $file->method('getMimetype')->willReturn('text/plain');
524
+        $file->method('getSize')->willReturn(33);
525
+        $file->method('isReadable')->willReturn(true);
526
+        $file->method('isShareable')->willReturn(true);
527
+        $file->method('getId')->willReturn(111);
528
+
529
+        $accountName = $this->createMock(IAccountProperty::class);
530
+        $accountName->method('getScope')
531
+            ->willReturn(IAccountManager::SCOPE_LOCAL);
532
+        $account = $this->createMock(IAccount::class);
533
+        $account->method('getProperty')
534
+            ->with(IAccountManager::PROPERTY_DISPLAYNAME)
535
+            ->willReturn($accountName);
536
+        $this->accountManager->expects($this->once())
537
+            ->method('getAccount')
538
+            ->with($owner)
539
+            ->willReturn($account);
540
+
541
+        /** @var IShare */
542
+        $share = Server::get(Manager::class)->newShare();
543
+        $share->setId(42);
544
+        $share->setPassword('password')
545
+            ->setShareOwner('ownerUID')
546
+            ->setSharedBy('initiatorUID')
547
+            ->setNode($file)
548
+            ->setNote($note)
549
+            ->setToken('token')
550
+            ->setPermissions(Constants::PERMISSION_ALL & ~Constants::PERMISSION_SHARE)
551
+            ->setTarget("/$filename");
552
+
553
+        $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
554
+        $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
555
+
556
+        $this->urlGenerator->expects(self::atLeast(2))
557
+            ->method('linkToRouteAbsolute')
558
+            ->willReturnMap([
559
+                // every file has the show show share url in the opengraph url prop
560
+                ['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
561
+                // this share is not an image to the default preview is used
562
+                ['files_sharing.PublicPreview.getPreview', ['x' => 256, 'y' => 256, 'file' => $share->getTarget(), 'token' => 'token'], 'previewUrl'],
563
+            ]);
564
+
565
+        $this->urlGenerator->expects($this->once())
566
+            ->method('getAbsoluteURL')
567
+            ->willReturnMap([
568
+                ['/public.php/dav/files/token/?accept=zip', 'downloadUrl'],
569
+            ]);
570
+
571
+        $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
572
+
573
+        $this->config->method('getSystemValue')
574
+            ->willReturnMap(
575
+                [
576
+                    ['max_filesize_animated_gifs_public_sharing', 10, 10],
577
+                    ['enable_previews', true, true],
578
+                    ['preview_max_x', 1024, 1024],
579
+                    ['preview_max_y', 1024, 1024],
580
+                ]
581
+            );
582
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
583
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
584
+
585
+        $this->shareManager
586
+            ->expects($this->once())
587
+            ->method('getShareByToken')
588
+            ->with('token')
589
+            ->willReturn($share);
590
+
591
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
592
+            if ($uid === 'ownerUID') {
593
+                return $owner;
594
+            }
595
+            if ($uid === 'initiatorUID') {
596
+                return $initiator;
597
+            }
598
+            return null;
599
+        });
600
+
601
+        $this->eventDispatcher->method('dispatchTyped')->with(
602
+            $this->callback(function ($event) use ($share) {
603
+                if ($event instanceof BeforeTemplateRenderedEvent) {
604
+                    return $event->getShare() === $share;
605
+                } else {
606
+                    return true;
607
+                }
608
+            })
609
+        );
610
+
611
+        $this->l10n->expects($this->any())
612
+            ->method('t')
613
+            ->will($this->returnCallback(function ($text, $parameters) {
614
+                return vsprintf($text, $parameters);
615
+            }));
616
+
617
+        $this->defaults->expects(self::any())
618
+            ->method('getProductName')
619
+            ->willReturn('Nextcloud');
620
+
621
+        $response = $this->shareController->showShare();
622
+
623
+        $csp = new ContentSecurityPolicy();
624
+        $csp->addAllowedFrameDomain('\'self\'');
625
+        $expectedResponse = new PublicTemplateResponse('files', 'index');
626
+        $expectedResponse->setParams(['pageTitle' => $filename]);
627
+        $expectedResponse->setContentSecurityPolicy($csp);
628
+        $expectedResponse->setHeaderTitle($filename);
629
+        $expectedResponse->setHeaderDetails('');
630
+        $expectedResponse->setHeaderActions([
631
+            new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', 'downloadUrl', 0, '33'),
632
+            new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', 'owner', 'ownerDisplay', $filename),
633
+            new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'downloadUrl'),
634
+        ]);
635
+
636
+        $this->assertEquals($expectedResponse, $response);
637
+    }
638
+
639
+
640
+    public function testShowShareInvalid(): void {
641
+        $this->expectException(NotFoundException::class);
642
+
643
+        $filename = 'file1.txt';
644
+        $this->shareController->setToken('token');
645
+
646
+        $owner = $this->getMockBuilder(IUser::class)->getMock();
647
+        $owner->method('getDisplayName')->willReturn('ownerDisplay');
648
+        $owner->method('getUID')->willReturn('ownerUID');
649
+
650
+        $file = $this->getMockBuilder('OCP\Files\File')->getMock();
651
+        $file->method('getName')->willReturn($filename);
652
+        $file->method('getMimetype')->willReturn('text/plain');
653
+        $file->method('getSize')->willReturn(33);
654
+        $file->method('isShareable')->willReturn(false);
655
+        $file->method('isReadable')->willReturn(true);
656
+
657
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
658
+        $share->setId(42);
659
+        $share->setPassword('password')
660
+            ->setShareOwner('ownerUID')
661
+            ->setNode($file)
662
+            ->setTarget("/$filename");
663
+
664
+        $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
665
+        $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
666
+
667
+        $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
668
+
669
+        $this->config->method('getSystemValue')
670
+            ->willReturnMap(
671
+                [
672
+                    ['max_filesize_animated_gifs_public_sharing', 10, 10],
673
+                    ['enable_previews', true, true],
674
+                ]
675
+            );
676
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
677
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
678
+
679
+        $this->shareManager
680
+            ->expects($this->once())
681
+            ->method('getShareByToken')
682
+            ->with('token')
683
+            ->willReturn($share);
684
+
685
+        $this->userManager->method('get')->with('ownerUID')->willReturn($owner);
686
+
687
+        $this->shareController->showShare();
688
+    }
689
+
690
+    public function testDownloadShareWithCreateOnlyShare(): void {
691
+        $share = $this->getMockBuilder(IShare::class)->getMock();
692
+        $share->method('getPassword')->willReturn('password');
693
+        $share
694
+            ->expects($this->once())
695
+            ->method('getPermissions')
696
+            ->willReturn(Constants::PERMISSION_CREATE);
697
+
698
+        $this->shareManager
699
+            ->expects($this->once())
700
+            ->method('getShareByToken')
701
+            ->with('validtoken')
702
+            ->willReturn($share);
703
+
704
+        // Test with a password protected share and no authentication
705
+        $response = $this->shareController->downloadShare('validtoken');
706
+        $expectedResponse = new DataResponse('Share has no read permission');
707
+        $this->assertEquals($expectedResponse, $response);
708
+    }
709
+
710
+    public function testDownloadShareWithoutDownloadPermission(): void {
711
+        $attributes = $this->createMock(IAttributes::class);
712
+        $attributes->expects(self::once())
713
+            ->method('getAttribute')
714
+            ->with('permissions', 'download')
715
+            ->willReturn(false);
716
+
717
+        $share = $this->createMock(IShare::class);
718
+        $share->method('getPassword')->willReturn('password');
719
+        $share->expects(self::once())
720
+            ->method('getPermissions')
721
+            ->willReturn(Constants::PERMISSION_READ);
722
+        $share->expects(self::once())
723
+            ->method('getAttributes')
724
+            ->willReturn($attributes);
725
+
726
+        $this->shareManager
727
+            ->expects(self::once())
728
+            ->method('getShareByToken')
729
+            ->with('validtoken')
730
+            ->willReturn($share);
731
+
732
+        // Test with a password protected share and no authentication
733
+        $response = $this->shareController->downloadShare('validtoken');
734
+        $expectedResponse = new DataResponse('Share has no download permission');
735
+        $this->assertEquals($expectedResponse, $response);
736
+    }
737
+
738
+    public function testDisabledOwner(): void {
739
+        $this->shareController->setToken('token');
740
+
741
+        $owner = $this->getMockBuilder(IUser::class)->getMock();
742
+        $owner->method('isEnabled')->willReturn(false);
743
+
744
+        $initiator = $this->createMock(IUser::class);
745
+        $initiator->method('isEnabled')->willReturn(false);
746
+
747
+        /* @var MockObject|Folder $folder */
748
+        $folder = $this->createMock(Folder::class);
749
+
750
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
751
+        $share->setId(42);
752
+        $share->setPermissions(Constants::PERMISSION_CREATE)
753
+            ->setShareOwner('ownerUID')
754
+            ->setSharedBy('initiatorUID')
755
+            ->setNode($folder)
756
+            ->setTarget('/share');
757
+
758
+        $this->shareManager
759
+            ->expects($this->once())
760
+            ->method('getShareByToken')
761
+            ->with('token')
762
+            ->willReturn($share);
763
+
764
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
765
+            if ($uid === 'ownerUID') {
766
+                return $owner;
767
+            }
768
+            if ($uid === 'initiatorUID') {
769
+                return $initiator;
770
+            }
771
+            return null;
772
+        });
773
+
774
+        $this->expectException(NotFoundException::class);
775
+
776
+        $this->shareController->showShare();
777
+    }
778
+
779
+    public function testDisabledInitiator(): void {
780
+        $this->shareController->setToken('token');
781
+
782
+        $owner = $this->getMockBuilder(IUser::class)->getMock();
783
+        $owner->method('isEnabled')->willReturn(false);
784
+
785
+        $initiator = $this->createMock(IUser::class);
786
+        $initiator->method('isEnabled')->willReturn(true);
787
+
788
+        /* @var MockObject|Folder $folder */
789
+        $folder = $this->createMock(Folder::class);
790
+
791
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
792
+        $share->setId(42);
793
+        $share->setPermissions(Constants::PERMISSION_CREATE)
794
+            ->setShareOwner('ownerUID')
795
+            ->setSharedBy('initiatorUID')
796
+            ->setNode($folder)
797
+            ->setTarget('/share');
798
+
799
+        $this->shareManager
800
+            ->expects($this->once())
801
+            ->method('getShareByToken')
802
+            ->with('token')
803
+            ->willReturn($share);
804
+
805
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
806
+            if ($uid === 'ownerUID') {
807
+                return $owner;
808
+            }
809
+            if ($uid === 'initiatorUID') {
810
+                return $initiator;
811
+            }
812
+            return null;
813
+        });
814
+
815
+        $this->expectException(NotFoundException::class);
816
+
817
+        $this->shareController->showShare();
818
+    }
819 819
 }
Please login to merge, or discard this patch.