44
55use Drupal \Core \Entity \EntityTypeManagerInterface ;
66use Drupal \Core \Form \FormStateInterface ;
7+ use Drupal \Core \Session \AccountInterface ;
78use Drupal \Core \Session \AccountProxyInterface ;
89use Drupal \Core \StringTranslation \StringTranslationTrait ;
910use Drupal \Core \Url ;
@@ -228,13 +229,36 @@ public function getWebform(string $webformId, string $submissionUuid = NULL): ?W
228229 * @return \Drupal\user\UserInterface[]|array
229230 * The users.
230231 */
231- public function getAllowedUsers (WebformInterface $ webform ): array {
232+ private function getAllowedUsers (WebformInterface $ webform ): array {
232233 $ settings = $ webform ->getThirdPartySetting ('os2forms ' , 'os2forms_rest_api ' );
233234 $ allowedUserIds = $ settings ['allowed_users ' ] ?? [];
234235
235236 return $ this ->loadUsers ($ allowedUserIds );
236237 }
237238
239+ /**
240+ * Check if a user has access to a webform.
241+ *
242+ * A user has access to a webform if the list of allowed users is empty or the
243+ * user is included in the list.
244+ *
245+ * @param \Drupal\webform\WebformInterface $webform
246+ * The webform.
247+ * @param \Drupal\Core\Session\AccountInterface|int $user
248+ * The user or user id.
249+ *
250+ * @return bool
251+ * True if user has access to the webform.
252+ */
253+ public function hasWebformAccess (WebformInterface $ webform , $ user ): bool {
254+ $ userId = $ user instanceof AccountInterface ? $ user ->id () : $ user ;
255+ assert (is_int ($ userId ));
256+
257+ $ allowedUsers = $ this ->getAllowedUsers ($ webform );
258+
259+ return empty ($ allowedUsers ) || isset ($ allowedUsers [$ userId ]);
260+ }
261+
238262 /**
239263 * Load users.
240264 *
@@ -250,34 +274,34 @@ private function loadUsers(array $spec): array {
250274 /**
251275 * Implements hook_file_download().
252276 *
277+ * Note: This is only used to deny access to a file that is attached to a
278+ * webform (submission) that the user does not have permission to access.
279+ * Permission to access private files are handles elsewhere.
280+ *
253281 * @phpstan-return int|array<string, string>|null
254282 */
255283 public function fileDownload (string $ uri ) {
256284 $ request = $ this ->requestStack ->getCurrentRequest ();
257285
286+ // We are only concerned with users authenticated via Key Auth (cf.
287+ // os2forms_rest_api.services.yml).
258288 if ($ user = $ this ->keyAuth ->authenticate ($ request )) {
259289 // Find webform id from uri, see example uri.
260290 // @Example: private://webform/some_webform_id/119/some_file_name.png
261291 $ pattern = '/private:\/\/webform\/(?<webform>[^\/]*)/ ' ;
262- if (!preg_match ($ pattern , $ uri , $ matches )) {
263- // Something is not right, deny access.
264- return -1 ;
265- }
266-
267- // User has API access. Try to load the webform.
268- $ webform = $ this ->getWebform ($ matches ['webform ' ]);
269- if (NULL === $ webform ) {
270- // Deny access if webform cannot be loaded.
271- return -1 ;
272- }
273-
274- $ allowedUsers = $ this ->getAllowedUsers ($ webform );
275- // If allowed users is non-empty and user is not in there deny access.
276- if (!empty ($ allowedUsers ) && !isset ($ allowedUsers [$ user ->id ()])) {
277- return -1 ;
292+ if (preg_match ($ pattern , $ uri , $ matches )) {
293+ $ webform = $ this ->getWebform ($ matches ['webform ' ]);
294+ if (NULL !== $ webform ) {
295+ // Deny access to file if user does not have access to the webform.
296+ if (!$ this ->hasWebformAccess ($ webform , $ user )) {
297+ return -1 ;
298+ }
299+ }
278300 }
279301 }
280302
303+ // We cannot deny access to the file. Let others handle the access control
304+ // for the (private) file.
281305 return NULL ;
282306 }
283307
0 commit comments