Use new settings systems for attachments settings

This commit is contained in:
Jan Böhmer 2024-05-14 23:02:46 +02:00
parent 4876068cce
commit 26d83af298
12 changed files with 130 additions and 50 deletions

8
.env
View file

@ -35,16 +35,8 @@ DEFAULT_TIMEZONE="Europe/Berlin"
BASE_CURRENCY="EUR" BASE_CURRENCY="EUR"
# The name of this installation. This will be shown as title in the browser and in the header of the website # 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" 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 gravatars for user avatars, when user has no own avatar defined
USE_GRAVATAR=0 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 # 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! # This must end with a slash!

1
.gitignore vendored
View file

@ -2,6 +2,7 @@
/.env.local /.env.local
/.env.local.php /.env.local.php
/.env.*.local /.env.*.local
/.env.local.bak
/config/secrets/prod/prod.decrypt.private.php /config/secrets/prod/prod.decrypt.private.php
/public/bundles/ /public/bundles/
/var/ /var/

View file

@ -34,11 +34,8 @@ parameters:
###################################################################################################################### ######################################################################################################################
# Attachments and files # 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.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.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 # Error pages
@ -113,7 +110,6 @@ parameters:
env(INSTANCE_NAME): 'Part-DB' env(INSTANCE_NAME): 'Part-DB'
env(BASE_CURRENCY): 'EUR' env(BASE_CURRENCY): 'EUR'
env(USE_GRAVATAR): '0' env(USE_GRAVATAR): '0'
env(MAX_ATTACHMENT_FILE_SIZE): '100M'
env(REDIRECT_TO_HTTPS): 0 env(REDIRECT_TO_HTTPS): 0

View file

