Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ script:
- cd ../

# Run Javascript unit tests
- cd tests/js
- sh -c "if [ '$JSTESTS' = '1' ]; then npm install --deps; node_modules/karma/bin/karma start karma.config.js --single-run; fi"
- cd ../
# - cd tests/js
# - sh -c "if [ '$JSTESTS' = '1' ]; then npm install --deps; node_modules/karma/bin/karma start karma.config.js --single-run; fi"
# - cd ../

matrix:
include:
Expand All @@ -63,8 +63,8 @@ matrix:
env: DB=mysql;CODECHECK=1
- php: 5.4
env: DB=mysql;CODECHECK=2
- php: 5.4
env: DB=mysql;JSTESTS=1
# - php: 5.4
# env: DB=mysql;JSTESTS=1
allow_failures:
- env: DB=mysql;CODECHECK=2
- env: DB=oracle # TODO: temporary until it is fixed
Expand Down
4 changes: 2 additions & 2 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?xml version="1.0"?>
<info>
<id>files_accesscontrol</id>
<name>Files Access Control</name>
<name>Files access control</name>
<description>An app for Nextcloud to control the access to files based on some conditions</description>
<licence>AGPL</licence>
<author>Morris Jobke</author>
<version>0.6.0</version>
<version>1.1.0</version>
<namespace>FilesAccessControl</namespace>

<category>other</category>
Expand Down
17 changes: 3 additions & 14 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
use OCA\FilesAccessControl\StorageWrapper;
use OCP\Files\Storage\IStorage;
use OCP\Util;
use Symfony\Component\EventDispatcher\GenericEvent;

class Application extends \OCP\AppFramework\App {

Expand All @@ -40,17 +39,6 @@ public function registerHooksAndListeners() {
Util::connectHook('OC_Filesystem', 'preSetup', $this, 'addStorageWrapper');

\OCP\App::registerAdmin('files_accesscontrol', 'settings/admin');

$container = $this->getContainer();
$container->getServer()->getEventDispatcher()->addListener(
'OCA\FilesAccessControl\StorageWrapper\Event',
function(GenericEvent $event) use ($container) {
/** @var \OCA\FilesAccessControl\AccessControl $accessControl */
$accessControl = $container->query('OCA\FilesAccessControl\AccessControl');
$accessControl->listen($event);
},
-10
);
}

/**
Expand All @@ -69,11 +57,12 @@ public function addStorageWrapper() {
*/
public function addStorageWrapperCallback($mountPoint, IStorage $storage) {
if (!\OC::$CLI && !$storage->instanceOfStorage('OC\Files\Storage\Shared')) {
$dispatcher = $this->getContainer()->getServer()->getEventDispatcher();
/** @var \OCA\FilesAccessControl\Operation $operation */
$operation = $this->getContainer()->query('OCA\FilesAccessControl\Operation');
return new StorageWrapper([
'storage' => $storage,
'mountPoint' => $mountPoint,
'dispatcher' => $dispatcher,
'operation' => $operation,
]);
}

Expand Down
3 changes: 2 additions & 1 deletion lib/Controller/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ public function index() {
\OCP\Util::addScript($this->appName, 'admin');
return new TemplateResponse('workflowengine', 'admin', [
'appid' => $this->appName,
'heading' => $this->l10n->t('Files Access Control'),
'heading' => $this->l10n->t('File access control'),
'description' => $this->l10n->t('Each rule group consists of one or more rules. A request matches a group if all rules evaluate to true. If a request matches at least one of the defined groups, the request is blocked and the file content can not be read or written.'),
], 'blank');
}
}
64 changes: 42 additions & 22 deletions lib/AccessControl.php → lib/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@

use OCP\Files\ForbiddenException;
use OCP\WorkflowEngine\IManager;
use Symfony\Component\EventDispatcher\GenericEvent;

class AccessControl {
class Operation {

/**
* AccessControl constructor.
Expand All @@ -38,39 +37,60 @@ public function __construct(IManager $manager) {
}

/**
* @param GenericEvent $event
* @param StorageWrapper $storage
* @param string $path
* @throws ForbiddenException
*/
public function listen(GenericEvent $event) {
if ($event->getArgument('slot') !== StorageWrapper::SLOT_BEFORE) {
public function checkFileAccess(StorageWrapper $storage, $path) {
if (!$this->isUserFileOrThumbnail($storage, $path) || $this->isCreatingSkeletonFiles()) {
// Allow creating skeletons and theming
// https://github.com/nextcloud/files_accesscontrol/issues/5
// https://github.com/nextcloud/files_accesscontrol/issues/12
return;
}

/** @var StorageWrapper $storage */
$storage = $event->getSubject();
$this->manager->setFileInfo($storage, $path);
$match = $this->manager->getMatchingOperations('OCA\FilesAccessControl\Operation');

if ($event->hasArgument('path')) {
$this->checkFileAccess($storage, $event->getArgument('path'));
}
if ($event->hasArgument('path1')) {
$this->checkFileAccess($storage, $event->getArgument('path1'));
}
if ($event->hasArgument('path2')) {
$this->checkFileAccess($storage, $event->getArgument('path2'));
if (!empty($match)) {
// All Checks of one operation matched: prevent access
throw new ForbiddenException('Access denied', true);
}
}

/**
* @param StorageWrapper $storage
* @param string $path
* @throws ForbiddenException
* @return bool
*/
protected function checkFileAccess(StorageWrapper $storage, $path) {
$this->manager->setFileInfo($storage, $path);
$match = $this->manager->getMatchingOperations('OCA\FilesAccessControl\Operation');
protected function isUserFileOrThumbnail(StorageWrapper $storage, $path) {
$fullPath = $storage->mountPoint . $path;

if (!empty($match)) {
// All Checks of one operation matched: prevent access
throw new ForbiddenException('Access denied', true);
if (substr_count($fullPath, '/') < 3) {
return false;
}

// '', admin, 'files', 'path/to/file.txt'
$segment = explode('/', $fullPath, 4);

return isset($segment[2]) && in_array($segment[2], ['files', 'thumbnails']);
}

/**
* Check if we are in the LoginController and if so, ignore the firewall
* @return bool
*/
protected function isCreatingSkeletonFiles() {
$exception = new \Exception();
$trace = $exception->getTrace();

foreach ($trace as $step) {
if ($step['class'] === 'OC\Core\Controller\LoginController' &&
$step['function'] === 'tryLogin') {
return true;
}
}

return false;
}
}
Loading