Completed
Push — master ( d20e4d...57e0ff )
by John
18:50 queued 14s
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
-		}
95
-		// Set up initial state
96
-		$this->initialState->provideInitialState('isPublic', true);
97
-		$this->initialState->provideInitialState('sharingToken', $token);
98
-		$this->initialState->provideInitialState('sharePermissions', $share->getPermissions());
99
-		$this->initialState->provideInitialState('filename', $shareNode->getName());
100
-		$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
+        }
95
+        // Set up initial state
96
+        $this->initialState->provideInitialState('isPublic', true);
97
+        $this->initialState->provideInitialState('sharingToken', $token);
98
+        $this->initialState->provideInitialState('sharePermissions', $share->getPermissions());
99
+        $this->initialState->provideInitialState('filename', $shareNode->getName());
100
+        $this->initialState->provideInitialState('view', $view);
101 101
 
102
-		// Load scripts and styles for UI
103
-		Util::addInitScript('files', 'init');
104
-		Util::addInitScript(Application::APP_ID, 'init');
105
-		Util::addInitScript(Application::APP_ID, 'init-public');
106
-		Util::addScript('files', 'main');
102
+        // Load scripts and styles for UI
103
+        Util::addInitScript('files', 'init');
104
+        Util::addInitScript(Application::APP_ID, 'init');
105
+        Util::addInitScript(Application::APP_ID, 'init-public');
106
+        Util::addScript('files', 'main');
107 107
 
108
-		// Add file-request script if needed
109
-		$attributes = $share->getAttributes();
110
-		$isFileRequest = $attributes?->getAttribute('fileRequest', 'enabled') === true;
111
-		if ($isFileRequest) {
112
-			Util::addScript(Application::APP_ID, 'public-file-request');
113
-		}
108
+        // Add file-request script if needed
109
+        $attributes = $share->getAttributes();
110
+        $isFileRequest = $attributes?->getAttribute('fileRequest', 'enabled') === true;
111
+        if ($isFileRequest) {
112
+            Util::addScript(Application::APP_ID, 'public-file-request');
113
+        }
114 114
 
115
-		// Load Viewer scripts
116
-		if (class_exists(LoadViewer::class)) {
117
-			$this->eventDispatcher->dispatchTyped(new LoadViewer());
118
-		}
115
+        // Load Viewer scripts
116
+        if (class_exists(LoadViewer::class)) {
117
+            $this->eventDispatcher->dispatchTyped(new LoadViewer());
118
+        }
119 119
 
120
-		// Allow external apps to register their scripts
121
-		$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
120
+        // Allow external apps to register their scripts
121
+        $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
122 122
 
123
-		$this->addMetaHeaders($share);
123
+        $this->addMetaHeaders($share);
124 124
 
125
-		// CSP to allow office
126
-		$csp = new ContentSecurityPolicy();
127
-		$csp->addAllowedFrameDomain('\'self\'');
125
+        // CSP to allow office
126
+        $csp = new ContentSecurityPolicy();
127
+        $csp->addAllowedFrameDomain('\'self\'');
128 128
 
129
-		$response = new PublicTemplateResponse(
130
-			'files',
131
-			'index',
132
-		);
133
-		$response->setContentSecurityPolicy($csp);
129
+        $response = new PublicTemplateResponse(
130
+            'files',
131
+            'index',
132
+        );
133
+        $response->setContentSecurityPolicy($csp);
134 134
 
135
-		// If the share has a label, use it as the title
136
-		if ($share->getLabel() !== '') {
137
-			$response->setHeaderTitle($share->getLabel());
138
-			$response->setParams(['pageTitle' => $share->getLabel()]);
139
-		} else {
140
-			$response->setHeaderTitle($shareNode->getName());
141
-			$response->setParams(['pageTitle' => $shareNode->getName()]);
142
-		}
135
+        // If the share has a label, use it as the title
136
+        if ($share->getLabel() !== '') {
137
+            $response->setHeaderTitle($share->getLabel());
138
+            $response->setParams(['pageTitle' => $share->getLabel()]);
139
+        } else {
140
+            $response->setHeaderTitle($shareNode->getName());
141
+            $response->setParams(['pageTitle' => $shareNode->getName()]);
142
+        }
143 143
 
144
-		if ($ownerName !== '') {
145
-			$response->setHeaderDetails($this->l10n->t('shared by %s', [$ownerName]));
146
-		}
144
+        if ($ownerName !== '') {
145
+            $response->setHeaderDetails($this->l10n->t('shared by %s', [$ownerName]));
146
+        }
147 147
 
148
-		// Create the header action menu
149
-		$headerActions = [];
150
-		if ($view !== 'public-file-drop' && !$share->getHideDownload()) {
151
-			// The download URL is used for the "download" header action as well as in some cases for the direct link
152
-			$downloadUrl = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', [
153
-				'token' => $token,
154
-				'filename' => ($shareNode instanceof File) ? $shareNode->getName() : null,
155
-			]);
148
+        // Create the header action menu
149
+        $headerActions = [];
150
+        if ($view !== 'public-file-drop' && !$share->getHideDownload()) {
151
+            // The download URL is used for the "download" header action as well as in some cases for the direct link
152
+            $downloadUrl = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', [
153
+                'token' => $token,
154
+                'filename' => ($shareNode instanceof File) ? $shareNode->getName() : null,
155
+            ]);
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   +750 added lines, -750 removed lines patch added patch discarded remove patch
@@ -54,754 +54,754 @@
 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
