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