Merge branch 'master' into settings-bundle

This commit is contained in:
Jan Böhmer 2025-01-17 22:06:18 +01:00
commit 8750573724
191 changed files with 27745 additions and 12133 deletions

View file

@ -531,7 +531,7 @@ abstract class Attachment extends AbstractNamedDBElement
$url = str_replace(' ', '%20', $url);
//Only set if the URL is not empty
if ($url !== null && $url !== '') {
if ($url !== '') {
if (str_contains($url, '%BASE%') || str_contains($url, '%MEDIA%')) {
throw new InvalidArgumentException('You can not reference internal files via the url field! But nice try!');
}

View file

@ -33,7 +33,7 @@ use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @template-covariant AT of Attachment
* @template AT of Attachment
*/
#[ORM\MappedSuperclass(repositoryClass: AttachmentContainingDBElementRepository::class)]
abstract class AttachmentContainingDBElement extends AbstractNamedDBElement implements HasMasterAttachmentInterface, HasAttachmentsInterface

View file

@ -33,8 +33,8 @@ use Symfony\Component\Validator\Constraints as Assert;
/**
* This abstract class is used for companies like suppliers or manufacturers.
*
* @template-covariant AT of Attachment
* @template-covariant PT of AbstractParameter
* @template AT of Attachment
* @template PT of AbstractParameter
* @extends AbstractPartsContainingDBElement<AT, PT>
*/
#[ORM\MappedSuperclass]

View file

@ -31,8 +31,8 @@ use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @template-covariant AT of Attachment
* @template-covariant PT of AbstractParameter
* @template AT of Attachment
* @template PT of AbstractParameter
* @extends AbstractStructuralDBElement<AT, PT>
*/
#[ORM\MappedSuperclass(repositoryClass: AbstractPartsContainingRepository::class)]

View file

@ -53,8 +53,8 @@ use Symfony\Component\Serializer\Annotation\Groups;
*
* @see \App\Tests\Entity\Base\AbstractStructuralDBElementTest
*
* @template-covariant AT of Attachment
* @template-covariant PT of AbstractParameter
* @template AT of Attachment
* @template PT of AbstractParameter
* @template-use ParametersTrait<PT>
* @extends AttachmentContainingDBElement<AT>
* @uses ParametersTrait<PT>

View file

@ -22,6 +22,8 @@ declare(strict_types=1);
*/
namespace App\Entity\LabelSystem;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Base\AbstractNamedDBElement;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartLot;
use App\Entity\Parts\StorageLocation;
@ -34,7 +36,7 @@ enum LabelSupportedElement: string
/**
* Returns the entity class for the given element type
* @return string
* @return class-string<AbstractDBElement>
*/
public function getEntityClass(): string
{

View file

@ -44,9 +44,9 @@ namespace App\Entity\LogSystem;
use App\Entity\Base\AbstractDBElement;
use App\Entity\UserSystem\User;
use App\Events\SecurityEvents;
use App\Helpers\IPAnonymizer;
use Doctrine\ORM\Mapping as ORM;
use InvalidArgumentException;
use Symfony\Component\HttpFoundation\IpUtils;
/**
* This log entry is created when something security related to a user happens.
@ -127,14 +127,14 @@ class SecurityEventLogEntry extends AbstractLogEntry
* Sets the IP address used to log in the user.
*
* @param string $ip the IP address used to log in the user
* @param bool $anonymize Anonymize the IP address (remove last block) to be GPDR compliant
* @param bool $anonymize Anonymize the IP address (remove last block) to be GDPR compliant
*
* @return $this
*/
public function setIPAddress(string $ip, bool $anonymize = true): self
{
if ($anonymize) {
$ip = IpUtils::anonymize($ip);
$ip = IPAnonymizer::anonymize($ip);
}
$this->extra['i'] = $ip;

View file

@ -22,8 +22,9 @@ declare(strict_types=1);
namespace App\Entity\LogSystem;
use App\Helpers\IPAnonymizer;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\IpUtils;
/**
* This log entry is created when a user logs in.
@ -52,14 +53,14 @@ class UserLoginLogEntry extends AbstractLogEntry
* Sets the IP address used to log in the user.
*
* @param string $ip the IP address used to log in the user
* @param bool $anonymize Anonymize the IP address (remove last block) to be GPDR compliant
* @param bool $anonymize Anonymize the IP address (remove last block) to be GDPR compliant
*
* @return $this
*/
public function setIPAddress(string $ip, bool $anonymize = true): self
{
if ($anonymize) {
$ip = IpUtils::anonymize($ip);
$ip = IPAnonymizer::anonymize($ip);
}
$this->extra['i'] = $ip;

View file

@ -22,8 +22,8 @@ declare(strict_types=1);
namespace App\Entity\LogSystem;
use App\Helpers\IPAnonymizer;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\IpUtils;
#[ORM\Entity]
class UserLogoutLogEntry extends AbstractLogEntry
@ -49,14 +49,14 @@ class UserLogoutLogEntry extends AbstractLogEntry
* Sets the IP address used to log in the user.
*
* @param string $ip the IP address used to log in the user
* @param bool $anonymize Anonymize the IP address (remove last block) to be GPDR compliant
* @param bool $anonymize Anonymize the IP address (remove last block) to be GDPR compliant
*
* @return $this
*/
public function setIPAddress(string $ip, bool $anonymize = true): self
{
if ($anonymize) {
$ip = IpUtils::anonymize($ip);
$ip = IPAnonymizer::anonymize($ip);
}
$this->extra['i'] = $ip;

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts;
use App\ApiPlatform\Filter\TagFilter;
use Doctrine\Common\Collections\Criteria;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
@ -97,7 +98,8 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[ApiFilter(PropertyFilter::class)]
#[ApiFilter(EntityFilter::class, properties: ["category", "footprint", "manufacturer", "partUnit"])]
#[ApiFilter(PartStoragelocationFilter::class, properties: ["storage_location"])]
#[ApiFilter(LikeFilter::class, properties: ["name", "comment", "description", "ipn", "tags", "manufacturer_product_number"])]
#[ApiFilter(LikeFilter::class, properties: ["name", "comment", "description", "ipn", "manufacturer_product_number"])]
#[ApiFilter(TagFilter::class, properties: ["tags"])]
#[ApiFilter(BooleanFilter::class, properties: ["favorite" , "needs_review"])]
#[ApiFilter(RangeFilter::class, properties: ["mass", "minamount"])]
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
@ -118,7 +120,7 @@ class Part extends AttachmentContainingDBElement
/** @var Collection<int, PartParameter>
*/
#[Assert\Valid]
#[Groups(['full', 'part:read', 'part:write'])]
#[Groups(['full', 'part:read', 'part:write', 'import'])]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: PartParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])]
#[UniqueObjectCollection(fields: ['name', 'group', 'element'])]

View file

@ -68,7 +68,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[ORM\Index(columns: ['needs_refill'], name: 'part_lots_idx_needs_refill')]
#[ORM\Index(columns: ['vendor_barcode'], name: 'part_lots_idx_barcode')]
#[ValidPartLot]
#[UniqueEntity(['vendor_barcode'], message: 'validator.part_lot.vendor_barcode_must_be_unique')]
#[UniqueEntity(['user_barcode'], message: 'validator.part_lot.vendor_barcode_must_be_unique')]
#[ApiResource(
operations: [
new Get(security: 'is_granted("read", object)'),
@ -166,10 +166,10 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
/**
* @var string|null The content of the barcode of this part lot (e.g. a barcode on the package put by the vendor)
*/
#[ORM\Column(type: Types::STRING, nullable: true)]
#[ORM\Column(name: "vendor_barcode", type: Types::STRING, nullable: true)]
#[Groups(['part_lot:read', 'part_lot:write'])]
#[Length(max: 255)]
protected ?string $vendor_barcode = null;
protected ?string $user_barcode = null;
public function __clone()
{
@ -185,7 +185,6 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
*
* @return bool|null True, if the part lot is expired. Returns null, if no expiration date was set.
*
* @throws Exception If an error with the DateTime occurs
*/
public function isExpired(): ?bool
{
@ -376,19 +375,19 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
* null if no barcode is set.
* @return string|null
*/
public function getVendorBarcode(): ?string
public function getUserBarcode(): ?string
{
return $this->vendor_barcode;
return $this->user_barcode;
}
/**
* Set the content of the barcode of this part lot (e.g. a barcode on the package put by the vendor).
* @param string|null $vendor_barcode
* @param string|null $user_barcode
* @return $this
*/
public function setVendorBarcode(?string $vendor_barcode): PartLot
public function setUserBarcode(?string $user_barcode): PartLot
{
$this->vendor_barcode = $vendor_barcode;
$this->user_barcode = $user_barcode;
return $this;
}

View file

@ -103,7 +103,7 @@ class Supplier extends AbstractCompany
protected ?AbstractStructuralDBElement $parent = null;
/**
* @var Collection<int, Orderdetail>|Orderdetail[]
* @var Collection<int, Orderdetail>
*/
#[ORM\OneToMany(mappedBy: 'supplier', targetEntity: Orderdetail::class)]
protected Collection $orderdetails;

View file

@ -333,7 +333,6 @@ class Project extends AbstractStructuralDBElement
{
//If this project has subprojects, and these have builds part, they must be included in the BOM
foreach ($this->getChildren() as $child) {
/** @var $child Project */
if (!$child->getBuildPart() instanceof Part) {
continue;
}

View file

@ -102,7 +102,7 @@ use Jbtronics\TFAWebauthn\Model\TwoFactorInterface as WebauthnTwoFactorInterface
#[ApiFilter(LikeFilter::class, properties: ["name", "aboutMe"])]
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
#[NoLockout]
#[NoLockout(groups: ['permissions:edit'])]
class User extends AttachmentContainingDBElement implements UserInterface, HasPermissionsInterface, TwoFactorInterface,
BackupCodeInterface, TrustedDeviceInterface, WebauthnTwoFactorInterface, PreferredProviderInterface, PasswordAuthenticatedUserInterface, SamlUserInterface
{
@ -256,7 +256,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
protected ?string $password = null;
#[Assert\NotBlank]
#[Assert\Regex('/^[\w\.\+\-\$]+$/', message: 'user.invalid_username')]
#[Assert\Regex('/^[\w\.\+\-\$]+[\w\.\+\-\$\@]*$/', message: 'user.invalid_username')]
#[Groups(['user:read'])]
protected string $name = '';
@ -893,8 +893,6 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
* @param string[] $codes An array containing the backup codes
*
* @return $this
*
* @throws Exception If an error with the datetime occurs
*/
public function setBackupCodes(array $codes): self
{