Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revision signing & setRawDataFinalizedBy #950

Open
Davidmattei opened this issue Jul 10, 2024 · 2 comments
Open

Revision signing & setRawDataFinalizedBy #950

Davidmattei opened this issue Jul 10, 2024 · 2 comments
Assignees

Comments

@Davidmattei
Copy link
Member

Revision Entity:

public function setRawDataFinalizedBy(string $finalizedBy): self
{
        $this->rawData[Mapping::FINALIZED_BY_FIELD] = $finalizedBy;
        $this->tryToFinalizeOn = new \DateTime();
        $this->rawData[Mapping::FINALIZATION_DATETIME_FIELD] = $this->tryToFinalizeOn->format(\DateTimeInterface::ATOM);

        return $this;
}

public function setFinalizedBy(string $finalizedBy): self
{
        $this->finalizedBy = $finalizedBy;
        $this->finalizedDate = $this->tryToFinalizeOn;

        return $this;
}

dataService:

  public function sign(Revision $revision, bool $silentPublish = false): array
    {
        if ($silentPublish && $revision->getAutoSave()) {
            $objectArray = $revision->getAutoSave();
        } else {
            $objectArray = $revision->getRawData();
        }

        $objectArray[Mapping::CONTENT_TYPE_FIELD] = $revision->giveContentType()->getName();
        if ($revision->hasVersionTags()) {
            $objectArray[Mapping::VERSION_UUID] = $revision->getVersionUuid();
            $objectArray[Mapping::VERSION_TAG] = $revision->getVersionTag();
            $revision->updateVersionNextTag();
        }

        $hash = $this->signRaw($objectArray);
        $revision->setSha1($hash);

        $revision->setRawData($objectArray);

        return $objectArray;
    }


public function signRaw(array &$objectArray): string
{
        if (isset($objectArray[Mapping::HASH_FIELD])) {
            unset($objectArray[Mapping::HASH_FIELD]);
        }
        if (isset($objectArray[Mapping::SIGNATURE_FIELD])) {
            unset($objectArray[Mapping::SIGNATURE_FIELD]);
        }
        if (isset($objectArray[Mapping::PUBLISHED_DATETIME_FIELD])) {
            unset($objectArray[Mapping::PUBLISHED_DATETIME_FIELD]);
        }
        Json::normalize($objectArray);
        $json = Json::encode($objectArray);

        $hash = $this->storageManager->computeStringHash($json);
        $objectArray[Mapping::HASH_FIELD] = $hash;

        //......
}


public function finalizeDraft(Revision $revision, ......)
{
       //......
       $revision->setRawDataFinalizedBy($username);

       $objectArray = $this->sign($revision);

       if ($this->isValid($form, null, $objectArray)) {
            //......

            $revision->setFinalizedBy($username);

            $em->persist($revision);
            $em->flush();
       }

Issues with this code:

  • Change nothing on a revision will create a new hash if the finalized by username is different, because signRaw is not excluding this.
  • The setRawDataFinilizedBy method is overkill and should be removed, together with the tryToFinalizeOn property

Solution:

  • The signRaw should excluded the _finalized_by & _finalization_datetime for calculating the hash
  • The signRaw is also call by bulker, should it should not delete the _finalized_by & _finalization_datetime field, the $objectArray is passed by reference
  • The setFinalizedBy should be called be for calling the sign method, and should also set the finalizationDateTime to now
@Davidmattei
Copy link
Member Author

If we change this we can also update the recompute:

We are signing the new revision twice, because we first need to be able to see if something has changed.
Setting the finalized by to SYSTEM_RECOMPUTE will allways result in a new revision, see description ticket.

  $revision->close(new \DateTime('now'));
  $newRevision->setDraft(false);

  $this->dataService->sign($revision);
  $this->dataService->sign($newRevision);

  if ($this->isChanged && $revision->getHash() === $newRevision->getHash()) {
      $this->revisionRepository->unlockRevision($revisionId);
      $progress->advance();
      continue;
  }

  $newRevision->setFinalizedBy(self::LOCK_BY);
  $newRevision->setRawDataFinalizedBy(self::LOCK_BY);
  $this->dataService->sign($newRevision);

Should become

  $revision->close(new \DateTime('now'));
  $newRevision->setDraft(false);
  $newRevision->setFinalizedBy(self::LOCK_BY);

  $this->dataService->sign($revision);
  $this->dataService->sign($newRevision);

  if ($this->isChanged && $revision->getHash() === $newRevision->getHash()) {
      $this->revisionRepository->unlockRevision($revisionId);
      $progress->advance();
      continue;
  }

@Davidmattei
Copy link
Member Author

Davidmattei commented Jul 16, 2024

Discussed: the signing raw can excluded all fields starting with an underscore. at the root level

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Todo
Development

No branches or pull requests

1 participant