-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding new Symfony events for zipfile download and public link share #29885
Conversation
199790f
to
74627de
Compare
Codecov Report
@@ Coverage Diff @@
## master #29885 +/- ##
============================================
+ Coverage 58.24% 58.26% +0.01%
- Complexity 18519 18525 +6
============================================
Files 1093 1093
Lines 63711 63771 +60
============================================
+ Hits 37108 37155 +47
- Misses 26603 26616 +13
Continue to review full report at Codecov.
|
89c8df4
to
fecaf0b
Compare
de74508
to
738162e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments above.
Note that for ZIP download I think there are at least 3 cases:
- URL with "files" with only one file => direct download
- URL with "files" and multiple files with full path => download all of them as ZIP
- URL with "dir" containing base dir and "files" containing a list of files inside that dir => prepend dir to all files and download as ZIP
- URL with "dir" without "files" => download said folder as ZIP
this is from memory, please check the code
@@ -103,6 +107,7 @@ public function __construct( | |||
$this->l = $l10n; | |||
$this->config = $config; | |||
$this->additionalInfoField = $this->config->getAppValue('core', 'user_additional_info_field', ''); | |||
$this->eventDispatcher = \OC::$server->getEventDispatcher(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not inject it in the constructor like the other 9 services ?
$event->setArgument('name', $name); | ||
$event->setArgument('run', true); | ||
//Dispatch an event to see if creating shares is blocked by any app | ||
$this->eventDispatcher->dispatch('file.beforecreateShare', $event); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
share.beforeCreate
?
Please also add a share.afterCreate
if possible for the sake of completeness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And also catch exception here and transform it to an OCS Result with the exception message. I expect that listeners will throw exceptions in case of denied access.
lib/private/legacy/files.php
Outdated
@@ -139,6 +139,13 @@ public static function get($dir, $files, $params = null) { | |||
} | |||
} | |||
|
|||
//Dispatch an event to see if any apps have problem with download | |||
$event = new \Symfony\Component\EventDispatcher\GenericEvent(null, ['files' => $files]); | |||
OC::$server->getEventDispatcher()->dispatch('file.beforecreatezip', $event); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in your other PR you used camel case for event names, please do so here as well.
lib/private/legacy/files.php
Outdated
@@ -139,6 +139,13 @@ public static function get($dir, $files, $params = null) { | |||
} | |||
} | |||
|
|||
//Dispatch an event to see if any apps have problem with download | |||
$event = new \Symfony\Component\EventDispatcher\GenericEvent(null, ['files' => $files]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please double check what happens if "$dir" is set with a single value and multiple "$files" are set. It is likely that we also need to pass $dir
. The alternative is to have a loop that prepends the directory to all given $files
entries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the snapshot I took from IDE:
Basically during testing I have used a directory and a file. Above is the screenshot of the get
method with single dir newfolder
and multiple files: welcome.txt
and rename_testfile.txt
. The newfolder and the files reside in the home folder of the user. The $dir
is "/" in the above screenshot. I tried to create a folder inside newfolder
and then created few files inside newfolder
. In this case also $dir
remains "/".
lib/private/legacy/files.php
Outdated
$event = new \Symfony\Component\EventDispatcher\GenericEvent(null, ['files' => $files]); | ||
OC::$server->getEventDispatcher()->dispatch('file.beforecreatezip', $event); | ||
if ($event->hasArgument('run') and ($event->getArgument('run') === false) and ($event->hasArgument('message'))) { | ||
throw new Exception(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A generic exception without a message will confuse the user. Maybe throw ForbiddenException instead with a message "Access denied".
In general I'd rather expect event listeners to directly throw an exception from inside with a proper message, so the exception itself would already be forwarded by not catching it in the dispatch()
call.
//Dispatch an event to see if creating shares is blocked by any app | ||
$this->eventDispatcher->dispatch('file.beforecreateShare', $event); | ||
if ($event->getArgument('run') === false) { | ||
return new \OC\OCS\Result(null, 404, $this->l->t('No permission to create share')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no permission is a 403 forbidden, not 404 not found
dabb82e
to
6e0724c
Compare
Made the following changes:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better, still some changes needed
@@ -466,12 +484,15 @@ public function createShare() { | |||
|
|||
$share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); | |||
|
|||
$event->setArgument('output', $output); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create a new event instance, don't resend the same one
apps/files_sharing/tests/ApiTest.php
Outdated
@@ -115,6 +116,10 @@ private function createOCS($request, $userId) { | |||
return vsprintf($text, $parameters); | |||
})); | |||
|
|||
\OC::$server->getEventDispatcher()->addListener('share.beforeCreate', function (GenericEvent $event) { | |||
$event->setArgument('run', true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this really needed ? "run" is true by default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was added because the tests were failing. It was using false value from Share20OCSTest.php. That's the reason I set run
value to true here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strange. Do you mean one test is influencing another ? This shouldn't happen. We need to find a way to reset the event dispatcher in tearDown
to avoid test side effects.
lib/private/legacy/files.php
Outdated
//Dispatch an event to see if any apps have problem with download | ||
$event = new \Symfony\Component\EventDispatcher\GenericEvent(null, ['dir' => $dir, 'files' => $files]); | ||
OC::$server->getEventDispatcher()->dispatch('file.beforeCreateZip', $event); | ||
if ($event->hasArgument('run') and ($event->getArgument('run') === false) and ($event->hasArgument('message'))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure the "run" argument is created by you and set to "true" by default like you did for share creation.
Any reason you chose to not simply use the same pattern like for share creation ?
rename "message" to "errorMessage"
6e0724c
to
89c1dc3
Compare
Updated the changes:
|
89c1dc3
to
ddffd96
Compare
ddffd96
to
f656be5
Compare
lib/private/legacy/files.php
Outdated
//Dispatch an event to see if any apps have problem with download | ||
$event = new \Symfony\Component\EventDispatcher\GenericEvent(null, ['dir' => $dir, 'files' => $files, 'run' => true]); | ||
OC::$server->getEventDispatcher()->dispatch('file.beforeCreateZip', $event); | ||
if (($event->getArgument('run') === false) and ($event->hasArgument('errorMessage'))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be ||
, not and
. If run is false and no error message was supplied, we should still stop running.
lib/private/legacy/files.php
Outdated
@@ -167,6 +174,9 @@ public static function get($dir, $files, $params = null) { | |||
$streamer->finalize(); | |||
set_time_limit($executionTime); | |||
self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); | |||
$event = new \Symfony\Component\EventDispatcher\GenericEvent(null, ['result' => 'success']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please also pass dir
and files
arguments here
92c20e2
to
1abe239
Compare
Adding new Symfony events, to check, if creating shares or downloading zips are blocked by any apps or not. Signed-off-by: Sujith H <[email protected]>
1abe239
to
7e977b4
Compare
@PVince81 Let me know if this change looks ok. |
Created backport to stable10 PR: #30067 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Adding new Symfony events, to check, if creating
shares or downloading zips are blocked by any
apps or not.
Signed-off-by: Sujith H [email protected]
Description
Adding new Symfony events to check if any apps revoked the premission to download zip files or creating public links.
Related Issue
#29877
#29876
Motivation and Context
Adding new symfony events which can be used by the apps to see if creating public links for files/folders are allowed or not. And also see if downloading zip files are allowed or not.
How Has This Been Tested?
Screenshots (if appropriate):
Types of changes
Checklist: