Skip to content

Commit

Permalink
PS-690 coll share (#467)
Browse files Browse the repository at this point in the history
* PS-691 databox - fix js on date range filter

* PS-693 add clear method to workflow doctrine state cache
  • Loading branch information
4rthem authored Oct 23, 2024
1 parent 2e1cfa0 commit 8526487
Show file tree
Hide file tree
Showing 78 changed files with 2,972 additions and 1,530 deletions.
3 changes: 1 addition & 2 deletions databox/api/src/Api/Model/Output/ShareAlternateUrlOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ public function __construct(
private string $name,
private string $url,
private ?string $type,
)
{
) {
}

#[Groups([Share::GROUP_READ])]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class CollectionOutputTransformer implements OutputTransformerInterface
use GroupsHelperTrait;
use UserOutputTransformerTrait;
use SecurityAwareTrait;
final public const COLLECTION_CACHE_NS = 'coll_visibility';
final public const string COLLECTION_CACHE_NS = 'coll_visibility';

public function __construct(
private readonly CollectionSearch $collectionSearch,
Expand Down Expand Up @@ -71,9 +71,8 @@ public function transform($data, string $outputClass, array &$context = []): obj
}

$key = sprintf(AbstractObjectNormalizer::DEPTH_KEY_PATTERN, $output::class, 'children');
$maxDepth = $this->hasGroup(Collection::GROUP_2LEVEL_CHILDREN, $context) ? 2 : 1;
$depth = $context[$key] ?? 0;
if ($depth < $maxDepth) {
if ($depth < 1) {
if (false !== $data->getHasChildren()) {
$collections = $this->collectionSearch->search($context['userId'], $context['groupIds'], [
'parent' => $data->getId(),
Expand Down
8 changes: 4 additions & 4 deletions databox/api/src/Api/Provider/ShareReadProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ public function provideShare(Share $item): Share
$item->alternateUrls[] = new ShareAlternateUrlOutput(
$definition->getName(),
$this->urlGenerator->generate('share_public_rendition', [
'id' => $item->getId(),
'rendition' => $definition->getId(),
'token' => $item->getToken(),
], UrlGeneratorInterface::ABS_URL),
'id' => $item->getId(),
'rendition' => $definition->getId(),
'token' => $item->getToken(),
], UrlGeneratorInterface::ABS_URL),
$rendition->getFile()->getType(),
);
}
Expand Down
1 change: 0 additions & 1 deletion databox/api/src/Api/Provider/ShareRenditionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
'createdAt' => 'DESC',
]);


if (null !== $file = $rendition?->getFile()) {
return new RedirectResponse($this->fileUrlResolver->resolveUrl($file));
}
Expand Down
20 changes: 12 additions & 8 deletions databox/api/src/Attribute/Type/DateTimeAttributeType.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,20 @@ public function getGroupValueLabel($value): ?string

public function createFilterQuery(string $field, $value): AbstractQuery
{
$startFloor = (new \DateTimeImmutable())
->setTimestamp((int) $value[0]);
$criteria = [];
if (null !== $value[0]) {
$criteria['gte'] = (new \DateTimeImmutable())
->setTimestamp((int) $value[0])
->getTimestamp() * 1000;
}

$endCeil = (new \DateTimeImmutable())
->setTimestamp((int) $value[1]);
if (null !== $value[1]) {
$criteria['lte'] = (new \DateTimeImmutable())
->setTimestamp((int) $value[1])
->getTimestamp() * 1000;
}

return new Range($field, [
'gte' => $startFloor->getTimestamp() * 1000,
'lte' => $endCeil->getTimestamp() * 1000,
]);
return new Range($field, $criteria);
}

public function getFacetType(): string
Expand Down
2 changes: 1 addition & 1 deletion databox/api/src/Controller/Admin/AssetCrudController.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function triggerIngest(AdminContext $context): Response
WorkflowState::INITIATOR_ID => $user->getId(),
]);

