Skip to content

Commit

Permalink
Support setting updates expiration date on user groups level
Browse files Browse the repository at this point in the history
  • Loading branch information
vtsykun committed Feb 8, 2024
1 parent 8c5535c commit 9521a0f
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 24 deletions.
21 changes: 21 additions & 0 deletions src/Entity/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class Group
#[ORM\Column(name: 'name', length: 64, unique: true)]
private ?string $name = null;

#[ORM\Column(name: 'expired_updates_at', type: 'datetime', nullable: true)]
private ?\DateTimeInterface $expiredUpdatesAt = null;

#[ORM\Column(name: 'proxies', type: 'simple_array', nullable: true)]
private ?array $proxies = null;

Expand Down Expand Up @@ -141,4 +144,22 @@ public function removeAclPermissions(GroupAclPermission $permission)

return $this;
}

/**
* {@inheritdoc}
*/
public function getExpiredUpdatesAt(): ?\DateTimeInterface
{
return $this->expiredUpdatesAt;
}

/**
* @param \DateTimeInterface $expiredUpdatesAt
* @return $this
*/
public function setExpiredUpdatesAt(?\DateTimeInterface $expiredUpdatesAt)
{
$this->expiredUpdatesAt = $expiredUpdatesAt;
return $this;
}
}
4 changes: 2 additions & 2 deletions src/Form/Type/CustomerUserType.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
->add('expiredUpdatesAt', DateType::class, [
'required' => false,
'widget' => 'single_text',
'label' => 'Update expiration',
'tooltip' => 'A new release updates will be frozen after this date. But the user can uses the versions released before'
'label' => 'Update expiration date',
'tooltip' => 'Default release updates expiration date. By default the value from the ACL group will be used if it is set'
])
->add('fullAccess', CheckboxType::class, [
'required' => false,
Expand Down
9 changes: 8 additions & 1 deletion src/Form/Type/GroupType.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Packeton\Mirror\ProxyRepositoryRegistry;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
Expand All @@ -26,7 +27,13 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
$proxyChoice = \array_combine($proxyChoice, $proxyChoice);

$builder
->add('name', TextType::class, ['label' => 'Name', 'constraints' => [new NotBlank()]]);
->add('name', TextType::class, ['label' => 'Name', 'constraints' => [new NotBlank()]])
->add('expiredUpdatesAt', DateType::class, [
'widget' => 'single_text',
'required' => false,
'label' => 'Update expiration',
'tooltip' => 'A new release updates will be frozen after this date. But the user can uses the versions released before.'
]);

if ($proxyChoice) {
$builder
Expand Down
22 changes: 22 additions & 0 deletions src/Repository/GroupRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,27 @@ public function getAllowedVersionByPackage(?UserInterface $user, Package $packag
return $result;
}

public function getExpirationDateForUser(PacketonUserInterface $user): array
{
$qb = $this->getEntityManager()->createQueryBuilder();

$result = [];
$expiredData = $qb->select('MAX(g.expiredUpdatesAt) as expired', 'IDENTITY(perm.package) as package')
->from(Group::class, 'g')
->innerJoin('g.aclPermissions', 'perm')
->andWhere('g.expiredUpdatesAt IS NOT NULL')
->andWhere('g.id IN (:ids)')
->groupBy('package')
->setParameter('ids', $user->getAclGroups() ?: [-1])
->getQuery()->getArrayResult();

foreach ($expiredData as $item) {
$result[(int)$item['package']] = new \DateTimeImmutable($item['expired'], new \DateTimeZone('UTC'));
}

return $result;
}

/**
* @param UserInterface $user
* @param bool $hydration flags
Expand Down Expand Up @@ -161,6 +182,7 @@ public function getApiData(Group $group)
'id' => $group->getId(),
'name' => $group->getName(),
'proxies' => $group->getProxies(),
'expiredUpdatesAt' => $group->getExpiredUpdatesAt(),
] + $this->getGroupsData($group);
}

Expand Down
43 changes: 22 additions & 21 deletions src/Security/Acl/PackagesAclChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,17 @@
use Packeton\Entity\Package;
use Packeton\Entity\Version;
use Packeton\Model\PacketonUserInterface as PUI;
use Packeton\Repository\GroupRepository;

class PackagesAclChecker
{
/**
* @var ManagerRegistry
*/
private $registry;

/**
* @var VersionParser
*/
private $parser;
private VersionParser $parser;
private array $versionCache = [];
private array $expiredCache = [];

/**
* @var array
*/
private $versionCache = [];

/**
* @param ManagerRegistry $registry
*/
public function __construct(ManagerRegistry $registry)
public function __construct(private ManagerRegistry $registry)
{
$this->registry = $registry;
$this->parser = new VersionParser();
}

Expand All @@ -55,6 +42,9 @@ public function isGrantedAccessForAllVersions(PUI $user, Package $package)
if ($package->isFullVisibility()) {
return true;
}
if ($this->getExpiredDate($user, $package)) {
return false;
}

$versionConstraints = $this->getVersions($user, $package);
foreach ($versionConstraints as $constraint) {
Expand All @@ -76,7 +66,7 @@ public function isGrantedAccessForAllVersions(PUI $user, Package $package)
*/
public function isGrantedAccessForVersion(PUI $user, Version $version)
{
if ($user->getExpiredUpdatesAt() && $user->getExpiredUpdatesAt() < $version->getReleasedAt()) {
if (($date = $this->getExpiredDate($user, $version->getPackage())) && $date < $version->getReleasedAt()) {
return false;
}

Expand All @@ -102,8 +92,19 @@ private function getVersions(PUI $user, Package $package)
return $this->versionCache[$hash];
}

$version = $this->registry->getRepository(Group::class)
->getAllowedVersionByPackage($user, $package);
$version = $this->getGroupRepo()->getAllowedVersionByPackage($user, $package);
return $this->versionCache[$hash] = $version;
}

public function getExpiredDate(PUI $user, Package $package): ?\DateTimeInterface
{
$expiredData = $this->expiredCache[$user->getUserIdentifier()] ??= $this->getGroupRepo()->getExpirationDateForUser($user);

return $expiredData[$package->getId()] ?? $user->getExpiredUpdatesAt();
}

private function getGroupRepo(): GroupRepository
{
return $this->registry->getRepository(Group::class);
}
}
13 changes: 13 additions & 0 deletions templates/group/update.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
{{ form_start(form, { attr: { class: 'col-md-6' } }) }}
{{ form_errors(form) }}
{{ form_row(form.name) }}
{{ form_row(form.expiredUpdatesAt) }}
{% if form.proxies is defined %}
{{ form_row(form.proxies) }}
{% endif %}
Expand Down Expand Up @@ -64,3 +65,15 @@
});
</script>
{% endblock %}

{% block scripts %}
<script src="{{ asset('libs/datepicker/bootstrap-datepicker.min.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js"></script>
<script nonce="{{ csp_nonce('script') }}">
$(function(){
$('.js-datepicker').datepicker({
format: 'yyyy-mm-dd'
});
});
</script>
{% endblock %}

0 comments on commit 9521a0f

Please sign in to comment.