-				// for the direct link
265
-				['files_sharing.sharecontroller.downloadShare', ['token' => 'token', 'filename' => $filename ], 'downloadUrl'],
266
-			]);
267
-
268
-		$this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
269
-
270
-		$this->config->method('getSystemValue')
271
-			->willReturnMap(
272
-				[
273
-					['max_filesize_animated_gifs_public_sharing', 10, 10],
274
-					['enable_previews', true, true],
275
-					['preview_max_x', 1024, 1024],
276
-					['preview_max_y', 1024, 1024],
277
-				]
278
-			);
279
-
280
-		$this->shareManager
281
-			->expects($this->once())
282
-			->method('getShareByToken')
283
-			->with('token')
284
-			->willReturn($share);
285
-
286
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
287
-			if ($uid === 'ownerUID') {
288
-				return $owner;
289
-			}
290
-			if ($uid === 'initiatorUID') {
291
-				return $initiator;
292
-			}
293
-			return null;
294
-		});
295
-
296
-		$this->eventDispatcher->method('dispatchTyped')->with(
297
-			$this->callback(function ($event) use ($share) {
298
-				if ($event instanceof BeforeTemplateRenderedEvent) {
299
-					return $event->getShare() === $share;
300
-				} else {
301
-					return true;
302
-				}
303
-			})
304
-		);
305
-
306
-		$this->l10n->expects($this->any())
307
-			->method('t')
308
-			->willReturnCallback(function ($text, $parameters) {
309
-				return vsprintf($text, $parameters);
310
-			});
311
-
312
-		$this->defaults->expects(self::any())
313
-			->method('getProductName')
314
-			->willReturn('Nextcloud');
315
-
316
-		// Ensure the correct initial state is setup
317
-		// Shared node is a file so this is a single file share:
318
-		$view = 'public-file-share';
319
-		// Set up initial state
320
-		$initialState = [];
321
-		$this->initialState->expects(self::any())
322
-			->method('provideInitialState')
323
-			->willReturnCallback(function ($key, $value) use (&$initialState): void {
324
-				$initialState[$key] = $value;
325
-			});
326
-		$expectedInitialState = [
327
-			'isPublic' => true,
328
-			'sharingToken' => 'token',
329
-			'sharePermissions' => (Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE),
330
-			'filename' => $filename,
331
-			'view' => $view,
332
-			'fileId' => 111,
333
-			'owner' => 'ownerUID',
334
-			'ownerDisplayName' => 'ownerDisplay',
335
-		];
336
-
337
-		$response = $this->shareController->showShare();
338
-
339
-		$this->assertEquals($expectedInitialState, $initialState);
340
-
341
-		$csp = new ContentSecurityPolicy();
342
-		$csp->addAllowedFrameDomain('\'self\'');
343
-		$expectedResponse = new PublicTemplateResponse('files', 'index');
344
-		$expectedResponse->setParams(['pageTitle' => $filename]);
345
-		$expectedResponse->setContentSecurityPolicy($csp);
346
-		$expectedResponse->setHeaderTitle($filename);
347
-		$expectedResponse->setHeaderDetails('shared by ownerDisplay');
348
-		$expectedResponse->setHeaderActions([
349
-			new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', 'downloadUrl', 0, '33'),
350
-			new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', 'owner', 'ownerDisplay', $filename),
351
-			new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'downloadUrl'),
352
-		]);
353
-
354
-		$this->assertEquals($expectedResponse, $response);
355
-	}
356
-
357
-	public function testShowFileDropShare(): void {
358
-		$filename = 'folder1';
359
-
360
-		$this->shareController->setToken('token');
361
-
362
-		$owner = $this->createMock(IUser::class);
363
-		$owner->method('getDisplayName')->willReturn('ownerDisplay');
364
-		$owner->method('getUID')->willReturn('ownerUID');
365
-		$owner->method('isEnabled')->willReturn(true);
366
-
367
-		$initiator = $this->createMock(IUser::class);
368
-		$initiator->method('getDisplayName')->willReturn('initiatorDisplay');
369
-		$initiator->method('getUID')->willReturn('initiatorUID');
370
-		$initiator->method('isEnabled')->willReturn(true);
371
-
372
-		$file = $this->createMock(Folder::class);
373
-		$file->method('isReadable')->willReturn(true);
374
-		$file->method('isShareable')->willReturn(true);
375
-		$file->method('getId')->willReturn(1234);
376
-		$file->method('getName')->willReturn($filename);
377
-
378
-		$accountName = $this->createMock(IAccountProperty::class);
379
-		$accountName->method('getScope')
380
-			->willReturn(IAccountManager::SCOPE_PUBLISHED);
381
-		$account = $this->createMock(IAccount::class);
382
-		$account->method('getProperty')
383
-			->with(IAccountManager::PROPERTY_DISPLAYNAME)
384
-			->willReturn($accountName);
385
-		$this->accountManager->expects($this->once())
386
-			->method('getAccount')
387
-			->with($owner)
388
-			->willReturn($account);
389
-
390
-		/** @var Manager */
391
-		$manager = Server::get(Manager::class);
392
-		$share = $manager->newShare();
393
-		$share->setId(42)
394
-			->setPermissions(Constants::PERMISSION_CREATE)
395
-			->setPassword('password')
396
-			->setShareOwner('ownerUID')
397
-			->setSharedBy('initiatorUID')
398
-			->setNode($file)
399
-			->setTarget("/$filename")
400
-			->setToken('token');
401
-
402
-		$this->appConfig
403
-			->expects($this->once())
404
-			->method('getValueString')
405
-			->with('core', 'shareapi_public_link_disclaimertext', '')
406
-			->willReturn('My disclaimer text');
407
-
408
-		$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
409
-		$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
410
-
411
-		$this->urlGenerator->expects(self::atLeastOnce())
412
-			->method('linkToRouteAbsolute')
413
-			->willReturnMap([
414
-				// every file has the show show share url in the opengraph url prop
415
-				['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
416
-				// there is no preview or folders so no other link for opengraph
417
-			]);
418
-
419
-		$this->config->method('getSystemValue')
420
-			->willReturnMap(
421
-				[
422
-					['max_filesize_animated_gifs_public_sharing', 10, 10],
423
-					['enable_previews', true, true],
424
-					['preview_max_x', 1024, 1024],
425
-					['preview_max_y', 1024, 1024],
426
-				]
427
-			);
428
-
429
-		$this->shareManager
430
-			->expects($this->once())
431
-			->method('getShareByToken')
432
-			->with('token')
433
-			->willReturn($share);
434
-
435
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
436
-			if ($uid === 'ownerUID') {
437
-				return $owner;
438
-			}
439
-			if ($uid === 'initiatorUID') {
440
-				return $initiator;
441
-			}
442
-			return null;
443
-		});
444
-
445
-		$this->eventDispatcher->method('dispatchTyped')->with(
446
-			$this->callback(function ($event) use ($share) {
447
-				if ($event instanceof BeforeTemplateRenderedEvent) {
448
-					return $event->getShare() === $share;
449
-				} else {
450
-					return true;
451
-				}
452
-			})
453
-		);
454
-
455
-		$this->l10n->expects($this->any())
456
-			->method('t')
457
-			->willReturnCallback(function ($text, $parameters) {
458
-				return vsprintf($text, $parameters);
459
-			});
460
-
461
-		// Set up initial state
462
-		$initialState = [];
463
-		$this->initialState->expects(self::any())
464
-			->method('provideInitialState')
465
-			->willReturnCallback(function ($key, $value) use (&$initialState): void {
466
-				$initialState[$key] = $value;
467
-			});
468
-		$expectedInitialState = [
469
-			'isPublic' => true,
470
-			'sharingToken' => 'token',
471
-			'sharePermissions' => Constants::PERMISSION_CREATE,
472
-			'filename' => $filename,
473
-			'view' => 'public-file-drop',
474
-			'disclaimer' => 'My disclaimer text',
475
-			'owner' => 'ownerUID',
476
-			'ownerDisplayName' => 'ownerDisplay',
477
-		];
478
-
479
-		$response = $this->shareController->showShare();
480
-
481
-		$this->assertEquals($expectedInitialState, $initialState);
482
-
483
-		$csp = new ContentSecurityPolicy();
484
-		$csp->addAllowedFrameDomain('\'self\'');
485
-		$expectedResponse = new PublicTemplateResponse('files', 'index');
486
-		$expectedResponse->setParams(['pageTitle' => $filename]);
487
-		$expectedResponse->setContentSecurityPolicy($csp);
488
-		$expectedResponse->setHeaderTitle($filename);
489
-		$expectedResponse->setHeaderDetails('shared by ownerDisplay');
490
-		$expectedResponse->setHeaderActions([
491
-			new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'shareUrl'),
492
-		]);
493
-
494
-		$this->assertEquals($expectedResponse, $response);
495
-	}
496
-
497
-	public function testShowShareWithPrivateName(): void {
498
-		$note = 'personal note';
499
-		$filename = 'file1.txt';
500
-
501
-		$this->shareController->setToken('token');
502
-
503
-		$owner = $this->createMock(IUser::class);
504
-		$owner->method('getDisplayName')->willReturn('ownerDisplay');
505
-		$owner->method('getUID')->willReturn('ownerUID');
506
-		$owner->method('isEnabled')->willReturn(true);
507
-
508
-		$initiator = $this->createMock(IUser::class);
509
-		$initiator->method('getDisplayName')->willReturn('initiatorDisplay');
510
-		$initiator->method('getUID')->willReturn('initiatorUID');
511
-		$initiator->method('isEnabled')->willReturn(true);
512
-
513
-		$file = $this->createMock(File::class);
514
-		$file->method('getName')->willReturn($filename);
515
-		$file->method('getMimetype')->willReturn('text/plain');
516
-		$file->method('getSize')->willReturn(33);
517
-		$file->method('isReadable')->willReturn(true);
518
-		$file->method('isShareable')->willReturn(true);
519
-		$file->method('getId')->willReturn(111);
520
-
521
-		$accountName = $this->createMock(IAccountProperty::class);
522
-		$accountName->method('getScope')
523
-			->willReturn(IAccountManager::SCOPE_LOCAL);
524
-		$account = $this->createMock(IAccount::class);
525
-		$account->method('getProperty')
526
-			->with(IAccountManager::PROPERTY_DISPLAYNAME)
527
-			->willReturn($accountName);
528
-		$this->accountManager->expects($this->once())
529
-			->method('getAccount')
530
-			->with($owner)
531
-			->willReturn($account);
532
-
533
-		/** @var IShare */
534
-		$share = Server::get(Manager::class)->newShare();
535
-		$share->setId(42);
536
-		$share->setPassword('password')
537
-			->setShareOwner('ownerUID')
538
-			->setSharedBy('initiatorUID')
539
-			->setNode($file)
540
-			->setNote($note)
541
-			->setToken('token')
542
-			->setPermissions(Constants::PERMISSION_ALL & ~Constants::PERMISSION_SHARE)
543
-			->setTarget("/$filename");
544
-
545
-		$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
546
-		$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
547
-
548
-		$this->urlGenerator->expects(self::atLeast(2))
549
-			->method('linkToRouteAbsolute')
550
-			->willReturnMap([
551
-				// every file has the show show share url in the opengraph url prop
552
-				['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
553
-				// this share is not an image to the default preview is used
554
-				['files_sharing.PublicPreview.getPreview', ['x' => 256, 'y' => 256, 'file' => $share->getTarget(), 'token' => 'token'], 'previewUrl'],
555
-				// for the direct link
556
-				['files_sharing.sharecontroller.downloadShare', ['token' => 'token', 'filename' => $filename ], 'downloadUrl'],
557
-			]);
558
-
559
-		$this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
560
-
561
-		$this->config->method('getSystemValue')
562
-			->willReturnMap(
563
-				[
564
-					['max_filesize_animated_gifs_public_sharing', 10, 10],
565
-					['enable_previews', true, true],
566
-					['preview_max_x', 1024, 1024],
567
-					['preview_max_y', 1024, 1024],
568
-				]
569
-			);
570
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
571
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
572
-
573
-		$this->shareManager
574
-			->expects($this->once())
575
-			->method('getShareByToken')
576
-			->with('token')
577
-			->willReturn($share);
578
-
579
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
580
-			if ($uid === 'ownerUID') {
581
-				return $owner;
582
-			}
583
-			if ($uid === 'initiatorUID') {
584
-				return $initiator;
585
-			}
586
-			return null;
587
-		});
588
-
589
-		$this->eventDispatcher->method('dispatchTyped')->with(
590
-			$this->callback(function ($event) use ($share) {
591
-				if ($event instanceof BeforeTemplateRenderedEvent) {
592
-					return $event->getShare() === $share;
593
-				} else {
594
-					return true;
595
-				}
596
-			})
597
-		);
598
-
599
-		$this->l10n->expects($this->any())
600
-			->method('t')
601
-			->will($this->returnCallback(function ($text, $parameters) {
602
-				return vsprintf($text, $parameters);
603
-			}));
604
-
605
-		$this->defaults->expects(self::any())
606
-			->method('getProductName')
607
-			->willReturn('Nextcloud');
608
-
609
-		$response = $this->shareController->showShare();
610
-
611
-		$csp = new ContentSecurityPolicy();
612
-		$csp->addAllowedFrameDomain('\'self\'');
613
-		$expectedResponse = new PublicTemplateResponse('files', 'index');
614
-		$expectedResponse->setParams(['pageTitle' => $filename]);
615
-		$expectedResponse->setContentSecurityPolicy($csp);
616
-		$expectedResponse->setHeaderTitle($filename);
617
-		$expectedResponse->setHeaderDetails('');
618
-		$expectedResponse->setHeaderActions([
619
-			new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', 'downloadUrl', 0, '33'),
620
-			new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', 'owner', 'ownerDisplay', $filename),
621
-			new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'downloadUrl'),
622
-		]);
623
-
624
-		$this->assertEquals($expectedResponse, $response);
625
-	}
626
-
627
-
628
-	public function testShowShareInvalid(): void {
629
-		$this->expectException(NotFoundException::class);
630
-
631
-		$filename = 'file1.txt';
632
-		$this->shareController->setToken('token');
633
-
634
-		$owner = $this->getMockBuilder(IUser::class)->getMock();
635
-		$owner->method('getDisplayName')->willReturn('ownerDisplay');
636
-		$owner->method('getUID')->willReturn('ownerUID');
637
-
638
-		$file = $this->getMockBuilder('OCP\Files\File')->getMock();
639
-		$file->method('getName')->willReturn($filename);
640
-		$file->method('getMimetype')->willReturn('text/plain');
641
-		$file->method('getSize')->willReturn(33);
642
-		$file->method('isShareable')->willReturn(false);
643
-		$file->method('isReadable')->willReturn(true);
644
-
645
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
646
-		$share->setId(42);
647
-		$share->setPassword('password')
648
-			->setShareOwner('ownerUID')
649
-			->setNode($file)
650
-			->setTarget("/$filename");
651
-
652
-		$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
653
-		$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
654
-
655
-		$this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
656
-
657
-		$this->config->method('getSystemValue')
658
-			->willReturnMap(
659
-				[
660
-					['max_filesize_animated_gifs_public_sharing', 10, 10],
661
-					['enable_previews', true, true],
662
-				]
663
-			);
664
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
665
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
666
-
667
-		$this->shareManager
668
-			->expects($this->once())
669
-			->method('getShareByToken')
670
-			->with('token')
671
-			->willReturn($share);
672
-
673
-		$this->userManager->method('get')->with('ownerUID')->willReturn($owner);
674
-
675
-		$this->shareController->showShare();
676
-	}
677
-
678
-	public function testDownloadShareWithCreateOnlyShare(): void {
679
-		$share = $this->getMockBuilder(IShare::class)->getMock();
680
-		$share->method('getPassword')->willReturn('password');
681
-		$share
682
-			->expects($this->once())
683
-			->method('getPermissions')
684
-			->willReturn(Constants::PERMISSION_CREATE);
685
-
686
-		$this->shareManager
687
-			->expects($this->once())
688
-			->method('getShareByToken')
689
-			->with('validtoken')
690
-			->willReturn($share);
691
-
692
-		// Test with a password protected share and no authentication
693
-		$response = $this->shareController->downloadShare('validtoken');
694
-		$expectedResponse = new DataResponse('Share has no read permission');
695
-		$this->assertEquals($expectedResponse, $response);
696
-	}
697
-
698
-	public function testDownloadShareWithoutDownloadPermission(): void {
699
-		$attributes = $this->createMock(IAttributes::class);
700
-		$attributes->expects(self::once())
701
-			->method('getAttribute')
702
-			->with('permissions', 'download')
703
-			->willReturn(false);
704
-
705
-		$share = $this->createMock(IShare::class);
706
-		$share->method('getPassword')->willReturn('password');
707
-		$share->expects(self::once())
708
-			->method('getPermissions')
709
-			->willReturn(Constants::PERMISSION_READ);
710
-		$share->expects(self::once())
711
-			->method('getAttributes')
712
-			->willReturn($attributes);
713
-
714
-		$this->shareManager
715
-			->expects(self::once())
716
-			->method('getShareByToken')
717
-			->with('validtoken')
718
-			->willReturn($share);
719
-
720
-		// Test with a password protected share and no authentication
721
-		$response = $this->shareController->downloadShare('validtoken');
722
-		$expectedResponse = new DataResponse('Share has no download permission');
723
-		$this->assertEquals($expectedResponse, $response);
724
-	}
725
-
726
-	public function testDisabledOwner(): void {
727
-		$this->shareController->setToken('token');
728
-
729
-		$owner = $this->getMockBuilder(IUser::class)->getMock();
730
-		$owner->method('isEnabled')->willReturn(false);
731
-
732
-		$initiator = $this->createMock(IUser::class);
733
-		$initiator->method('isEnabled')->willReturn(false);
734
-
735
-		/* @var MockObject|Folder $folder */
736
-		$folder = $this->createMock(Folder::class);
737
-
738
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
739
-		$share->setId(42);
740
-		$share->setPermissions(Constants::PERMISSION_CREATE)
741
-			->setShareOwner('ownerUID')
742
-			->setSharedBy('initiatorUID')
743
-			->setNode($folder)
744
-			->setTarget('/share');
745
-
746
-		$this->shareManager
747
-			->expects($this->once())
748
-			->method('getShareByToken')
749
-			->with('token')
750
-			->willReturn($share);
751
-
752
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
753
-			if ($uid === 'ownerUID') {
754
-				return $owner;
755
-			}
756
-			if ($uid === 'initiatorUID') {
757
-				return $initiator;
758
-			}
759
-			return null;
760
-		});
761
-
762
-		$this->expectException(NotFoundException::class);
763
-
764
-		$this->shareController->showShare();
765
-	}
766
-
767
-	public function testDisabledInitiator(): void {
768
-		$this->shareController->setToken('token');
769
-
770
-		$owner = $this->getMockBuilder(IUser::class)->getMock();
771
-		$owner->method('isEnabled')->willReturn(false);
772
-
773
-		$initiator = $this->createMock(IUser::class);
774
-		$initiator->method('isEnabled')->willReturn(true);
775
-
776
-		/* @var MockObject|Folder $folder */
777
-		$folder = $this->createMock(Folder::class);
778
-
779
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
780
-		$share->setId(42);
781
-		$share->setPermissions(Constants::PERMISSION_CREATE)
782
-			->setShareOwner('ownerUID')
783
-			->setSharedBy('initiatorUID')
784
-			->setNode($folder)
785
-			->setTarget('/share');
786
-
787
-		$this->shareManager
788
-			->expects($this->once())
789
-			->method('getShareByToken')
790
-			->with('token')
791
-			->willReturn($share);
792
-
793
-		$this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
794
-			if ($uid === 'ownerUID') {
795
-				return $owner;
796
-			}
797
-			if ($uid === 'initiatorUID') {
798
-				return $initiator;
799
-			}
800
-			return null;
801
-		});
802
-
803
-		$this->expectException(NotFoundException::class);
804
-
805
-		$this->shareController->showShare();
806
-	}
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
+                // for the direct link
265
+                ['files_sharing.sharecontroller.downloadShare', ['token' => 'token', 'filename' => $filename ], 'downloadUrl'],
266
+            ]);
267
+
268
+        $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
269
+
270
+        $this->config->method('getSystemValue')
271
+            ->willReturnMap(
272
+                [
273
+                    ['max_filesize_animated_gifs_public_sharing', 10, 10],
274
+                    ['enable_previews', true, true],
275
+                    ['preview_max_x', 1024, 1024],
276
+                    ['preview_max_y', 1024, 1024],
277
+                ]
278
+            );
279
+
280
+        $this->shareManager
281
+            ->expects($this->once())
282
+            ->method('getShareByToken')
283
+            ->with('token')
284
+            ->willReturn($share);
285
+
286
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
287
+            if ($uid === 'ownerUID') {
288
+                return $owner;
289
+            }
290
+            if ($uid === 'initiatorUID') {
291
+                return $initiator;
292
+            }
293
+            return null;
294
+        });
295
+
296
+        $this->eventDispatcher->method('dispatchTyped')->with(
297
+            $this->callback(function ($event) use ($share) {
298
+                if ($event instanceof BeforeTemplateRenderedEvent) {
299
+                    return $event->getShare() === $share;
300
+                } else {
301
+                    return true;
302
+                }
303
+            })
304
+        );
305
+
306
+        $this->l10n->expects($this->any())
307
+            ->method('t')
308
+            ->willReturnCallback(function ($text, $parameters) {
309
+                return vsprintf($text, $parameters);
310
+            });
311
+
312
+        $this->defaults->expects(self::any())
313
+            ->method('getProductName')
314
+            ->willReturn('Nextcloud');
315
+
316
+        // Ensure the correct initial state is setup
317
+        // Shared node is a file so this is a single file share:
318
+        $view = 'public-file-share';
319
+        // Set up initial state
320
+        $initialState = [];
321
+        $this->initialState->expects(self::any())
322
+            ->method('provideInitialState')
323
+            ->willReturnCallback(function ($key, $value) use (&$initialState): void {
324
+                $initialState[$key] = $value;
325
+            });
326
+        $expectedInitialState = [
327
+            'isPublic' => true,
328
+            'sharingToken' => 'token',
329
+            'sharePermissions' => (Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE),
330
+            'filename' => $filename,
331
+            'view' => $view,
332
+            'fileId' => 111,
333
+            'owner' => 'ownerUID',
334
+            'ownerDisplayName' => 'ownerDisplay',
335
+        ];
336
+
337
+        $response = $this->shareController->showShare();
338
+
339
+        $this->assertEquals($expectedInitialState, $initialState);
340
+
341
+        $csp = new ContentSecurityPolicy();
342
+        $csp->addAllowedFrameDomain('\'self\'');
343
+        $expectedResponse = new PublicTemplateResponse('files', 'index');
344
+        $expectedResponse->setParams(['pageTitle' => $filename]);
345
+        $expectedResponse->setContentSecurityPolicy($csp);
346
+        $expectedResponse->setHeaderTitle($filename);
347
+        $expectedResponse->setHeaderDetails('shared by ownerDisplay');
348
+        $expectedResponse->setHeaderActions([
349
+            new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', 'downloadUrl', 0, '33'),
350
+            new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', 'owner', 'ownerDisplay', $filename),
351
+            new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'downloadUrl'),
352
+        ]);
353
+
354
+        $this->assertEquals($expectedResponse, $response);
355
+    }
356
+
357
+    public function testShowFileDropShare(): void {
358
+        $filename = 'folder1';
359
+
360
+        $this->shareController->setToken('token');
361
+
362
+        $owner = $this->createMock(IUser::class);
363
+        $owner->method('getDisplayName')->willReturn('ownerDisplay');
364
+        $owner->method('getUID')->willReturn('ownerUID');
365
+        $owner->method('isEnabled')->willReturn(true);
366
+
367
+        $initiator = $this->createMock(IUser::class);
368
+        $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
369
+        $initiator->method('getUID')->willReturn('initiatorUID');
370
+        $initiator->method('isEnabled')->willReturn(true);
371
+
372
+        $file = $this->createMock(Folder::class);
373
+        $file->method('isReadable')->willReturn(true);
374
+        $file->method('isShareable')->willReturn(true);
375
+        $file->method('getId')->willReturn(1234);
376
+        $file->method('getName')->willReturn($filename);
377
+
378
+        $accountName = $this->createMock(IAccountProperty::class);
379
+        $accountName->method('getScope')
380
+            ->willReturn(IAccountManager::SCOPE_PUBLISHED);
381
+        $account = $this->createMock(IAccount::class);
382
+        $account->method('getProperty')
383
+            ->with(IAccountManager::PROPERTY_DISPLAYNAME)
384
+            ->willReturn($accountName);
385
+        $this->accountManager->expects($this->once())
386
+            ->method('getAccount')
387
+            ->with($owner)
388
+            ->willReturn($account);
389
+
390
+        /** @var Manager */
391
+        $manager = Server::get(Manager::class);
392
+        $share = $manager->newShare();
393
+        $share->setId(42)
394
+            ->setPermissions(Constants::PERMISSION_CREATE)
395
+            ->setPassword('password')
396
+            ->setShareOwner('ownerUID')
397
+            ->setSharedBy('initiatorUID')
398
+            ->setNode($file)
399
+            ->setTarget("/$filename")
400
+            ->setToken('token');
401
+
402
+        $this->appConfig
403
+            ->expects($this->once())
404
+            ->method('getValueString')
405
+            ->with('core', 'shareapi_public_link_disclaimertext', '')
406
+            ->willReturn('My disclaimer text');
407
+
408
+        $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
409
+        $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
410
+
411
+        $this->urlGenerator->expects(self::atLeastOnce())
412
+            ->method('linkToRouteAbsolute')
413
+            ->willReturnMap([
414
+                // every file has the show show share url in the opengraph url prop
415
+                ['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
416
+                // there is no preview or folders so no other link for opengraph
417
+            ]);
418
+
419
+        $this->config->method('getSystemValue')
420
+            ->willReturnMap(
421
+                [
422
+                    ['max_filesize_animated_gifs_public_sharing', 10, 10],
423
+                    ['enable_previews', true, true],
424
+                    ['preview_max_x', 1024, 1024],
425
+                    ['preview_max_y', 1024, 1024],
426
+                ]
427
+            );
428
+
429
+        $this->shareManager
430
+            ->expects($this->once())
431
+            ->method('getShareByToken')
432
+            ->with('token')
433
+            ->willReturn($share);
434
+
435
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
436
+            if ($uid === 'ownerUID') {
437
+                return $owner;
438
+            }
439
+            if ($uid === 'initiatorUID') {
440
+                return $initiator;
441
+            }
442
+            return null;
443
+        });
444
+
445
+        $this->eventDispatcher->method('dispatchTyped')->with(
446
+            $this->callback(function ($event) use ($share) {
447
+                if ($event instanceof BeforeTemplateRenderedEvent) {
448
+                    return $event->getShare() === $share;
449
+                } else {
450
+                    return true;
451
+                }
452
+            })
453
+        );
454
+
455
+        $this->l10n->expects($this->any())
456
+            ->method('t')
457
+            ->willReturnCallback(function ($text, $parameters) {
458
+                return vsprintf($text, $parameters);
459
+            });
460
+
461
+        // Set up initial state
462
+        $initialState = [];
463
+        $this->initialState->expects(self::any())
464
+            ->method('provideInitialState')
465
+            ->willReturnCallback(function ($key, $value) use (&$initialState): void {
466
+                $initialState[$key] = $value;
467
+            });
468
+        $expectedInitialState = [
469
+            'isPublic' => true,
470
+            'sharingToken' => 'token',
471
+            'sharePermissions' => Constants::PERMISSION_CREATE,
472
+            'filename' => $filename,
473
+            'view' => 'public-file-drop',
474
+            'disclaimer' => 'My disclaimer text',
475
+            'owner' => 'ownerUID',
476
+            'ownerDisplayName' => 'ownerDisplay',
477
+        ];
478
+
479
+        $response = $this->shareController->showShare();
480
+
481
+        $this->assertEquals($expectedInitialState, $initialState);
482
+
483
+        $csp = new ContentSecurityPolicy();
484
+        $csp->addAllowedFrameDomain('\'self\'');
485
+        $expectedResponse = new PublicTemplateResponse('files', 'index');
486
+        $expectedResponse->setParams(['pageTitle' => $filename]);
487
+        $expectedResponse->setContentSecurityPolicy($csp);
488
+        $expectedResponse->setHeaderTitle($filename);
489
+        $expectedResponse->setHeaderDetails('shared by ownerDisplay');
490
+        $expectedResponse->setHeaderActions([
491
+            new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'shareUrl'),
492
+        ]);
493
+
494
+        $this->assertEquals($expectedResponse, $response);
495
+    }
496
+
497
+    public function testShowShareWithPrivateName(): void {
498
+        $note = 'personal note';
499
+        $filename = 'file1.txt';
500
+
501
+        $this->shareController->setToken('token');
502
+
503
+        $owner = $this->createMock(IUser::class);
504
+        $owner->method('getDisplayName')->willReturn('ownerDisplay');
505
+        $owner->method('getUID')->willReturn('ownerUID');
506
+        $owner->method('isEnabled')->willReturn(true);
507
+
508
+        $initiator = $this->createMock(IUser::class);
509
+        $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
510
+        $initiator->method('getUID')->willReturn('initiatorUID');
511
+        $initiator->method('isEnabled')->willReturn(true);
512
+
513
+        $file = $this->createMock(File::class);
514
+        $file->method('getName')->willReturn($filename);
515
+        $file->method('getMimetype')->willReturn('text/plain');
516
+        $file->method('getSize')->willReturn(33);
517
+        $file->method('isReadable')->willReturn(true);
518
+        $file->method('isShareable')->willReturn(true);
519
+        $file->method('getId')->willReturn(111);
520
+
521
+        $accountName = $this->createMock(IAccountProperty::class);
522
+        $accountName->method('getScope')
523
+            ->willReturn(IAccountManager::SCOPE_LOCAL);
524
+        $account = $this->createMock(IAccount::class);
525
+        $account->method('getProperty')
526
+            ->with(IAccountManager::PROPERTY_DISPLAYNAME)
527
+            ->willReturn($accountName);
528
+        $this->accountManager->expects($this->once())
529
+            ->method('getAccount')
530
+            ->with($owner)
531
+            ->willReturn($account);
532
+
533
+        /** @var IShare */
534
+        $share = Server::get(Manager::class)->newShare();
535
+        $share->setId(42);
536
+        $share->setPassword('password')
537
+            ->setShareOwner('ownerUID')
538
+            ->setSharedBy('initiatorUID')
539
+            ->setNode($file)
540
+            ->setNote($note)
541
+            ->setToken('token')
542
+            ->setPermissions(Constants::PERMISSION_ALL & ~Constants::PERMISSION_SHARE)
543
+            ->setTarget("/$filename");
544
+
545
+        $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
546
+        $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
547
+
548
+        $this->urlGenerator->expects(self::atLeast(2))
549
+            ->method('linkToRouteAbsolute')
550
+            ->willReturnMap([
551
+                // every file has the show show share url in the opengraph url prop
552
+                ['files_sharing.sharecontroller.showShare', ['token' => 'token'], 'shareUrl'],
553
+                // this share is not an image to the default preview is used
554
+                ['files_sharing.PublicPreview.getPreview', ['x' => 256, 'y' => 256, 'file' => $share->getTarget(), 'token' => 'token'], 'previewUrl'],
555
+                // for the direct link
556
+                ['files_sharing.sharecontroller.downloadShare', ['token' => 'token', 'filename' => $filename ], 'downloadUrl'],
557
+            ]);
558
+
559
+        $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
560
+
561
+        $this->config->method('getSystemValue')
562
+            ->willReturnMap(
563
+                [
564
+                    ['max_filesize_animated_gifs_public_sharing', 10, 10],
565
+                    ['enable_previews', true, true],
566
+                    ['preview_max_x', 1024, 1024],
567
+                    ['preview_max_y', 1024, 1024],
568
+                ]
569
+            );
570
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
571
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
572
+
573
+        $this->shareManager
574
+            ->expects($this->once())
575
+            ->method('getShareByToken')
576
+            ->with('token')
577
+            ->willReturn($share);
578
+
579
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
580
+            if ($uid === 'ownerUID') {
581
+                return $owner;
582
+            }
583
+            if ($uid === 'initiatorUID') {
584
+                return $initiator;
585
+            }
586
+            return null;
587
+        });
588
+
589
+        $this->eventDispatcher->method('dispatchTyped')->with(
590
+            $this->callback(function ($event) use ($share) {
591
+                if ($event instanceof BeforeTemplateRenderedEvent) {
592
+                    return $event->getShare() === $share;
593
+                } else {
594
+                    return true;
595
+                }
596
+            })
597
+        );
598
+
599
+        $this->l10n->expects($this->any())
600
+            ->method('t')
601
+            ->will($this->returnCallback(function ($text, $parameters) {
602
+                return vsprintf($text, $parameters);
603
+            }));
604
+
605
+        $this->defaults->expects(self::any())
606
+            ->method('getProductName')
607
+            ->willReturn('Nextcloud');
608
+
609
+        $response = $this->shareController->showShare();
610
+
611
+        $csp = new ContentSecurityPolicy();
612
+        $csp->addAllowedFrameDomain('\'self\'');
613
+        $expectedResponse = new PublicTemplateResponse('files', 'index');
614
+        $expectedResponse->setParams(['pageTitle' => $filename]);
615
+        $expectedResponse->setContentSecurityPolicy($csp);
616
+        $expectedResponse->setHeaderTitle($filename);
617
+        $expectedResponse->setHeaderDetails('');
618
+        $expectedResponse->setHeaderActions([
619
+            new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', 'downloadUrl', 0, '33'),
620
+            new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', 'owner', 'ownerDisplay', $filename),
621
+            new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', 'downloadUrl'),
622
+        ]);
623
+
624
+        $this->assertEquals($expectedResponse, $response);
625
+    }
626
+
627
+
628
+    public function testShowShareInvalid(): void {
629
+        $this->expectException(NotFoundException::class);
630
+
631
+        $filename = 'file1.txt';
632
+        $this->shareController->setToken('token');
633
+
634
+        $owner = $this->getMockBuilder(IUser::class)->getMock();
635
+        $owner->method('getDisplayName')->willReturn('ownerDisplay');
636
+        $owner->method('getUID')->willReturn('ownerUID');
637
+
638
+        $file = $this->getMockBuilder('OCP\Files\File')->getMock();
639
+        $file->method('getName')->willReturn($filename);
640
+        $file->method('getMimetype')->willReturn('text/plain');
641
+        $file->method('getSize')->willReturn(33);
642
+        $file->method('isShareable')->willReturn(false);
643
+        $file->method('isReadable')->willReturn(true);
644
+
645
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
646
+        $share->setId(42);
647
+        $share->setPassword('password')
648
+            ->setShareOwner('ownerUID')
649
+            ->setNode($file)
650
+            ->setTarget("/$filename");
651
+
652
+        $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
653
+        $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
654
+
655
+        $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
656
+
657
+        $this->config->method('getSystemValue')
658
+            ->willReturnMap(
659
+                [
660
+                    ['max_filesize_animated_gifs_public_sharing', 10, 10],
661
+                    ['enable_previews', true, true],
662
+                ]
663
+            );
664
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
665
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
666
+
667
+        $this->shareManager
668
+            ->expects($this->once())
669
+            ->method('getShareByToken')
670
+            ->with('token')
671
+            ->willReturn($share);
672
+
673
+        $this->userManager->method('get')->with('ownerUID')->willReturn($owner);
674
+
675
+        $this->shareController->showShare();
676
+    }
677
+
678
+    public function testDownloadShareWithCreateOnlyShare(): void {
679
+        $share = $this->getMockBuilder(IShare::class)->getMock();
680
+        $share->method('getPassword')->willReturn('password');
681
+        $share
682
+            ->expects($this->once())
683
+            ->method('getPermissions')
684
+            ->willReturn(Constants::PERMISSION_CREATE);
685
+
686
+        $this->shareManager
687
+            ->expects($this->once())
688
+            ->method('getShareByToken')
689
+            ->with('validtoken')
690
+            ->willReturn($share);
691
+
692
+        // Test with a password protected share and no authentication
693
+        $response = $this->shareController->downloadShare('validtoken');
694
+        $expectedResponse = new DataResponse('Share has no read permission');
695
+        $this->assertEquals($expectedResponse, $response);
696
+    }
697
+
698
+    public function testDownloadShareWithoutDownloadPermission(): void {
699
+        $attributes = $this->createMock(IAttributes::class);
700
+        $attributes->expects(self::once())
701
+            ->method('getAttribute')
702
+            ->with('permissions', 'download')
703
+            ->willReturn(false);
704
+
705
+        $share = $this->createMock(IShare::class);
706
+        $share->method('getPassword')->willReturn('password');
707
+        $share->expects(self::once())
708
+            ->method('getPermissions')
709
+            ->willReturn(Constants::PERMISSION_READ);
710
+        $share->expects(self::once())
711
+            ->method('getAttributes')
712
+            ->willReturn($attributes);
713
+
714
+        $this->shareManager
715
+            ->expects(self::once())
716
+            ->method('getShareByToken')
717
+            ->with('validtoken')
718
+            ->willReturn($share);
719
+
720
+        // Test with a password protected share and no authentication
721
+        $response = $this->shareController->downloadShare('validtoken');
722
+        $expectedResponse = new DataResponse('Share has no download permission');
723
+        $this->assertEquals($expectedResponse, $response);
724
+    }
725
+
726
+    public function testDisabledOwner(): void {
727
+        $this->shareController->setToken('token');
728
+
729
+        $owner = $this->getMockBuilder(IUser::class)->getMock();
730
+        $owner->method('isEnabled')->willReturn(false);
731
+
732
+        $initiator = $this->createMock(IUser::class);
733
+        $initiator->method('isEnabled')->willReturn(false);
734
+
735
+        /* @var MockObject|Folder $folder */
736
+        $folder = $this->createMock(Folder::class);
737
+
738
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
739
+        $share->setId(42);
740
+        $share->setPermissions(Constants::PERMISSION_CREATE)
741
+            ->setShareOwner('ownerUID')
742
+            ->setSharedBy('initiatorUID')
743
+            ->setNode($folder)
744
+            ->setTarget('/share');
745
+
746
+        $this->shareManager
747
+            ->expects($this->once())
748
+            ->method('getShareByToken')
749
+            ->with('token')
750
+            ->willReturn($share);
751
+
752
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
753
+            if ($uid === 'ownerUID') {
754
+                return $owner;
755
+            }
756
+            if ($uid === 'initiatorUID') {
757
+                return $initiator;
758
+            }
759
+            return null;
760
+        });
761
+
762
+        $this->expectException(NotFoundException::class);
763
+
764
+        $this->shareController->showShare();
765
+    }
766
+
767
+    public function testDisabledInitiator(): void {
768
+        $this->shareController->setToken('token');
769
+
770
+        $owner = $this->getMockBuilder(IUser::class)->getMock();
771
+        $owner->method('isEnabled')->willReturn(false);
772
+
773
+        $initiator = $this->createMock(IUser::class);
774
+        $initiator->method('isEnabled')->willReturn(true);
775
+
776
+        /* @var MockObject|Folder $folder */
777
+        $folder = $this->createMock(Folder::class);
778
+
779
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
780
+        $share->setId(42);
781
+        $share->setPermissions(Constants::PERMISSION_CREATE)
782
+            ->setShareOwner('ownerUID')
783
+            ->setSharedBy('initiatorUID')
784
+            ->setNode($folder)
785
+            ->setTarget('/share');
786
+
787
+        $this->shareManager
788
+            ->expects($this->once())
789
+            ->method('getShareByToken')
790
+            ->with('token')
791
+            ->willReturn($share);
792
+
793
+        $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
794
+            if ($uid === 'ownerUID') {
795
+                return $owner;
796
+            }
797
+            if ($uid === 'initiatorUID') {
798
+                return $initiator;
799
+            }
800
+            return null;
801
+        });
802
+
803
+        $this->expectException(NotFoundException::class);
804
+
805
+        $this->shareController->showShare();
806
+    }
807 807
 }
Please login to merge, or discard this patch.