Skip to content

Commit

Permalink
Merge pull request #13 from mhaagen85/feature/AOM2-172
Browse files Browse the repository at this point in the history
[FEATURE] Introduce a counter for CSP reports which already exist.
  • Loading branch information
Boris van Katwijk authored Aug 12, 2021
2 parents dfabc35 + a3c6e13 commit de41b41
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 26 deletions.
14 changes: 13 additions & 1 deletion Api/Data/ReportInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@

interface ReportInterface extends \Magento\Framework\Api\ExtensibleDataInterface
{

const VIOLATED_DIRECTIVE = 'violated_directive';
const REPORT_ID = 'report_id';
const DOCUMENT_URI = 'document_uri';
const REFERRER = 'referrer';
const ORIGINAL_POLICY = 'original_policy';
const DATE = 'date';
const BLOCKED_URI = 'blocked_uri';
const COUNT = 'count';

/**
* Get report_id
Expand Down Expand Up @@ -124,5 +124,17 @@ public function getDate();
*/
public function setDate($date);

/**
* Get Count
* @return string|null
*/
public function getCount();

/**
* @param $count
* @return \Experius\Csp\Api\Data\ReportInterface
*/
public function setCount($count);

}

19 changes: 19 additions & 0 deletions Model/Data/Report.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,5 +165,24 @@ public function setDate($date)
return $this->setData(self::DATE, $date);
}

/**
* Get count
* @return string|null
*/
public function getCount()
{
return $this->_get(self::COUNT);
}

/**
* Set count
* @param string $count
* @return \Experius\Csp\Api\Data\ReportInterface
*/
public function setCount($count)
{
return $this->setData(self::COUNT, $count);
}

}

101 changes: 76 additions & 25 deletions Model/ReportRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Experius\Csp\Model;

use Experius\Csp\Api\Data\ReportInterface;
use Experius\Csp\Api\Data\ReportInterfaceFactory;
use Experius\Csp\Api\Data\ReportSearchResultsInterfaceFactory;
use Experius\Csp\Api\ReportRepositoryInterface;
Expand All @@ -16,11 +17,13 @@
use Magento\Framework\Api\ExtensibleDataObjectConverter;
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
use Magento\Framework\Exception\AbstractAggregateException;
use Magento\Framework\Exception\CouldNotDeleteException;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Reflection\DataObjectProcessor;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;

class ReportRepository implements ReportRepositoryInterface
{
Expand All @@ -46,8 +49,10 @@ class ReportRepository implements ReportRepositoryInterface

private $collectionProcessor;

protected $searchCriteriaBuilder;

/**
* ReportRepository constructor.
* @param ResourceReport $resource
* @param ReportFactory $reportFactory
* @param ReportInterfaceFactory $dataReportFactory
Expand All @@ -59,6 +64,7 @@ class ReportRepository implements ReportRepositoryInterface
* @param CollectionProcessorInterface $collectionProcessor
* @param JoinProcessorInterface $extensionAttributesJoinProcessor
* @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
* @param SearchCriteriaBuilder $searchCriteriaBuilder
*/
public function __construct(
ResourceReport $resource,
Expand All @@ -71,7 +77,8 @@ public function __construct(
StoreManagerInterface $storeManager,
CollectionProcessorInterface $collectionProcessor,
JoinProcessorInterface $extensionAttributesJoinProcessor,
ExtensibleDataObjectConverter $extensibleDataObjectConverter
ExtensibleDataObjectConverter $extensibleDataObjectConverter,
SearchCriteriaBuilder $searchCriteriaBuilder
) {
$this->resource = $resource;
$this->reportFactory = $reportFactory;
Expand All @@ -84,36 +91,40 @@ public function __construct(
$this->collectionProcessor = $collectionProcessor;
$this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;
$this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
}

/**
* {@inheritdoc}
*/
public function save(
\Experius\Csp\Api\Data\ReportInterface $report
ReportInterface $report
) {
/* if (empty($report->getStoreId())) {
$storeId = $this->storeManager->getStore()->getId();
$report->setStoreId($storeId);
} */

$reportData = $this->extensibleDataObjectConverter->toNestedArray(
$report,
[],
\Experius\Csp\Api\Data\ReportInterface::class
);

$reportModel = $this->reportFactory->create()->setData($reportData);

try {
$this->resource->save($reportModel);
} catch (\Exception $exception) {
throw new CouldNotSaveException(__(
'Could not save the report: %1',
$exception->getMessage()
));
// @TODO: [Should have] Move detection if already exists outside of the save() function
// @TODO: [Nice to have] Find the reason csp reports are sent directly at the same time, to prevent having to
// to use the usleep() mechanic to de-synchronise saving.

// Sleep for a random millisecond to prevent double saves
$sleep = rand(1000, 1000000);
usleep($sleep);
$existingReport = $this->doesReportExistAlready($report);

if(!$existingReport) {
try {
$report = $this->resource->save($this->createReportModel($report));
} catch (\Exception $exception) {
throw new CouldNotSaveException(__(
'Could not save the report: %1',
$exception->getMessage()
));
}
return $report;
} else {
$existingReport->setCount($existingReport->getCount() + 1);
$existingReport = $this->resource->save($this->createReportModel($existingReport));

return $existingReport;
}
return $reportModel->getDataModel();
}

/**
Expand All @@ -139,7 +150,7 @@ public function getList(

$this->extensionAttributesJoinProcessor->process(
$collection,
\Experius\Csp\Api\Data\ReportInterface::class
ReportInterface::class
);

$this->collectionProcessor->process($criteria, $collection);
Expand All @@ -161,7 +172,7 @@ public function getList(
* {@inheritdoc}
*/
public function delete(
\Experius\Csp\Api\Data\ReportInterface $report
ReportInterface $report
) {
try {
$reportModel = $this->reportFactory->create();
Expand All @@ -183,5 +194,45 @@ public function deleteById($reportId)
{
return $this->delete($this->get($reportId));
}

/**
* Does report exist already?
*
* @param $report
* @return ReportInterface|false
*/
public function doesReportExistAlready($report)
{
if (!$report || $report instanceof ReportInterface == false) {
return false;
}

$searchCriteria = $this->searchCriteriaBuilder
->addFilter(ReportInterface::VIOLATED_DIRECTIVE, $report->getViolatedDirective())
->addFilter(ReportInterface::BLOCKED_URI, $report->getBlockedUri())
->addFilter(ReportInterface::DOCUMENT_URI, $report->getDocumentUri())
->create();

if ($this->getList($searchCriteria)->getTotalCount() < 1) {
return false;
}

// Return first match if found
foreach ($this->getList($searchCriteria)->getItems() as $item) {
return $item;
}
return false;
}

public function createReportModel($report)
{
$reportData = $this->extensibleDataObjectConverter->toNestedArray(
$report,
[],
ReportInterface::class
);

return $this->reportFactory->create()->setData($reportData);
}
}

1 change: 1 addition & 0 deletions etc/db_schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@
<index referenceId="EXPERIUS_CSP_REPORT_DATE" indexType="btree">
<column name="date"/>
</index>
<column xsi:type="int" name="count" padding="11" nullable="true" default="1" comment="Count"/>
</table>
</schema>

0 comments on commit de41b41

Please sign in to comment.