return $this->redirect($context->getReferrer());
return $this->returnToReferer($context);
}

public function configureCrud(Crud $crud): Crud
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Filter\DateTimeFilter;
Expand Down
7 changes: 4 additions & 3 deletions databox/api/src/Controller/Admin/JobStateCrudController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Filter\ChoiceFilter;
use EasyCorp\Bundle\EasyAdminBundle\Filter\DateTimeFilter;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Symfony\Component\HttpFoundation\RedirectResponse;

class JobStateCrudController extends AbstractAdminCrudController
Expand Down Expand Up @@ -63,7 +64,7 @@ public function retryJob(AdminContext $context): RedirectResponse
$jobState = $context->getEntity()->getInstance();
$this->workflowOrchestrator->retryFailedJobs($jobState->getWorkflow()->getId(), $jobState->getJobState()->getJobId());

return new RedirectResponse($context->getReferrer());
return $this->returnToReferer($context);
}

public function cancelJob(AdminContext $context): RedirectResponse
Expand All @@ -72,7 +73,7 @@ public function cancelJob(AdminContext $context): RedirectResponse
$jobState = $context->getEntity()->getInstance();
$this->workflowOrchestrator->cancelWorkflow($jobState->getWorkflow()->getId());

return new RedirectResponse($context->getReferrer());
return $this->returnToReferer($context);
}

public function rerunJob(AdminContext $context): RedirectResponse
Expand All @@ -81,7 +82,7 @@ public function rerunJob(AdminContext $context): RedirectResponse
$jobState = $context->getEntity()->getInstance();
$this->workflowOrchestrator->rerunJobs($jobState->getWorkflow()->getId(), $jobState->getJobState()->getJobId());

return new RedirectResponse($context->getReferrer());
return $this->returnToReferer($context);
}

public function configureCrud(Crud $crud): Crud
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function cancelWorkflow(AdminContext $context): RedirectResponse
$workflowState = $context->getEntity()->getInstance();
$this->workflowOrchestrator->cancelWorkflow($workflowState->getId());

return new RedirectResponse($context->getReferrer());
return $this->returnToReferer($context);
}

public function configureActions(Actions $actions): Actions
Expand Down
4 changes: 4 additions & 0 deletions databox/api/src/Elasticsearch/Facet/CollectionFacet.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ private function normalizeCollectionPath(string $path): ?string
$pColl = $pColl->getParent();
}

if (empty($levels)) {
return null;
}

return implode(' / ', array_reverse($levels));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function hydrateDocument(PostTransformEvent $event): void

$document = $event->getDocument();

$bestPrivacy = $collection->getBestPrivacyInParentHierarchy();
$bestPrivacy = $collection->getPrivacy();

$users = $this->permissionManager->getAllowedUsers($collection, PermissionInterface::VIEW);
$groups = $this->permissionManager->getAllowedGroups($collection, PermissionInterface::VIEW);
Expand All @@ -35,21 +35,35 @@ public function hydrateDocument(PostTransformEvent $event): void
$nlUsers = $users;
$nlGroups = $groups;

if (!in_array(null, $users, true)) {
$parent = $collection->getParent();
while (null !== $parent) {
$users = array_merge($users, $this->permissionManager->getAllowedUsers($parent, PermissionInterface::VIEW));
if (in_array(null, $users, true)) {
break;
}
$parent = $collection->getParent();
while (null !== $parent) {
$bestPrivacy = max($bestPrivacy, $parent->getPrivacy());
if ($bestPrivacy >= WorkspaceItemPrivacyInterface::PUBLIC_FOR_USERS) {
$nlUsers = [];
$nlGroups = [];
break;
}

$parentUsers = $this->permissionManager->getAllowedUsers($parent, PermissionInterface::VIEW);
$users = array_merge($users, $parentUsers);
$nlUsers = array_diff($nlUsers, $parentUsers);

$groups = array_merge($groups, $this->permissionManager->getAllowedGroups($parent, PermissionInterface::VIEW));
$parent = $parent->getParent();
if (in_array(null, $users, true)) {
$nlUsers = [];
$nlGroups = [];
$bestPrivacy = max($bestPrivacy, WorkspaceItemPrivacyInterface::PUBLIC_FOR_USERS);
break;
}

$parentGroups = $this->permissionManager->getAllowedGroups($parent, PermissionInterface::VIEW);
$groups = array_merge($groups, $parentGroups);
$nlGroups = array_diff($nlGroups, $parentGroups);

$parent = $parent->getParent();
}

if (in_array(null, $users, true)) {
$users = ['*'];
$users = [];
$groups = [];
$bestPrivacy = max($bestPrivacy, WorkspaceItemPrivacyInterface::PUBLIC_FOR_USERS);
}
Expand Down
17 changes: 9 additions & 8 deletions databox/api/src/Entity/Core/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
operations: [
new Get(
normalizationContext: [
'groups' => [self::GROUP_READ],
'groups' => [
self::GROUP_READ,
self::GROUP_ABSOLUTE_TITLE,
],
],
security: 'is_granted("'.AbstractVoter::LIST.'", object)'
),
Expand Down Expand Up @@ -82,7 +85,6 @@
'groups' => [
self::GROUP_LIST,
self::GROUP_CHILDREN,
self::GROUP_2LEVEL_CHILDREN,
],
],
input: CollectionInput::class,
Expand All @@ -103,11 +105,10 @@ class Collection extends AbstractUuidEntity implements SoftDeleteableInterface,
use LocaleTrait;
use WorkspacePrivacyTrait;

final public const GROUP_READ = 'coll:read';
final public const GROUP_LIST = 'coll:index';
final public const GROUP_CHILDREN = 'coll:ic';
final public const GROUP_2LEVEL_CHILDREN = 'coll:2lc';
final public const GROUP_ABSOLUTE_TITLE = 'coll:absTitle';
final public const string GROUP_READ = 'coll:read';
final public const string GROUP_LIST = 'coll:index';
final public const string GROUP_CHILDREN = 'coll:ic';
final public const string GROUP_ABSOLUTE_TITLE = 'coll:absTitle';

#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
private ?string $title = null;
Expand Down Expand Up @@ -241,7 +242,7 @@ private function computePrivacyRoots(): array
{
$roots = [];
for ($i = WorkspaceItemPrivacyInterface::PRIVATE_IN_WORKSPACE; $i <= WorkspaceItemPrivacyInterface::PUBLIC; ++$i) {
$roots[$i] = $this->privacy === $i;
$roots[$i] = $this->privacy >= $i;
}

if (null !== $this->parent) {
Expand Down
2 changes: 2 additions & 0 deletions databox/api/src/Security/Voter/AbstractVoter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ abstract class AbstractVoter extends Voter
final public const EDIT = 'EDIT';
final public const DELETE = 'DELETE';
final public const EDIT_PERMISSIONS = 'EDIT_PERMISSIONS';
final public const OPERATOR = 'OPERATOR';
final public const OWNER = 'OWNER';

protected EntityManagerInterface $em;
protected Security $security;
Expand Down
16 changes: 6 additions & 10 deletions databox/api/src/Security/Voter/AssetVoter.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,17 @@ protected function voteOnAttribute(string $attribute, $subject, TokenInterface $
return $isOwner()
|| $this->security->isGranted(self::SCOPE_PREFIX.'EDIT')
|| $this->hasAcl(PermissionInterface::OPERATOR, $subject, $token)
|| $this->containerHasAcl($subject, PermissionInterface::OPERATOR, $token);
|| $this->voteOnContainer($subject, AbstractVoter::OPERATOR);
case self::EDIT_ATTRIBUTES:
return $isOwner()
|| $this->security->isGranted(self::SCOPE_PREFIX.'EDIT')
|| $this->hasAcl(PermissionInterface::EDIT, $subject, $token)
|| $this->containerHasAcl($subject, PermissionInterface::EDIT, $token);
|| $this->voteOnContainer($subject, AbstractVoter::EDIT);
case self::SHARE:
return $isOwner()
|| $this->security->isGranted(self::SCOPE_PREFIX.'EDIT')
|| $this->hasAcl(PermissionInterface::SHARE, $subject, $token)
|| $this->containerHasAcl($subject, PermissionInterface::EDIT, $token);
|| $this->voteOnContainer($subject, AbstractVoter::EDIT);
case self::DELETE:
return $isOwner()
|| $this->security->isGranted(self::SCOPE_PREFIX.'DELETE')
Expand All @@ -80,19 +80,15 @@ protected function voteOnAttribute(string $attribute, $subject, TokenInterface $
return $isOwner()
|| $this->security->isGranted(self::SCOPE_PREFIX.'OWNER')
|| $this->hasAcl(PermissionInterface::OWNER, $subject, $token)
|| $this->containerHasAcl($subject, PermissionInterface::OWNER, $token);
|| $this->voteOnContainer($subject, AbstractVoter::OWNER);
}

return false;
}

private function containerHasAcl(Asset $asset, int $permission, TokenInterface $token): bool
private function voteOnContainer(Asset $asset, string|int $attribute): bool
{
if (null !== $collection = $asset->getReferenceCollection()) {
return $this->hasAcl($permission, $collection, $token);
}

return $this->hasAcl($permission, $asset->getWorkspace(), $token);
return $this->security->isGranted($attribute, $asset->getReferenceCollection() ?? $asset->getWorkspace());
}

private function collectionGrantsAccess(Asset $subject): bool
Expand Down
6 changes: 6 additions & 0 deletions databox/api/src/Security/Voter/CollectionVoter.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ private function doVote(string $attribute, Collection $subject, TokenInterface $
self::EDIT_PERMISSIONS => $isOwner()
|| $this->hasAcl(PermissionInterface::OWNER, $subject, $token)
|| (null !== $subject->getParent() && $this->security->isGranted($attribute, $subject->getParent())),
self::OPERATOR => $isOwner()
|| $this->hasAcl(PermissionInterface::OPERATOR, $subject, $token)
|| (null !== $subject->getParent() && $this->security->isGranted($attribute, $subject->getParent())),
self::OWNER => $isOwner()
|| $this->hasAcl(PermissionInterface::OWNER, $subject, $token)
|| (null !== $subject->getParent() && $this->security->isGranted($attribute, $subject->getParent())),
default => false,
};
}
Expand Down
6 changes: 6 additions & 0 deletions databox/api/src/Security/Voter/WorkspaceVoter.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ private function doVote(string $attribute, Workspace $subject, TokenInterface $t
self::EDIT_PERMISSIONS => $isOwner()
|| $this->hasAcl(PermissionInterface::OWNER, $subject, $token)
|| $this->isAdmin(),
self::OPERATOR => $isOwner()
|| $this->hasAcl(PermissionInterface::OPERATOR, $subject, $token),
self::OWNER => $isOwner()
|| $this->hasAcl(PermissionInterface::OWNER, $subject, $token)
|| $this->isAdmin(),

default => false,
};
}
Expand Down
3 changes: 3 additions & 0 deletions databox/api/tests/DataboxTestTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ protected function createCollection(array $options = []): Collection
if ($options['public'] ?? false) {
$collection->setPrivacy(WorkspaceItemPrivacyInterface::PUBLIC);
}
if ($options['parent'] ?? false) {
$collection->setParent($options['parent']);
}

$em->persist($collection);
if (!($options['no_flush'] ?? false)) {
Expand Down
Loading

0 comments on commit 8526487

Please sign in to comment.