From 26d83af298cdf577ed2e3599e75d1219e6029e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Tue, 14 May 2024 23:02:46 +0200 Subject: [PATCH] Use new settings systems for attachments settings --- .env | 8 --- .gitignore | 1 + config/parameters.yaml | 4 -- config/services.yaml | 8 --- src/Controller/ToolsController.php | 8 ++- src/Form/AttachmentFormType.php | 11 ++-- .../Attachments/AttachmentSubmitHandler.php | 18 +++--- src/Settings/AppSettings.php | 9 ++- .../{TestSettings.php => SystemSettings.php} | 15 ++--- .../SystemSettings/AttachmentsSettings.php | 56 +++++++++++++++++++ translations/messages.en.xlf | 36 ++++++++++++ translations/validators.en.xlf | 6 ++ 12 files changed, 130 insertions(+), 50 deletions(-) rename src/Settings/{TestSettings.php => SystemSettings.php} (79%) create mode 100644 src/Settings/SystemSettings/AttachmentsSettings.php diff --git a/.env b/.env index 8e48085e..26204360 100644 --- a/.env +++ b/.env @@ -35,16 +35,8 @@ DEFAULT_TIMEZONE="Europe/Berlin" BASE_CURRENCY="EUR" # The name of this installation. This will be shown as title in the browser and in the header of the website INSTANCE_NAME="Part-DB" -# Allow users to download attachments to the server by providing an URL -# This could be a potential security issue, as the user can retrieve any file the server has access to (via internet) -ALLOW_ATTACHMENT_DOWNLOADS=0 -# Set this to 1, if the "download external files" checkbox should be checked by default for new attachments -ATTACHMENT_DOWNLOAD_BY_DEFAULT=0 # Use gravatars for user avatars, when user has no own avatar defined USE_GRAVATAR=0 -# The maximum allowed size for attachment files in bytes (you can use M for megabytes and G for gigabytes) -# Please note that the php.ini setting upload_max_filesize also limits the maximum size of uploaded files -MAX_ATTACHMENT_FILE_SIZE="100M" # The public reachable URL of this Part-DB installation. This is used for generating links in SAML and email templates # This must end with a slash! diff --git a/.gitignore b/.gitignore index b726f64c..c8c59090 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /.env.local /.env.local.php /.env.*.local +/.env.local.bak /config/secrets/prod/prod.decrypt.private.php /public/bundles/ /var/ diff --git a/config/parameters.yaml b/config/parameters.yaml index 4caa5780..205b31a8 100644 --- a/config/parameters.yaml +++ b/config/parameters.yaml @@ -34,11 +34,8 @@ parameters: ###################################################################################################################### # Attachments and files ###################################################################################################################### - partdb.attachments.allow_downloads: '%env(bool:ALLOW_ATTACHMENT_DOWNLOADS)%' # Allow users to download attachments to server. Warning: This can be dangerous, because via that feature attackers maybe can access ressources on your intranet! - partdb.attachments.download_by_default: '%env(bool:ATTACHMENT_DOWNLOAD_BY_DEFAULT)%' # If this is set the 'download external files' checkbox is set by default for new attachments (only if allow_downloads is set to true) partdb.attachments.dir.media: 'public/media/' # The folder where uploaded attachment files are saved (must be in public folder) partdb.attachments.dir.secure: 'uploads/' # The folder where secured attachment files are saved (must not be in public/) - partdb.attachments.max_file_size: '%env(string:MAX_ATTACHMENT_FILE_SIZE)%' # The maximum size of an attachment file (in bytes, you can use M for megabytes and G for gigabytes) ###################################################################################################################### # Error pages @@ -113,7 +110,6 @@ parameters: env(INSTANCE_NAME): 'Part-DB' env(BASE_CURRENCY): 'EUR' env(USE_GRAVATAR): '0' - env(MAX_ATTACHMENT_FILE_SIZE): '100M' env(REDIRECT_TO_HTTPS): 0 diff --git a/config/services.yaml b/config/services.yaml index 292c532f..7264783e 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -89,17 +89,9 @@ services: tags: - { name: 'doctrine.event_subscriber' } - App\Form\AttachmentFormType: - arguments: - $allow_attachments_download: '%partdb.attachments.allow_downloads%' - $max_file_size: '%partdb.attachments.max_file_size%' - $download_by_default: '%partdb.attachments.download_by_default%' - App\Services\Attachments\AttachmentSubmitHandler: arguments: - $allow_attachments_downloads: '%partdb.attachments.allow_downloads%' $mimeTypes: '@mime_types' - $max_upload_size: '%partdb.attachments.max_file_size%' App\Services\LogSystem\EventCommentNeededHelper: arguments: diff --git a/src/Controller/ToolsController.php b/src/Controller/ToolsController.php index 984e50eb..040e418c 100644 --- a/src/Controller/ToolsController.php +++ b/src/Controller/ToolsController.php @@ -28,6 +28,7 @@ use App\Services\Attachments\BuiltinAttachmentsFinder; use App\Services\Misc\GitVersionInfo; use App\Services\Misc\DBInfoHelper; use App\Services\System\UpdateAvailableManager; +use App\Settings\AppSettings; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; @@ -45,7 +46,8 @@ class ToolsController extends AbstractController #[Route(path: '/server_infos', name: 'tools_server_infos')] public function systemInfos(GitVersionInfo $versionInfo, DBInfoHelper $DBInfoHelper, - AttachmentSubmitHandler $attachmentSubmitHandler, UpdateAvailableManager $updateAvailableManager): Response + AttachmentSubmitHandler $attachmentSubmitHandler, UpdateAvailableManager $updateAvailableManager, + AppSettings $settings): Response { $this->denyAccessUnlessGranted('@system.server_infos'); @@ -66,10 +68,10 @@ class ToolsController extends AbstractController 'is_debug' => $this->getParameter('kernel.debug'), 'email_sender' => $this->getParameter('partdb.mail.sender_email'), 'email_sender_name' => $this->getParameter('partdb.mail.sender_name'), - 'allow_attachments_downloads' => $this->getParameter('partdb.attachments.allow_downloads'), + 'allow_attachments_downloads' => $settings->system->attachments->allowDownloads, 'detailed_error_pages' => $this->getParameter('partdb.error_pages.show_help'), 'error_page_admin_email' => $this->getParameter('partdb.error_pages.admin_email'), - 'configured_max_file_size' => $this->getParameter('partdb.attachments.max_file_size'), + 'configured_max_file_size' => $settings->system->attachments->maxFileSize, 'effective_max_file_size' => $attachmentSubmitHandler->getMaximumAllowedUploadSize(), 'saml_enabled' => $this->getParameter('partdb.saml.enabled'), diff --git a/src/Form/AttachmentFormType.php b/src/Form/AttachmentFormType.php index 109c6602..b9963bed 100644 --- a/src/Form/AttachmentFormType.php +++ b/src/Form/AttachmentFormType.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace App\Form; +use App\Settings\SystemSettings\AttachmentsSettings; use Symfony\Bundle\SecurityBundle\Security; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentType; @@ -54,9 +55,7 @@ class AttachmentFormType extends AbstractType protected Security $security, protected AttachmentSubmitHandler $submitHandler, protected TranslatorInterface $translator, - protected bool $allow_attachments_download, - protected bool $download_by_default, - protected string $max_file_size + protected AttachmentsSettings $settings, ) { } @@ -108,7 +107,7 @@ class AttachmentFormType extends AbstractType 'required' => false, 'label' => 'attachment.edit.download_url', 'mapped' => false, - 'disabled' => !$this->allow_attachments_download, + 'disabled' => !$this->settings->allowDownloads, ]); $builder->add('file', FileType::class, [ @@ -177,7 +176,7 @@ class AttachmentFormType extends AbstractType //If the attachment should be downloaded by default (and is download allowed at all), register a listener, // which sets the downloadURL checkbox to true for new attachments - if ($this->download_by_default && $this->allow_attachments_download) { + if ($this->settings->downloadByDefault && $this->settings->allowDownloads) { $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event): void { $form = $event->getForm(); $attachment = $form->getData(); @@ -204,7 +203,7 @@ class AttachmentFormType extends AbstractType { $resolver->setDefaults([ 'data_class' => Attachment::class, - 'max_file_size' => $this->max_file_size, + 'max_file_size' => $this->settings->maxFileSize, 'allow_builtins' => true, ]); } diff --git a/src/Services/Attachments/AttachmentSubmitHandler.php b/src/Services/Attachments/AttachmentSubmitHandler.php index d5fe9370..2cd9a153 100644 --- a/src/Services/Attachments/AttachmentSubmitHandler.php +++ b/src/Services/Attachments/AttachmentSubmitHandler.php @@ -40,6 +40,7 @@ use App\Entity\Attachments\StorageLocationAttachment; use App\Entity\Attachments\SupplierAttachment; use App\Entity\Attachments\UserAttachment; use App\Exceptions\AttachmentDownloadException; +use App\Settings\SystemSettings\AttachmentsSettings; use Hshn\Base64EncodedFile\HttpFoundation\File\Base64EncodedFile; use Hshn\Base64EncodedFile\HttpFoundation\File\UploadedBase64EncodedFile; use const DIRECTORY_SEPARATOR; @@ -64,12 +65,13 @@ class AttachmentSubmitHandler 'asp', 'cgi', 'py', 'pl', 'exe', 'aspx', 'js', 'mjs', 'jsp', 'css', 'jar', 'html', 'htm', 'shtm', 'shtml', 'htaccess', 'htpasswd', '']; - public function __construct(protected AttachmentPathResolver $pathResolver, protected bool $allow_attachments_downloads, - protected HttpClientInterface $httpClient, protected MimeTypesInterface $mimeTypes, - protected FileTypeFilterTools $filterTools, /** - * @var string The user configured maximum upload size. This is a string like "10M" or "1G" and will be converted to - */ - protected string $max_upload_size) + public function __construct( + protected AttachmentPathResolver $pathResolver, + protected HttpClientInterface $httpClient, + protected MimeTypesInterface $mimeTypes, + protected FileTypeFilterTools $filterTools, + protected AttachmentsSettings $settings, + ) { //The mapping used to determine which folder will be used for an attachment type $this->folder_mapping = [ @@ -334,7 +336,7 @@ class AttachmentSubmitHandler protected function downloadURL(Attachment $attachment, bool $secureAttachment): Attachment { //Check if we are allowed to download files - if (!$this->allow_attachments_downloads) { + if (!$this->settings->allowDownloads) { throw new RuntimeException('Download of attachments is not allowed!'); } @@ -472,7 +474,7 @@ class AttachmentSubmitHandler $this->max_upload_size_bytes = min( $this->parseFileSizeString(ini_get('post_max_size')), $this->parseFileSizeString(ini_get('upload_max_filesize')), - $this->parseFileSizeString($this->max_upload_size), + $this->parseFileSizeString($this->settings->maxFileSize) ); return $this->max_upload_size_bytes; diff --git a/src/Settings/AppSettings.php b/src/Settings/AppSettings.php index fd0a8c6d..6bd19894 100644 --- a/src/Settings/AppSettings.php +++ b/src/Settings/AppSettings.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace App\Settings; use App\Settings\InfoProviderSystem\InfoProviderSettings; +use App\Settings\SystemSettings\AttachmentsSettings; use Jbtronics\SettingsBundle\Settings\EmbeddedSettings; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsTrait; @@ -33,9 +34,11 @@ class AppSettings { use SettingsTrait; - #[EmbeddedSettings()] - public ?InfoProviderSettings $infoProviders = null; #[EmbeddedSettings()] - public ?TestSettings $test = null; + public ?SystemSettings $system; + + + #[EmbeddedSettings()] + public ?InfoProviderSettings $infoProviders = null; } \ No newline at end of file diff --git a/src/Settings/TestSettings.php b/src/Settings/SystemSettings.php similarity index 79% rename from src/Settings/TestSettings.php rename to src/Settings/SystemSettings.php index 42020546..b8aafd57 100644 --- a/src/Settings/TestSettings.php +++ b/src/Settings/SystemSettings.php @@ -23,18 +23,13 @@ declare(strict_types=1); namespace App\Settings; +use App\Settings\SystemSettings\AttachmentsSettings; +use Jbtronics\SettingsBundle\Settings\EmbeddedSettings; use Jbtronics\SettingsBundle\Settings\Settings; -use Jbtronics\SettingsBundle\Settings\SettingsParameter; #[Settings] -class TestSettings +class SystemSettings { - #[SettingsParameter()] - public bool $bool = false; - - #[SettingsParameter()] - public int $int = 0; - - #[SettingsParameter()] - public float $float = 0.0; + #[EmbeddedSettings()] + public ?AttachmentsSettings $attachments = null; } \ No newline at end of file diff --git a/src/Settings/SystemSettings/AttachmentsSettings.php b/src/Settings/SystemSettings/AttachmentsSettings.php new file mode 100644 index 00000000..e7c49fd7 --- /dev/null +++ b/src/Settings/SystemSettings/AttachmentsSettings.php @@ -0,0 +1,56 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\SystemSettings; + +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; +use Jbtronics\SettingsBundle\Settings\Settings; +use Jbtronics\SettingsBundle\Settings\SettingsParameter; +use Symfony\Component\Translation\TranslatableMessage as TM; +use Symfony\Component\Validator\Constraints as Assert; + +#[Settings(label: new TM("settings.system.attachments"))] +class AttachmentsSettings +{ + #[SettingsParameter( + label: new TM("settings.system.attachments.maxFileSize"), + description: new TM("settings.system.attachments.maxFileSize.help"), + envVar: "MAX_ATTACHMENT_FILE_SIZE", envVarMode: EnvVarMode::OVERWRITE + )] + #[Assert\Regex("/^([1-9][0-9]*)([KMG])?$/", message: "validator.fileSize.invalidFormat")] + public string $maxFileSize = '100M'; + + #[SettingsParameter( + label: new TM("settings.system.attachments.allowDownloads"), + description: new TM("settings.system.attachments.allowDownloads.help"), + formOptions: ['help_html' => true], + envVar: "bool:ALLOW_ATTACHMENT_DOWNLOADS", envVarMode: EnvVarMode::OVERWRITE + )] + public bool $allowDownloads = false; + + #[SettingsParameter( + label: new TM("settings.system.attachments.downloadByDefault"), + envVar: "bool:ATTACHMENT_DOWNLOAD_BY_DEFAULT", envVarMode: EnvVarMode::OVERWRITE + )] + public bool $downloadByDefault = false; +} \ No newline at end of file diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 636b5b90..a0165885 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -12377,5 +12377,41 @@ Please note, that you can not impersonate a disabled user. If you try you will g Currency + + + settings.system.attachments + + + + + + settings.system.attachments.maxFileSize + Maximum file size + + + + + settings.system.attachments.maxFileSize.help + The maximum size of files that can be uploaded. Please note that this is also limited by PHP configuration. + + + + + settings.system.attachments.allowDownloads + Allow downloading of external files + + + + + settings.system.attachments.allowDownloads.help + Attention: This can be a security issue, as it might allow users to access intranet ressources via Part-DB!]]> + + + + + settings.system.attachments.downloadByDefault + Download new attachment URLs by default + + diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf index cec89ea6..5c437129 100644 --- a/translations/validators.en.xlf +++ b/translations/validators.en.xlf @@ -347,5 +347,11 @@ Due to technical limitations, it is not possible to select dates after the 2038-01-19 on 32-bit systems! + + + validator.fileSize.invalidFormat + Invalid file size format. Use an integer number plus K, M, G as suffix for Kilo, Mega or Gigabytes. + +