mirror of
https://github.com/silverstripe/silverstripe-userforms.git
synced 2024-10-22 17:05:42 +02:00
145 lines
3.2 KiB
PHP
145 lines
3.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Provides additional file security for uploaded files when the securefiles module is installed
|
|
*
|
|
* {@see EditableFileField}
|
|
*/
|
|
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;
|
|
}
|
|
}
|
|
}
|