diff --git a/Classes/Hooks/FileDumpHook.php b/Classes/Hooks/FileDumpHook.php
index cd02f04..b4f64b0 100644
--- a/Classes/Hooks/FileDumpHook.php
+++ b/Classes/Hooks/FileDumpHook.php
@@ -79,6 +79,11 @@ class FileDumpHook implements FileDumpEIDHookInterface
*/
protected $resumableDownload = false;
+ /**
+ * @var $checkPermissionsService CheckPermissions
+ */
+ protected $checkPermissionsService = false;
+
/**
* Constructor
*/
@@ -102,6 +107,9 @@ public function __construct()
$this->forceDownloadForExt = ExtensionConfiguration::forceDownloadForExt();
}
$this->resumableDownload = ExtensionConfiguration::resumableDownload();
+
+ $this->checkPermissionsService = GeneralUtility::makeInstance(CheckPermissions::class);
+
}
/**
@@ -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;
}
}
@@ -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) {
diff --git a/Classes/Security/CheckPermissions.php b/Classes/Security/CheckPermissions.php
index dba8b32..d1064e0 100644
--- a/Classes/Security/CheckPermissions.php
+++ b/Classes/Security/CheckPermissions.php
@@ -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);
@@ -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
@@ -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
*
@@ -127,7 +208,6 @@ public function checkFolderRootLineAccess(Folder $folder, $userFeGroups)
$folder->getHashedIdentifier() .
serialize($userFeGroups)
);
-
if (!isset($this->checkFolderRootLineAccessCache[$cacheIdentifier])) {
$this->checkFolderRootLineAccessCache[$cacheIdentifier] = true;
diff --git a/Classes/Service/Utility.php b/Classes/Service/Utility.php
index 9fd491a..b2f8ba0 100644
--- a/Classes/Service/Utility.php
+++ b/Classes/Service/Utility.php
@@ -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()];
}
diff --git a/Classes/ViewHelpers/Security/AssetAccessViewHelper.php b/Classes/ViewHelpers/Security/AssetAccessViewHelper.php
index 0b4ced3..a74d5f0 100644
--- a/Classes/ViewHelpers/Security/AssetAccessViewHelper.php
+++ b/Classes/ViewHelpers/Security/AssetAccessViewHelper.php
@@ -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;
@@ -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) {
diff --git a/Configuration/TCA/Overrides/sys_file_metadata.php b/Configuration/TCA/Overrides/sys_file_metadata.php
index 431f767..426e29f 100644
--- a/Configuration/TCA/Overrides/sys_file_metadata.php
+++ b/Configuration/TCA/Overrides/sys_file_metadata.php
@@ -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');
diff --git a/Configuration/TCA/tx_falsecuredownload_folder.php b/Configuration/TCA/tx_falsecuredownload_folder.php
index 5de07ff..434b6aa 100644
--- a/Configuration/TCA/tx_falsecuredownload_folder.php
+++ b/Configuration/TCA/tx_falsecuredownload_folder.php
@@ -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',
@@ -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
+ ]
]
]
];
diff --git a/Configuration/TypoScript/setup.txt b/Configuration/TypoScript/setup.txt
index 1f0b547..72b3bbb 100644
--- a/Configuration/TypoScript/setup.txt
+++ b/Configuration/TypoScript/setup.txt
@@ -36,4 +36,21 @@ page.jsFooterInline.303030.value (
$(this).next('ul').slideDown();
}
});
-)
\ No newline at end of file
+)
+
+#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
+# }
+# }
+# }
+# }
+#}
\ No newline at end of file
diff --git a/README.md b/README.md
index a4c1656..6a4e714 100644
--- a/README.md
+++ b/README.md
@@ -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)
diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf
index 5f91bd2..a5a5bf3 100644
--- a/Resources/Private/Language/locallang_db.xlf
+++ b/Resources/Private/Language/locallang_db.xlf
@@ -13,7 +13,12 @@
Folder
-
+
+ Access FE Group/User
+
+
+ Time Restrictions
+