2015-08-28 03:21:57 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides additional file security for uploaded files when the securefiles module is installed
|
|
|
|
*
|
|
|
|
* {@see EditableFileField}
|
|
|
|
*/
|
2016-07-21 07:53:59 +02:00
|
|
|
class SecureEditableFileField extends DataExtension
|
|
|
|
{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Path to secure files location under assets
|
|
|
|
*
|
|
|
|
* @config
|
|
|
|
* @var type
|
|
|
|
*/
|
|
|
|
private static $secure_folder_name = 'SecureUploads';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Disable file security if a user-defined mechanism is in place
|
|
|
|
*
|
|
|
|
* @config
|
|
|
|
* @var bool
|
|
|
|
*/
|
|
|
|
private static $disable_security = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if file security is enabled
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function getIsSecurityEnabled()
|
|
|
|
{
|
|
|
|
// Skip if requested
|
|
|
|
if ($this->owner->config()->disable_security) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for necessary security module
|
|
|
|
if (!class_exists('SecureFileExtension')) {
|
|
|
|
trigger_error('SecureEditableFileField requires secureassets module', E_USER_WARNING);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function requireDefaultRecords()
|
|
|
|
{
|
|
|
|
// Skip if disabled
|
|
|
|
if (!$this->getIsSecurityEnabled()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update all instances of editablefilefield which do NOT have a secure folder assigned
|
|
|
|
foreach (EditableFileField::get() as $fileField) {
|
|
|
|
// Skip if secured
|
|
|
|
if ($fileField->getIsSecure()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Force this field to secure itself on write
|
|
|
|
$fileField->write(false, false, true);
|
|
|
|
DB::alteration_message(
|
|
|
|
"Restricting editable file field \"{$fileField->Title}\" to secure folder",
|
|
|
|
"changed"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Secure this field before saving
|
|
|
|
*/
|
|
|
|
public function onBeforeWrite()
|
|
|
|
{
|
|
|
|
$this->makeSecure();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ensure this field is secured, but does not write changes to the database
|
|
|
|
*/
|
|
|
|
public function makeSecure()
|
|
|
|
{
|
|
|
|
// Skip if disabled or already secure
|
|
|
|
if (!$this->getIsSecurityEnabled() || $this->owner->getIsSecure()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure folder exists
|
|
|
|
$folder = $this->owner->Folder();
|
|
|
|
if (!$folder || !$folder->exists()) {
|
|
|
|
// Create new folder in default location
|
|
|
|
$folder = Folder::find_or_make($this->owner->config()->secure_folder_name);
|
|
|
|
$this->owner->FolderID = $folder->ID;
|
|
|
|
} elseif ($this->isFolderSecured($folder)) {
|
|
|
|
// If folder exists and is secure stop
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make secure
|
|
|
|
$folder->CanViewType = 'OnlyTheseUsers';
|
|
|
|
$folder->ViewerGroups()->add($this->findAdminGroup());
|
|
|
|
$folder->write();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find target group to record
|
|
|
|
*
|
|
|
|
* @return Group
|
|
|
|
*/
|
|
|
|
protected function findAdminGroup()
|
|
|
|
{
|
|
|
|
singleton('Group')->requireDefaultRecords();
|
|
|
|
return Permission::get_groups_by_permission('ADMIN')->First();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if the field is secure
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function getIsSecure()
|
|
|
|
{
|
|
|
|
return $this->isFolderSecured($this->owner->Folder());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if a Folder object is secure
|
|
|
|
*
|
|
|
|
* @param Folder $folder
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
protected function isFolderSecured($folder)
|
|
|
|
{
|
|
|
|
if (! ($folder instanceof Folder) || !$folder->exists()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ($folder->CanViewType) {
|
|
|
|
case 'OnlyTheseUsers':
|
|
|
|
return true;
|
|
|
|
case 'Inherit':
|
|
|
|
$parent = $folder->Parent();
|
|
|
|
return $parent && $parent->exists() && $this->isFolderSecured($parent);
|
|
|
|
case 'Anyone':
|
|
|
|
case 'LoggedInUsers':
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2015-08-28 03:21:57 +02:00
|
|
|
}
|