@ -89,17 +89,9 @@ services:
tags: tags:
- { name: 'doctrine.event_subscriber' } - { 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: App\Services\Attachments\AttachmentSubmitHandler:
arguments: arguments:
$allow_attachments_downloads: '%partdb.attachments.allow_downloads%'
$mimeTypes: '@mime_types' $mimeTypes: '@mime_types'
$max_upload_size: '%partdb.attachments.max_file_size%'
App\Services\LogSystem\EventCommentNeededHelper: App\Services\LogSystem\EventCommentNeededHelper:
arguments: arguments:

View file

@ -28,6 +28,7 @@ use App\Services\Attachments\BuiltinAttachmentsFinder;
use App\Services\Misc\GitVersionInfo; use App\Services\Misc\GitVersionInfo;
use App\Services\Misc\DBInfoHelper; use App\Services\Misc\DBInfoHelper;
use App\Services\System\UpdateAvailableManager; use App\Services\System\UpdateAvailableManager;
use App\Settings\AppSettings;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
@ -45,7 +46,8 @@ class ToolsController extends AbstractController
#[Route(path: '/server_infos', name: 'tools_server_infos')] #[Route(path: '/server_infos', name: 'tools_server_infos')]
public function systemInfos(GitVersionInfo $versionInfo, DBInfoHelper $DBInfoHelper, public function systemInfos(GitVersionInfo $versionInfo, DBInfoHelper $DBInfoHelper,
AttachmentSubmitHandler $attachmentSubmitHandler, UpdateAvailableManager $updateAvailableManager): Response AttachmentSubmitHandler $attachmentSubmitHandler, UpdateAvailableManager $updateAvailableManager,
AppSettings $settings): Response
{ {
$this->denyAccessUnlessGranted('@system.server_infos'); $this->denyAccessUnlessGranted('@system.server_infos');
@ -66,10 +68,10 @@ class ToolsController extends AbstractController
'is_debug' => $this->getParameter('kernel.debug'), 'is_debug' => $this->getParameter('kernel.debug'),
'email_sender' => $this->getParameter('partdb.mail.sender_email'), 'email_sender' => $this->getParameter('partdb.mail.sender_email'),
'email_sender_name' => $this->getParameter('partdb.mail.sender_name'), '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'), 'detailed_error_pages' => $this->getParameter('partdb.error_pages.show_help'),
'error_page_admin_email' => $this->getParameter('partdb.error_pages.admin_email'), '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(), 'effective_max_file_size' => $attachmentSubmitHandler->getMaximumAllowedUploadSize(),
'saml_enabled' => $this->getParameter('partdb.saml.enabled'), 'saml_enabled' => $this->getParameter('partdb.saml.enabled'),

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Form; namespace App\Form;
use App\Settings\SystemSettings\AttachmentsSettings;
use Symfony\Bundle\SecurityBundle\Security; use Symfony\Bundle\SecurityBundle\Security;
use App\Entity\Attachments\Attachment; use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentType;
@ -54,9 +55,7 @@ class AttachmentFormType extends AbstractType
protected Security $security, protected Security $security,
protected AttachmentSubmitHandler $submitHandler, protected AttachmentSubmitHandler $submitHandler,
protected TranslatorInterface $translator, protected TranslatorInterface $translator,
protected bool $allow_attachments_download, protected AttachmentsSettings $settings,
protected bool $download_by_default,
protected string $max_file_size
) { ) {
} }
@ -108,7 +107,7 @@ class AttachmentFormType extends AbstractType
'required' => false, 'required' => false,
'label' => 'attachment.edit.download_url', 'label' => 'attachment.edit.download_url',
'mapped' => false, 'mapped' => false,
'disabled' => !$this->allow_attachments_download, 'disabled' => !$this->settings->allowDownloads,
]); ]);
$builder->add('file', FileType::class, [ $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, //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 // 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 { $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event): void {
$form = $event->getForm(); $form = $event->getForm();
$attachment = $form->getData(); $attachment = $form->getData();
@ -204,7 +203,7 @@ class AttachmentFormType extends AbstractType
{ {
$resolver->setDefaults([ $resolver->setDefaults([
'data_class' => Attachment::class, 'data_class' => Attachment::class,
'max_file_size' => $this->max_file_size, 'max_file_size' => $this->settings->maxFileSize,
'allow_builtins' => true, 'allow_builtins' => true,
]); ]);
} }

View file

@ -40,6 +40,7 @@ use App\Entity\Attachments\StorageLocationAttachment;
use App\Entity\Attachments\SupplierAttachment; use App\Entity\Attachments\SupplierAttachment;
use App\Entity\Attachments\UserAttachment; use App\Entity\Attachments\UserAttachment;
use App\Exceptions\AttachmentDownloadException; use App\Exceptions\AttachmentDownloadException;
use App\Settings\SystemSettings\AttachmentsSettings;
use Hshn\Base64EncodedFile\HttpFoundation\File\Base64EncodedFile; use Hshn\Base64EncodedFile\HttpFoundation\File\Base64EncodedFile;
use Hshn\Base64EncodedFile\HttpFoundation\File\UploadedBase64EncodedFile; use Hshn\Base64EncodedFile\HttpFoundation\File\UploadedBase64EncodedFile;
use const DIRECTORY_SEPARATOR; 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', 'asp', 'cgi', 'py', 'pl', 'exe', 'aspx', 'js', 'mjs', 'jsp', 'css', 'jar', 'html', 'htm', 'shtm', 'shtml', 'htaccess',
'htpasswd', '']; 'htpasswd', ''];
public function __construct(protected AttachmentPathResolver $pathResolver, protected bool $allow_attachments_downloads, public function __construct(
protected HttpClientInterface $httpClient, protected MimeTypesInterface $mimeTypes, protected AttachmentPathResolver $pathResolver,
protected FileTypeFilterTools $filterTools, /** protected HttpClientInterface $httpClient,
* @var string The user configured maximum upload size. This is a string like "10M" or "1G" and will be converted to protected MimeTypesInterface $mimeTypes,
*/ protected FileTypeFilterTools $filterTools,
protected string $max_upload_size) protected AttachmentsSettings $settings,
)
{ {
//The mapping used to determine which folder will be used for an attachment type //The mapping used to determine which folder will be used for an attachment type
$this->folder_mapping = [ $this->folder_mapping = [
@ -334,7 +336,7 @@ class AttachmentSubmitHandler
protected function downloadURL(Attachment $attachment, bool $secureAttachment): Attachment protected function downloadURL(Attachment $attachment, bool $secureAttachment): Attachment
{ {
//Check if we are allowed to download files //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!'); throw new RuntimeException('Download of attachments is not allowed!');
} }
@ -472,7 +474,7 @@ class AttachmentSubmitHandler
$this->max_upload_size_bytes = min( $this->max_upload_size_bytes = min(
$this->parseFileSizeString(ini_get('post_max_size')), $this->parseFileSizeString(ini_get('post_max_size')),
$this->parseFileSizeString(ini_get('upload_max_filesize')), $this->parseFileSizeString(ini_get('upload_max_filesize')),
$this->parseFileSizeString($this->max_upload_size), $this->parseFileSizeString($this->settings->maxFileSize)
); );
return $this->max_upload_size_bytes; return $this->max_upload_size_bytes;

View file

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace App\Settings; namespace App\Settings;
use App\Settings\InfoProviderSystem\InfoProviderSettings; use App\Settings\InfoProviderSystem\InfoProviderSettings;
use App\Settings\SystemSettings\AttachmentsSettings;
use Jbtronics\SettingsBundle\Settings\EmbeddedSettings; use Jbtronics\SettingsBundle\Settings\EmbeddedSettings;
use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\Settings;
use Jbtronics\SettingsBundle\Settings\SettingsTrait; use Jbtronics\SettingsBundle\Settings\SettingsTrait;
@ -33,9 +34,11 @@ class AppSettings
{ {
use SettingsTrait; use SettingsTrait;
#[EmbeddedSettings()]
public ?InfoProviderSettings $infoProviders = null;
#[EmbeddedSettings()] #[EmbeddedSettings()]
public ?TestSettings $test = null; public ?SystemSettings $system;
#[EmbeddedSettings()]
public ?InfoProviderSettings $infoProviders = null;
} }

View file

@ -23,18 +23,13 @@ declare(strict_types=1);
namespace App\Settings; namespace App\Settings;
use App\Settings\SystemSettings\AttachmentsSettings;
use Jbtronics\SettingsBundle\Settings\EmbeddedSettings;
use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\Settings;
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
#[Settings] #[Settings]
class TestSettings class SystemSettings
{ {
#[SettingsParameter()] #[EmbeddedSettings()]
public bool $bool = false; public ?AttachmentsSettings $attachments = null;
#[SettingsParameter()]
public int $int = 0;
#[SettingsParameter()]
public float $float = 0.0;
} }

View file

@ -0,0 +1,56 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2024 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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;
}

View file

@ -12377,5 +12377,41 @@ Please note, that you can not impersonate a disabled user. If you try you will g
<target>Currency</target> <target>Currency</target>
</segment> </segment>
</unit> </unit>
<unit id="g0AgaAf" name="settings.system.attachments">
<segment>
<source>settings.system.attachments</source>
<target><![CDATA[Attachments & Files]]></target>
</segment>
</unit>
<unit id="1wsDvqz" name="settings.system.attachments.maxFileSize">
<segment>
<source>settings.system.attachments.maxFileSize</source>
<target>Maximum file size</target>
</segment>
</unit>
<unit id="Gn0P1Bv" name="settings.system.attachments.maxFileSize.help">
<segment>
<source>settings.system.attachments.maxFileSize.help</source>
<target>The maximum size of files that can be uploaded. Please note that this is also limited by PHP configuration.</target>
</segment>
</unit>
<unit id="DyIfVYH" name="settings.system.attachments.allowDownloads">
<segment>
<source>settings.system.attachments.allowDownloads</source>
<target>Allow downloading of external files</target>
</segment>
</unit>
<unit id="jD.pgZL" name="settings.system.attachments.allowDownloads.help">
<segment>
<source>settings.system.attachments.allowDownloads.help</source>
<target><![CDATA[With this option users can download external files into Part-DB by providing an URL. <b>Attention: This can be a security issue, as it might allow users to access intranet ressources via Part-DB!</b>]]></target>
</segment>
</unit>
<unit id="HRxjf.u" name="settings.system.attachments.downloadByDefault">
<segment>
<source>settings.system.attachments.downloadByDefault</source>
<target>Download new attachment URLs by default</target>
</segment>
</unit>
</file> </file>
</xliff> </xliff>

View file

@ -347,5 +347,11 @@
<target>Due to technical limitations, it is not possible to select dates after the 2038-01-19 on 32-bit systems!</target> <target>Due to technical limitations, it is not possible to select dates after the 2038-01-19 on 32-bit systems!</target>
</segment> </segment>
</unit> </unit>
<unit id="89nojXY" name="validator.fileSize.invalidFormat">
<segment>
<source>validator.fileSize.invalidFormat</source>
<target>Invalid file size format. Use an integer number plus K, M, G as suffix for Kilo, Mega or Gigabytes.</target>
</segment>
</unit>
</file> </file>
</xliff> </xliff>