Merge pull request #22225 from owncloud/sharing-moar-hooks
More sharing hooks for extended auditing
This commit is contained in:
commit
6474866aff
|
@ -30,7 +30,6 @@
|
||||||
namespace OCA\Files_Sharing\Controllers;
|
namespace OCA\Files_Sharing\Controllers;
|
||||||
|
|
||||||
use OC;
|
use OC;
|
||||||
use OC\Files\Filesystem;
|
|
||||||
use OC_Files;
|
use OC_Files;
|
||||||
use OC_Util;
|
use OC_Util;
|
||||||
use OCP;
|
use OCP;
|
||||||
|
@ -71,7 +70,7 @@ class ShareController extends Controller {
|
||||||
protected $logger;
|
protected $logger;
|
||||||
/** @var OCP\Activity\IManager */
|
/** @var OCP\Activity\IManager */
|
||||||
protected $activityManager;
|
protected $activityManager;
|
||||||
/** @var OC\Share20\Manager */
|
/** @var OCP\Share\IManager */
|
||||||
protected $shareManager;
|
protected $shareManager;
|
||||||
/** @var ISession */
|
/** @var ISession */
|
||||||
protected $session;
|
protected $session;
|
||||||
|
@ -88,7 +87,7 @@ class ShareController extends Controller {
|
||||||
* @param IUserManager $userManager
|
* @param IUserManager $userManager
|
||||||
* @param ILogger $logger
|
* @param ILogger $logger
|
||||||
* @param OCP\Activity\IManager $activityManager
|
* @param OCP\Activity\IManager $activityManager
|
||||||
* @param \OC\Share20\Manager $shareManager
|
* @param \OCP\Share\IManager $shareManager
|
||||||
* @param ISession $session
|
* @param ISession $session
|
||||||
* @param IPreview $previewManager
|
* @param IPreview $previewManager
|
||||||
* @param IRootFolder $rootFolder
|
* @param IRootFolder $rootFolder
|
||||||
|
@ -100,7 +99,7 @@ class ShareController extends Controller {
|
||||||
IUserManager $userManager,
|
IUserManager $userManager,
|
||||||
ILogger $logger,
|
ILogger $logger,
|
||||||
\OCP\Activity\IManager $activityManager,
|
\OCP\Activity\IManager $activityManager,
|
||||||
\OC\Share20\Manager $shareManager,
|
\OCP\Share\IManager $shareManager,
|
||||||
ISession $session,
|
ISession $session,
|
||||||
IPreview $previewManager,
|
IPreview $previewManager,
|
||||||
IRootFolder $rootFolder) {
|
IRootFolder $rootFolder) {
|
||||||
|
@ -177,6 +176,7 @@ class ShareController extends Controller {
|
||||||
if ($this->shareManager->checkPassword($share, $password)) {
|
if ($this->shareManager->checkPassword($share, $password)) {
|
||||||
$this->session->set('public_link_authenticated', (string)$share->getId());
|
$this->session->set('public_link_authenticated', (string)$share->getId());
|
||||||
} else {
|
} else {
|
||||||
|
$this->emitAccessShareHook($share, 403, 'Wrong password');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -189,6 +189,44 @@ class ShareController extends Controller {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* throws hooks when a share is attempted to be accessed
|
||||||
|
*
|
||||||
|
* @param \OCP\Share\IShare|string $share the Share instance if available,
|
||||||
|
* otherwise token
|
||||||
|
* @param int $errorCode
|
||||||
|
* @param string $errorMessage
|
||||||
|
* @throws OC\HintException
|
||||||
|
* @throws OC\ServerNotAvailableException
|
||||||
|
*/
|
||||||
|
protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
|
||||||
|
$itemType = $itemSource = $uidOwner = '';
|
||||||
|
$token = $share;
|
||||||
|
$exception = null;
|
||||||
|
if($share instanceof \OCP\Share\IShare) {
|
||||||
|
try {
|
||||||
|
$token = $share->getToken();
|
||||||
|
$uidOwner = $share->getSharedBy();
|
||||||
|
$itemType = $share->getNodeType();
|
||||||
|
$itemSource = $share->getNodeId();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// we log what we know and pass on the exception afterwards
|
||||||
|
$exception = $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\OC_Hook::emit('OCP\Share', 'share_link_access', [
|
||||||
|
'itemType' => $itemType,
|
||||||
|
'itemSource' => $itemSource,
|
||||||
|
'uidOwner' => $uidOwner,
|
||||||
|
'token' => $token,
|
||||||
|
'errorCode' => $errorCode,
|
||||||
|
'errorMessage' => $errorMessage,
|
||||||
|
]);
|
||||||
|
if(!is_null($exception)) {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
|
@ -205,6 +243,7 @@ class ShareController extends Controller {
|
||||||
try {
|
try {
|
||||||
$share = $this->shareManager->getShareByToken($token);
|
$share = $this->shareManager->getShareByToken($token);
|
||||||
} catch (ShareNotFound $e) {
|
} catch (ShareNotFound $e) {
|
||||||
|
$this->emitAccessShareHook($token, 404, 'Share not found');
|
||||||
return new NotFoundResponse();
|
return new NotFoundResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,9 +254,15 @@ class ShareController extends Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can't get the path of a file share
|
// We can't get the path of a file share
|
||||||
|
try {
|
||||||
if ($share->getNode() instanceof \OCP\Files\File && $path !== '') {
|
if ($share->getNode() instanceof \OCP\Files\File && $path !== '') {
|
||||||
|
$this->emitAccessShareHook($share, 404, 'Share not found');
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->emitAccessShareHook($share, 404, 'Share not found');
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
$rootFolder = null;
|
$rootFolder = null;
|
||||||
if ($share->getNode() instanceof \OCP\Files\Folder) {
|
if ($share->getNode() instanceof \OCP\Files\Folder) {
|
||||||
|
@ -227,6 +272,7 @@ class ShareController extends Controller {
|
||||||
try {
|
try {
|
||||||
$path = $rootFolder->get($path);
|
$path = $rootFolder->get($path);
|
||||||
} catch (\OCP\Files\NotFoundException $e) {
|
} catch (\OCP\Files\NotFoundException $e) {
|
||||||
|
$this->emitAccessShareHook($share, 404, 'Share not found');
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,6 +333,8 @@ class ShareController extends Controller {
|
||||||
$response = new TemplateResponse($this->appName, 'public', $shareTmpl, 'base');
|
$response = new TemplateResponse($this->appName, 'public', $shareTmpl, 'base');
|
||||||
$response->setContentSecurityPolicy($csp);
|
$response->setContentSecurityPolicy($csp);
|
||||||
|
|
||||||
|
$this->emitAccessShareHook($share);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +392,7 @@ class ShareController extends Controller {
|
||||||
try {
|
try {
|
||||||
$node = $node->get($path);
|
$node = $node->get($path);
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
|
$this->emitAccessShareHook($share, 404, 'Share not found');
|
||||||
return new NotFoundResponse();
|
return new NotFoundResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,6 +458,8 @@ class ShareController extends Controller {
|
||||||
setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
|
setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->emitAccessShareHook($share);
|
||||||
|
|
||||||
// download selected files
|
// download selected files
|
||||||
if (!is_null($files)) {
|
if (!is_null($files)) {
|
||||||
// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
|
// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
|
||||||
|
|
|
@ -219,7 +219,11 @@ class ShareControllerTest extends \Test\TestCase {
|
||||||
|
|
||||||
public function testAuthenticateInvalidPassword() {
|
public function testAuthenticateInvalidPassword() {
|
||||||
$share = \OC::$server->getShareManager()->newShare();
|
$share = \OC::$server->getShareManager()->newShare();
|
||||||
$share->setId(42);
|
$share->setNodeId(100)
|
||||||
|
->setNodeType('file')
|
||||||
|
->setToken('token')
|
||||||
|
->setSharedBy('initiator')
|
||||||
|
->setId(42);
|
||||||
|
|
||||||
$this->shareManager
|
$this->shareManager
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
|
@ -237,6 +241,20 @@ class ShareControllerTest extends \Test\TestCase {
|
||||||
->expects($this->never())
|
->expects($this->never())
|
||||||
->method('set');
|
->method('set');
|
||||||
|
|
||||||
|
$hookListner = $this->getMockBuilder('Dummy')->setMethods(['access'])->getMock();
|
||||||
|
\OCP\Util::connectHook('OCP\Share', 'share_link_access', $hookListner, 'access');
|
||||||
|
|
||||||
|
$hookListner->expects($this->once())
|
||||||
|
->method('access')
|
||||||
|
->with($this->callback(function(array $data) {
|
||||||
|
return $data['itemType'] === 'file' &&
|
||||||
|
$data['itemSource'] === 100 &&
|
||||||
|
$data['uidOwner'] === 'initiator' &&
|
||||||
|
$data['token'] === 'token' &&
|
||||||
|
$data['errorCode'] === 403 &&
|
||||||
|
$data['errorMessage'] === 'Wrong password';
|
||||||
|
}));
|
||||||
|
|
||||||
$response = $this->shareController->authenticate('token', 'invalidpassword');
|
$response = $this->shareController->authenticate('token', 'invalidpassword');
|
||||||
$expectedResponse = new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest');
|
$expectedResponse = new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest');
|
||||||
$this->assertEquals($expectedResponse, $response);
|
$this->assertEquals($expectedResponse, $response);
|
||||||
|
|
|
@ -597,7 +597,7 @@ class Manager implements IManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($share->getExpirationDate() !== $originalShare->getExpirationDate()) {
|
if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
|
||||||
//Verify the expiration date
|
//Verify the expiration date
|
||||||
$this->validateExpirationDate($share);
|
$this->validateExpirationDate($share);
|
||||||
$expirationDateUpdated = true;
|
$expirationDateUpdated = true;
|
||||||
|
@ -619,6 +619,16 @@ class Manager implements IManager {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($share->getPassword() !== $originalShare->getPassword()) {
|
||||||
|
\OC_Hook::emit('OCP\Share', 'post_update_password', [
|
||||||
|
'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
|
||||||
|
'itemSource' => $share->getNode()->getId(),
|
||||||
|
'uidOwner' => $share->getSharedBy(),
|
||||||
|
'token' => $share->getToken(),
|
||||||
|
'disabled' => is_null($share->getPassword()),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
if ($share->getPermissions() !== $originalShare->getPermissions()) {
|
if ($share->getPermissions() !== $originalShare->getPermissions()) {
|
||||||
$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
|
$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
|
||||||
\OC_Hook::emit('OCP\Share', 'post_update_permissions', array(
|
\OC_Hook::emit('OCP\Share', 'post_update_permissions', array(
|
||||||
|
|
|
@ -163,6 +163,7 @@ class Share implements \OCP\Share\IShare {
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->nodeType = $type;
|
$this->nodeType = $type;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue