Skip to content
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

Restricted time fileaccess #130

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
68 changes: 64 additions & 4 deletions Classes/Hooks/FileDumpHook.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ class FileDumpHook implements FileDumpEIDHookInterface
*/
protected $resumableDownload = false;

/**
* @var $checkPermissionsService CheckPermissions
*/
protected $checkPermissionsService = false;

/**
* Constructor
*/
Expand All @@ -102,6 +107,9 @@ public function __construct()
$this->forceDownloadForExt = ExtensionConfiguration::forceDownloadForExt();
}
$this->resumableDownload = ExtensionConfiguration::resumableDownload();

$this->checkPermissionsService = GeneralUtility::makeInstance(CheckPermissions::class);

}

/**
Expand Down Expand Up @@ -173,10 +181,55 @@ public function checkFileAccess(ResourceInterface $file)
// Dump the precise requested file for File and ProcessedFile, but dump the referenced file for FileReference
$dumpFile = $file instanceof FileReference ? $file->getOriginalFile() : $file;

if ($this->forceDownload($dumpFile->getExtension())) {
$this->dumpFileContents($dumpFile, true, $this->resumableDownload);
} elseif ($this->resumableDownload) {
$this->dumpFileContents($dumpFile, false, true);
// check Time Restrictions from File Meta
$fileMeta = $dumpFile->getProperties();


$condition1 = $fileMeta['starttime'] <= date('U'); // start lower than now
$condition2 = $fileMeta['starttime'] == 0; // start not set
$condition1_2 = ( $condition1 || $condition2 );
$condition3 = $fileMeta['endtime'] >= date('U'); // end greater than now
$condition4 = $fileMeta['endtime'] == 0; // end not set
$condition3_4 = ( $condition3 || $condition4 );

// debug([
// '1: $fileMeta[starttime] <= date(U)' => $con1,
// '2: $fileMeta[starttime] == 0'=> $con2,
// '1_2: 1||2' => $con1_2,
// '3: $fileMeta[endtime] >= date(U)'=> $con3,
// '4: $fileMeta[endtime] == 0'=> $con4,
// '3_4: 3||4' => $con3_4,
// '1_2 && 3_4' => ( $con1_2 && $con3_4),
// 'now' => date('U')
// ]);


if ( $condition1_2 && $condition3_4 ) {
// access inside period
// debug([
// 'access'=>'granted',
// 'meta' => $fileMeta ,
// 'now' => date ('d-m-Y H:i:s',date('U')),
// 'start' => date ('d-m-Y H:i:s',$fileMeta['starttime']),
// 'end' => date ('d-m-Y H:i:s',$fileMeta['endtime'])
// ]); exit;

if ($this->forceDownload($dumpFile->getExtension())) {
$this->dumpFileContents($dumpFile, true, $this->resumableDownload);
} elseif ($this->resumableDownload) {
$this->dumpFileContents($dumpFile, false, true);
}
} else {
// no access outside this period
// debug([
// 'access'=>'denied',
// 'meta' => $fileMeta ,
// 'now' => date('U'),
// 'start' => date ('d-m-Y H:i:s',$fileMeta['starttime']),
// 'end' => date ('d-m-Y H:i:s',$fileMeta['endtime'])
// ]);exit;
header('HTTP/1.1 404 File not found');
exit;
}
}

Expand Down Expand Up @@ -226,6 +279,13 @@ protected function dumpFileContents($file, $asDownload, $resumableDownload)
exit;
}

// Find part of file and push this out
$filePointer = @fopen($file->getForLocalProcessing(false), 'rb');
if ($filePointer === false) {
header('HTTP/1.1 404 File not found');
exit;
}

$dumpSize = $fileSize;
list($begin, $end) = $range;
if ($begin !== 0 || $end !== $fileSize - 1) {
Expand Down
82 changes: 81 additions & 1 deletion Classes/Security/CheckPermissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ public function checkFileAccess($file, $userFeGroups)
return true;
}

if( !$this->checkFileAccessForTimePeriod( $file ) ){
return false;
}

$customUserGroups = [];
/** @var Dispatcher $signalSlotDispatcher */
$signalSlotDispatcher = GeneralUtility::makeInstance(Dispatcher::class);
Expand All @@ -101,6 +105,11 @@ public function checkFileAccess($file, $userFeGroups)

/** @var Folder $parentFolder */
$parentFolder = $file->getParentFolder();

if( !$this->checkFolderAccessForTimePeriod($parentFolder) ){
return false;
}

// check folder access
if ($this->checkFolderRootLineAccess($parentFolder, $userFeGroups)) {
// access to folder then check file privileges if present
Expand All @@ -113,6 +122,78 @@ public function checkFileAccess($file, $userFeGroups)
return false;
}

/**
* Check if the folder start and stop date is set and if the current date is in the period.
*
* possible are only start date, start and end date, only end date
*
* TODO: implement check folder times
*
* @param Folder $folder
* @return bool
*/
public function checkFolderAccessForTimePeriod(Folder $folder){
// loop through the root line of an folder and check the permissions of every folder
$access = true;
$rootlineTree = array_slice($this->getFolderRootLine($folder),1);

foreach ($rootlineTree as $rootlinefolder) {
// fetch folder permissions record
$folderRecord = $this->utilityService->getFolderRecord($rootlinefolder);

// if no record found the folder in rootline has no access so subfolders have'nt also
if (!$folderRecord) {
$access = false;
break;
}
}
return $access;
}

public function checkAccessForTimePeriod( $dataRecord ){

$condition1 = $dataRecord['starttime'] <= date('U'); // start lower than now
$condition2 = $dataRecord['starttime'] == 0; // start not set
$condition1_2 = ( $condition1 || $condition2 );
$condition3 = $dataRecord['endtime'] >= date('U'); // end greater than now
$condition4 = $dataRecord['endtime'] == 0; // end not set
$condition3_4 = ( $condition3 || $condition4 );

// debug([
// 'access' => ($condition1_2 && $condition3_4) ? 'granted' : 'dismissed',
// 'meta' => $dataRecord,
// 'now' => date ('d-m-Y H:i:s',date('U')),
// 'start' => date ('d-m-Y H:i:s',$dataRecord['starttime']),
// 'end' => date ('d-m-Y H:i:s',$dataRecord['endtime']),
// 'now' => date('U'),
// 'condition results' => [
// '1: $fileMeta[starttime] <= date(U)' => $condition1,
// '2: $fileMeta[starttime] == 0'=> $condition2,
// '1_2: 1||2' => $condition1_2,
// '3: $fileMeta[endtime] >= date(U)'=> $condition3,
// '4: $fileMeta[endtime] == 0'=> $condition4,
// '3_4: 3||4' => $condition3_4,
// 'final' => ( $condition1_2 && $condition3_4),
// ]
// ]); exit;

return $condition1_2 && $condition3_4;
}
/**
* Check if the file start and stop date is set and if the current date is in the period.
*
* possible are only start date, start and end date, only end date
*
* @param \TYPO3\CMS\Core\Resource\File $file
* @return bool
*/
public function checkFileAccessForTimePeriod(File $file){

// check Time Restrictions from File Meta
$fileMeta = $file->getProperties();
return $this->checkAccessForTimePeriod($fileMeta);
}

/**
* Check if given FeGroups have enough rights to access given folder
*
Expand All @@ -127,7 +208,6 @@ public function checkFolderRootLineAccess(Folder $folder, $userFeGroups)
$folder->getHashedIdentifier() .
serialize($userFeGroups)
);

if (!isset($this->checkFolderRootLineAccessCache[$cacheIdentifier])) {
$this->checkFolderRootLineAccessCache[$cacheIdentifier] = true;

Expand Down
3 changes: 2 additions & 1 deletion Classes/Service/Utility.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public function getFolderRecord(Folder $folder)
// cache results
self::$folderRecordCache[$folder->getCombinedIdentifier()] = $record;
}

// debug($queryBuilder->getSQL());
// debug($queryBuilder->getParameters());
return self::$folderRecordCache[$folder->getCombinedIdentifier()];
}

Expand Down
14 changes: 14 additions & 0 deletions Classes/ViewHelpers/Security/AssetAccessViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

use BeechIt\FalSecuredownload\Service\Utility;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Resource\Folder;
Expand Down Expand Up @@ -73,6 +74,19 @@ protected static function evaluateCondition($arguments = null)
$userFeGroups = self::getFeUserGroups();
$access = false;

if($folder){
$utility = GeneralUtility::makeInstance(Utility::class);
$folderRecord = $utility->getFolderRecord($folder);
/* folder record automaticly disapears if start stop date is out of range,
* seems to be some native function...
*/
//debug($folderRecord);
if(!$folderRecord){
// Return with no access... no more need to check file permissions
return false;
}
}

// check folder access
if ($checkPermissionsService->checkFolderRootLineAccess($folder, $userFeGroups)) {
if ($file === null) {
Expand Down
43 changes: 43 additions & 0 deletions Configuration/TCA/Overrides/sys_file_metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,48 @@
]
];

$GLOBALS['TCA']['sys_file_metadata'] = array_merge_recursive(
$GLOBALS['TCA']['sys_file_metadata'],
[
'ctrl'=>[
// 'enablecolumns' => [
// 'starttime' => 'starttime',
// 'endtime' => 'endtime',
// ]
],
'columns' => [
'starttime' => [
'exclude' => true,
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int',
'default' => 0
]
],
'endtime' => [
'exclude' => true,
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int',
'default' => 0
]
]
],
'palettes' => [
'timeRestriction' => ['showitem' => 'starttime, endtime']
],
]
);

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('sys_file_metadata', $additionalColumns);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('sys_file_metadata', 'fe_groups');

// Add new Palette with Time Settings
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes(
'sys_file_metadata',
'--div--;LLL:EXT:fal_securedownload/Resources/Private/Language/locallang_db.xlf:timeRestrictions,
--palette--;;timeRestriction');
35 changes: 33 additions & 2 deletions Configuration/TCA/tx_falsecuredownload_folder.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,26 @@
'ignoreWebMountRestriction' => true,
'ignoreRootLevelRestriction' => true,
],
'enablecolumns' => [
'starttime' => 'starttime',
'endtime' => 'endtime',
],

'iconfile' => 'EXT:fal_securedownload/Resources/Public/Icons/folder.png'
],
'interface' => [
'showRecordFieldList' => 'fe_groups, storage, folder, folder_hash'
'showRecordFieldList' => 'fe_groups, storage, folder, folder_hash, starttime, endtime'
],
'types' => [
'0' => ['showitem' => 'fe_groups,--palette--;;filePalette'],
'0' => ['showitem' => '--div--;LLL:EXT:fal_securedownload/Resources/Private/Language/locallang_db.xlf:feGroupAccess,
--palette--;;accessPalette,
--palette--;;filePalette,
--div--;LLL:EXT:fal_securedownload/Resources/Private/Language/locallang_db.xlf:timeRestrictions,
--palette--;;timeRestriction'],
],
'palettes' => [
'accessPalette' => [ 'showitem' => 'fe_groups' ],
'timeRestriction' => ['showitem' => 'starttime, endtime'],
// File palette, hidden but needs to be included all the time
'filePalette' => [
'showitem' => 'storage, folder, folder_hash',
Expand Down Expand Up @@ -80,6 +91,26 @@
'foreign_table_where' => 'ORDER BY fe_groups.title',
'enableMultiSelectFilterTextfield' => true,
]
],
'starttime' => [
'exclude' => true,
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int',
'default' => 0
]
],
'endtime' => [
'exclude' => true,
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int',
'default' => 0
]
]
]
];
19 changes: 18 additions & 1 deletion Configuration/TypoScript/setup.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,21 @@ page.jsFooterInline.303030.value (
$(this).next('ul').slideDown();
}
});
)
)

#config.tx_extbase {
# objects {
# TYPO3\CMS\Core\Resource\Folder {
# className = BeechIt\FalSecuredownload\Resource\Folder
# }
# }
# persistence {
# classes {
# BeechIt\FalSecuredownload\Resource\Folder {
# mapping {
# tableName = tx_falsecuredownload_folder
# }
# }
# }
# }
#}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ The access to assets can be set on folder/file bases by setting access to fe_gro

- Restrict FE access on folder level
- Restrict FE access on file level
- Restrict FE access by start/stop datetime on folder level
- Restrict FE access by start/stop datetime on file level
- Let editor set permissions in file list
- Force download for all files (for protected file storages)
- Force download for specific file extensions (for protected file storages)
Expand Down
7 changes: 6 additions & 1 deletion Resources/Private/Language/locallang_db.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@
<trans-unit id="folder">
<source>Folder</source>
</trans-unit>

<trans-unit id="feGroupAccess">
<source>Access FE Group/User</source>
</trans-unit>
<trans-unit id="timeRestrictions">
<source>Time Restrictions</source>
</trans-unit>
</body>
</file>
</xliff>
Loading