Skip to content
Snippets Groups Projects
Unverified Commit b3a48406 authored by Marko Ivancic's avatar Marko Ivancic Committed by GitHub
Browse files

Implement data retention policy (#11)

parent 168fa860
Branches
Tags
1 merge request!1Relate histories
...@@ -8,6 +8,7 @@ use Psr\Log\LoggerInterface; ...@@ -8,6 +8,7 @@ use Psr\Log\LoggerInterface;
use SimpleSAML\Module\accounting\Entities\Activity; use SimpleSAML\Module\accounting\Entities\Activity;
use SimpleSAML\Module\accounting\Entities\Authentication\Event; use SimpleSAML\Module\accounting\Entities\Authentication\Event;
use SimpleSAML\Module\accounting\Entities\ConnectedServiceProvider; use SimpleSAML\Module\accounting\Entities\ConnectedServiceProvider;
use SimpleSAML\Module\accounting\Exceptions\InvalidConfigurationException;
use SimpleSAML\Module\accounting\ModuleConfiguration; use SimpleSAML\Module\accounting\ModuleConfiguration;
use SimpleSAML\Module\accounting\Providers\Interfaces\AuthenticationDataProviderInterface; use SimpleSAML\Module\accounting\Providers\Interfaces\AuthenticationDataProviderInterface;
use SimpleSAML\Module\accounting\Services\HelpersManager; use SimpleSAML\Module\accounting\Services\HelpersManager;
...@@ -84,4 +85,22 @@ class Tracker implements AuthenticationDataTrackerInterface, AuthenticationDataP ...@@ -84,4 +85,22 @@ class Tracker implements AuthenticationDataTrackerInterface, AuthenticationDataP
$userIdentifierHashSha256 = $this->helpersManager->getHashHelper()->getSha256($userIdentifier); $userIdentifierHashSha256 = $this->helpersManager->getHashHelper()->getSha256($userIdentifier);
return $this->dataStore->getActivity($userIdentifierHashSha256, $maxResults, $firstResult); return $this->dataStore->getActivity($userIdentifierHashSha256, $maxResults, $firstResult);
} }
public function enforceDataRetentionPolicy(\DateInterval $retentionPolicy): void
{
$dateTime = (new \DateTimeImmutable())->sub($retentionPolicy);
if ($dateTime === false) {
// @codeCoverageIgnoreStart
$message = sprintf(
'Could not create DateTime instance for data retention policy enforcement. Retention policy was: %s.',
var_export($retentionPolicy, true)
);
$this->logger->error($message);
throw new InvalidConfigurationException($message);
// @codeCoverageIgnoreEnd
}
$this->dataStore->deleteDataOlderThan($dateTime);
}
} }
<?php <?php
declare(strict_types=1);
namespace SimpleSAML\Module\accounting\Trackers\Interfaces; namespace SimpleSAML\Module\accounting\Trackers\Interfaces;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
...@@ -14,4 +16,6 @@ interface AuthenticationDataTrackerInterface extends BuildableUsingModuleConfigu ...@@ -14,4 +16,6 @@ interface AuthenticationDataTrackerInterface extends BuildableUsingModuleConfigu
public static function build(ModuleConfiguration $moduleConfiguration, LoggerInterface $logger): self; public static function build(ModuleConfiguration $moduleConfiguration, LoggerInterface $logger): self;
public function process(Event $authenticationEvent): void; public function process(Event $authenticationEvent): void;
public function enforceDataRetentionPolicy(\DateInterval $retentionPolicy): void;
} }
...@@ -28,10 +28,20 @@ ...@@ -28,10 +28,20 @@
<strong>{{ 'Tracker and Provider Setup Needed'|trans }}</strong>: <strong>{{ 'Tracker and Provider Setup Needed'|trans }}</strong>:
{{ defaultDataTrackerAndProvider.needsSetup ? 'Yes'|trans : 'No'|trans }} {{ defaultDataTrackerAndProvider.needsSetup ? 'Yes'|trans : 'No'|trans }}
</li> </li>
{% if additionalTrackers is not empty %}
<li>
<strong>{{ 'Additional Trackers and setup'|trans }}</strong>:
<ul>
{% for trackerClass, trackerInstance in additionalTrackers %}
<li>
{{ trackerClass }}: {{ trackerInstance.needsSetup ? 'Yes'|trans : 'No'|trans }}
</li>
{% endfor %}
</ul>
</li>
{% endif %}
</ul> </ul>
{# TODO mivanci setup for additional trackers#}
{% if moduleConfiguration.getAccountingProcessingType == 'asynchronous' %} {% if moduleConfiguration.getAccountingProcessingType == 'asynchronous' %}
<ul> <ul>
<li> <li>
......
...@@ -16,8 +16,6 @@ $config = [ ...@@ -16,8 +16,6 @@ $config = [
ModuleConfiguration::OPTION_ACCOUNTING_PROCESSING_TYPE => ModuleConfiguration::OPTION_ACCOUNTING_PROCESSING_TYPE =>
ModuleConfiguration\AccountingProcessingType::VALUE_SYNCHRONOUS, ModuleConfiguration\AccountingProcessingType::VALUE_SYNCHRONOUS,
ModuleConfiguration::OPTION_CRON_TAG_FOR_JOB_RUNNER => 'accounting_job_runner',
ModuleConfiguration::OPTION_JOBS_STORE => Stores\Jobs\DoctrineDbal\Store::class, ModuleConfiguration::OPTION_JOBS_STORE => Stores\Jobs\DoctrineDbal\Store::class,
ModuleConfiguration::OPTION_DEFAULT_DATA_TRACKER_AND_PROVIDER => ModuleConfiguration::OPTION_DEFAULT_DATA_TRACKER_AND_PROVIDER =>
...@@ -53,4 +51,11 @@ $config = [ ...@@ -53,4 +51,11 @@ $config = [
ModuleConfiguration::OPTION_JOB_RUNNER_MAXIMUM_EXECUTION_TIME => null, ModuleConfiguration::OPTION_JOB_RUNNER_MAXIMUM_EXECUTION_TIME => null,
ModuleConfiguration::OPTION_JOB_RUNNER_SHOULD_PAUSE_AFTER_NUMBER_OF_JOBS_PROCESSED => 10, ModuleConfiguration::OPTION_JOB_RUNNER_SHOULD_PAUSE_AFTER_NUMBER_OF_JOBS_PROCESSED => 10,
ModuleConfiguration::OPTION_TRACKER_DATA_RETENTION_POLICY => null,
ModuleConfiguration::OPTION_CRON_TAG_FOR_TRACKER_DATA_RETENTION_POLICY =>
'accounting_tracker_data_retention_policy',
ModuleConfiguration::OPTION_CRON_TAG_FOR_JOB_RUNNER => 'accounting_job_runner',
]; ];
...@@ -324,4 +324,29 @@ class ModuleConfigurationTest extends TestCase ...@@ -324,4 +324,29 @@ class ModuleConfigurationTest extends TestCase
] ]
); );
} }
public function testThrowsForInvalidTrackerDataRetentionPolicy(): void
{
$this->expectException(InvalidConfigurationException::class);
new ModuleConfiguration(
null,
[
ModuleConfiguration::OPTION_TRACKER_DATA_RETENTION_POLICY => 'invalid'
]
);
}
public function testThrowsForInvalidCronTagForTrackerDataRetentionPolicy(): void
{
$this->expectException(InvalidConfigurationException::class);
new ModuleConfiguration(
null,
[
ModuleConfiguration::OPTION_TRACKER_DATA_RETENTION_POLICY => 'P1D',
ModuleConfiguration::OPTION_CRON_TAG_FOR_TRACKER_DATA_RETENTION_POLICY => false,
]
);
}
} }
...@@ -727,4 +727,63 @@ class RepositoryTest extends TestCase ...@@ -727,4 +727,63 @@ class RepositoryTest extends TestCase
$repository->getActivity($this->userIdentifierHash, 10, 0); $repository->getActivity($this->userIdentifierHash, 10, 0);
} }
public function testCanDeleteAuthenticationEventsOlderThan(): void
{
$this->repository->insertIdp($this->idpEntityId, $this->idpEntityIdHash, $this->createdAt);
$idpResult = $this->repository->getIdp($this->idpEntityIdHash)->fetchAssociative();
$idpId = (int)$idpResult[Store\TableConstants::TABLE_IDP_COLUMN_NAME_ID];
$this->repository->insertIdpVersion($idpId, $this->idpMetadata, $this->idpMetadataHash, $this->createdAt);
$idpVersionResult = $this->repository->getIdpVersion($idpId, $this->idpMetadataHash)->fetchAssociative();
$this->repository->insertSp($this->spEntityId, $this->spEntityIdHash, $this->createdAt);
$spResult = $this->repository->getSp($this->spEntityIdHash)->fetchAssociative();
$spId = (int)$spResult[Store\TableConstants::TABLE_SP_COLUMN_NAME_ID];
$this->repository->insertSpVersion($spId, $this->spMetadata, $this->spMetadataHash, $this->createdAt);
$spVersionResult = $this->repository->getSpVersion($spId, $this->spMetadataHash)->fetchAssociative();
$this->repository->insertUser($this->userIdentifier, $this->userIdentifierHash, $this->createdAt);
$userResult = $this->repository->getUser($this->userIdentifierHash)->fetchAssociative();
$userId = (int)$userResult[Store\TableConstants::TABLE_USER_COLUMN_NAME_ID];
$this->repository
->insertUserVersion($userId, $this->userAttributes, $this->userAttributesHash, $this->createdAt);
$userVersionResult = $this->repository->getUserVersion($userId, $this->userAttributesHash)->fetchAssociative();
$idpVersionId = (int)$idpVersionResult[Store\TableConstants::TABLE_IDP_VERSION_COLUMN_NAME_ID];
$spVersionId = (int)$spVersionResult[Store\TableConstants::TABLE_SP_VERSION_COLUMN_NAME_ID];
$userVersionId = (int)$userVersionResult[Store\TableConstants::TABLE_USER_VERSION_COLUMN_NAME_ID];
$this->repository->insertIdpSpUserVersion($idpVersionId, $spVersionId, $userVersionId, $this->createdAt);
$idpSpUserVersionResult = $this->repository->getIdpSpUserVersion($idpVersionId, $spVersionId, $userVersionId)
->fetchAssociative();
$idpSpUserVersionId =
(int)$idpSpUserVersionResult[Store\TableConstants::TABLE_IDP_SP_USER_VERSION_COLUMN_NAME_ID];
$this->repository->insertAuthenticationEvent(
$idpSpUserVersionId,
$this->createdAt,
$this->clientIpAddress,
$this->createdAt
);
$resultArray = $this->repository->getActivity($this->userIdentifierHash, 10, 0);
$this->assertCount(1, $resultArray);
$dateTimeInFuture = $this->createdAt->add(new \DateInterval('P1D'));
$this->repository->deleteAuthenticationEventsOlderThan($dateTimeInFuture);
$resultArray = $this->repository->getActivity($this->userIdentifierHash, 10, 0);
$this->assertCount(0, $resultArray);
}
public function testDeleteAuthenticationEventsOlderThanThrowsOnInvalidDbal(): void
{
$this->connectionStub->method('dbal')->willThrowException(new \Exception('test'));
$repository = new Repository($this->connectionStub, $this->loggerStub);
$this->expectException(StoreException::class);
$repository->deleteAuthenticationEventsOlderThan(new \DateTimeImmutable());
}
} }
...@@ -69,15 +69,15 @@ class StoreTest extends TestCase ...@@ -69,15 +69,15 @@ class StoreTest extends TestCase
protected Event $authenticationEvent; protected Event $authenticationEvent;
protected Store\HashDecoratedState $hashDecoratedState; protected Store\HashDecoratedState $hashDecoratedState;
/** /**
* @var \PHPUnit\Framework\MockObject\Stub|Store\Repository|Store\Repository&\PHPUnit\Framework\MockObject\Stub * @var \PHPUnit\Framework\MockObject\MockObject|Store\Repository
*/ */
protected $repositoryStub; protected $repositoryMock;
/** /**
* @var Result|Result&\PHPUnit\Framework\MockObject\Stub|\PHPUnit\Framework\MockObject\Stub * @var Result|\PHPUnit\Framework\MockObject\Stub
*/ */
protected $resultStub; protected $resultStub;
/** /**
* @var \PHPUnit\Framework\MockObject\MockObject|LoggerInterface|LoggerInterface&\PHPUnit\Framework\MockObject\MockObject * @var \PHPUnit\Framework\MockObject\MockObject|LoggerInterface
*/ */
protected $loggerMock; protected $loggerMock;
...@@ -105,7 +105,7 @@ class StoreTest extends TestCase ...@@ -105,7 +105,7 @@ class StoreTest extends TestCase
$this->authenticationEvent = new Event($this->state); $this->authenticationEvent = new Event($this->state);
$this->hashDecoratedState = new Store\HashDecoratedState($this->state); $this->hashDecoratedState = new Store\HashDecoratedState($this->state);
$this->repositoryStub = $this->createStub(Store\Repository::class); $this->repositoryMock = $this->createMock(Store\Repository::class);
$this->resultStub = $this->createStub(Result::class); $this->resultStub = $this->createStub(Result::class);
} }
...@@ -240,7 +240,7 @@ class StoreTest extends TestCase ...@@ -240,7 +240,7 @@ class StoreTest extends TestCase
public function testResolveIdpIdThrowsOnFirstGetIdpFailure(): void public function testResolveIdpIdThrowsOnFirstGetIdpFailure(): void
{ {
$this->repositoryStub->method('getIdp')->willThrowException(new \Exception('test')); $this->repositoryMock->method('getIdp')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
$this->moduleConfigurationStub, $this->moduleConfigurationStub,
...@@ -248,7 +248,7 @@ class StoreTest extends TestCase ...@@ -248,7 +248,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -259,8 +259,8 @@ class StoreTest extends TestCase ...@@ -259,8 +259,8 @@ class StoreTest extends TestCase
public function testResolveIdpIdThrowsOnInsertAndGetIdpFailure(): void public function testResolveIdpIdThrowsOnInsertAndGetIdpFailure(): void
{ {
$this->resultStub->method('fetchOne')->willReturn(false); $this->resultStub->method('fetchOne')->willReturn(false);
$this->repositoryStub->method('getIdp')->willReturn($this->resultStub); $this->repositoryMock->method('getIdp')->willReturn($this->resultStub);
$this->repositoryStub->method('insertIdp')->willThrowException(new \Exception('test')); $this->repositoryMock->method('insertIdp')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
...@@ -269,7 +269,7 @@ class StoreTest extends TestCase ...@@ -269,7 +269,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -280,7 +280,7 @@ class StoreTest extends TestCase ...@@ -280,7 +280,7 @@ class StoreTest extends TestCase
public function testResolveIdpVersionIdThrowsOnFirstGetIdpVersionFailure(): void public function testResolveIdpVersionIdThrowsOnFirstGetIdpVersionFailure(): void
{ {
$this->repositoryStub->method('getIdpVersion')->willThrowException(new \Exception('test')); $this->repositoryMock->method('getIdpVersion')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
$this->moduleConfigurationStub, $this->moduleConfigurationStub,
...@@ -288,7 +288,7 @@ class StoreTest extends TestCase ...@@ -288,7 +288,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -299,8 +299,8 @@ class StoreTest extends TestCase ...@@ -299,8 +299,8 @@ class StoreTest extends TestCase
public function testResolveIdpVersionIdThrowsOnInsertAndGetIdpVersionFailure(): void public function testResolveIdpVersionIdThrowsOnInsertAndGetIdpVersionFailure(): void
{ {
$this->resultStub->method('fetchOne')->willReturn(false); $this->resultStub->method('fetchOne')->willReturn(false);
$this->repositoryStub->method('getIdpVersion')->willReturn($this->resultStub); $this->repositoryMock->method('getIdpVersion')->willReturn($this->resultStub);
$this->repositoryStub->method('insertIdpVersion')->willThrowException(new \Exception('test')); $this->repositoryMock->method('insertIdpVersion')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
...@@ -309,7 +309,7 @@ class StoreTest extends TestCase ...@@ -309,7 +309,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -320,7 +320,7 @@ class StoreTest extends TestCase ...@@ -320,7 +320,7 @@ class StoreTest extends TestCase
public function testResolveSpIdThrowsOnFirstGetSpFailure(): void public function testResolveSpIdThrowsOnFirstGetSpFailure(): void
{ {
$this->repositoryStub->method('getSp')->willThrowException(new \Exception('test')); $this->repositoryMock->method('getSp')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
$this->moduleConfigurationStub, $this->moduleConfigurationStub,
...@@ -328,7 +328,7 @@ class StoreTest extends TestCase ...@@ -328,7 +328,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -339,8 +339,8 @@ class StoreTest extends TestCase ...@@ -339,8 +339,8 @@ class StoreTest extends TestCase
public function testResolveSpIdThrowsOnInsertAndGetSpFailure(): void public function testResolveSpIdThrowsOnInsertAndGetSpFailure(): void
{ {
$this->resultStub->method('fetchOne')->willReturn(false); $this->resultStub->method('fetchOne')->willReturn(false);
$this->repositoryStub->method('getSp')->willReturn($this->resultStub); $this->repositoryMock->method('getSp')->willReturn($this->resultStub);
$this->repositoryStub->method('insertSp')->willThrowException(new \Exception('test')); $this->repositoryMock->method('insertSp')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
...@@ -349,7 +349,7 @@ class StoreTest extends TestCase ...@@ -349,7 +349,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -360,7 +360,7 @@ class StoreTest extends TestCase ...@@ -360,7 +360,7 @@ class StoreTest extends TestCase
public function testResolveSpVersionIdThrowsOnFirstGetSpVersionFailure(): void public function testResolveSpVersionIdThrowsOnFirstGetSpVersionFailure(): void
{ {
$this->repositoryStub->method('getSpVersion')->willThrowException(new \Exception('test')); $this->repositoryMock->method('getSpVersion')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
$this->moduleConfigurationStub, $this->moduleConfigurationStub,
...@@ -368,7 +368,7 @@ class StoreTest extends TestCase ...@@ -368,7 +368,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -379,8 +379,8 @@ class StoreTest extends TestCase ...@@ -379,8 +379,8 @@ class StoreTest extends TestCase
public function testResolveSpVersionIdThrowsOnInsertAndGetSpVersionFailure(): void public function testResolveSpVersionIdThrowsOnInsertAndGetSpVersionFailure(): void
{ {
$this->resultStub->method('fetchOne')->willReturn(false); $this->resultStub->method('fetchOne')->willReturn(false);
$this->repositoryStub->method('getSpVersion')->willReturn($this->resultStub); $this->repositoryMock->method('getSpVersion')->willReturn($this->resultStub);
$this->repositoryStub->method('insertSpVersion')->willThrowException(new \Exception('test')); $this->repositoryMock->method('insertSpVersion')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
...@@ -389,7 +389,7 @@ class StoreTest extends TestCase ...@@ -389,7 +389,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -410,7 +410,7 @@ class StoreTest extends TestCase ...@@ -410,7 +410,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(UnexpectedValueException::class); $this->expectException(UnexpectedValueException::class);
...@@ -420,7 +420,7 @@ class StoreTest extends TestCase ...@@ -420,7 +420,7 @@ class StoreTest extends TestCase
public function testResolveUserIdThrowsOnFirstGetUserFailure(): void public function testResolveUserIdThrowsOnFirstGetUserFailure(): void
{ {
$this->repositoryStub->method('getUser')->willThrowException(new \Exception('test')); $this->repositoryMock->method('getUser')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
$this->moduleConfigurationStub, $this->moduleConfigurationStub,
...@@ -428,7 +428,7 @@ class StoreTest extends TestCase ...@@ -428,7 +428,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -439,8 +439,8 @@ class StoreTest extends TestCase ...@@ -439,8 +439,8 @@ class StoreTest extends TestCase
public function testResolveUserIdThrowsOnInsertAndGetUserFailure(): void public function testResolveUserIdThrowsOnInsertAndGetUserFailure(): void
{ {
$this->resultStub->method('fetchOne')->willReturn(false); $this->resultStub->method('fetchOne')->willReturn(false);
$this->repositoryStub->method('getUser')->willReturn($this->resultStub); $this->repositoryMock->method('getUser')->willReturn($this->resultStub);
$this->repositoryStub->method('insertUser')->willThrowException(new \Exception('test')); $this->repositoryMock->method('insertUser')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
...@@ -449,7 +449,7 @@ class StoreTest extends TestCase ...@@ -449,7 +449,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -460,7 +460,7 @@ class StoreTest extends TestCase ...@@ -460,7 +460,7 @@ class StoreTest extends TestCase
public function testResolveUserVersionIdThrowsOnFirstGetUserVersionFailure(): void public function testResolveUserVersionIdThrowsOnFirstGetUserVersionFailure(): void
{ {
$this->repositoryStub->method('getUserVersion')->willThrowException(new \Exception('test')); $this->repositoryMock->method('getUserVersion')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
$this->moduleConfigurationStub, $this->moduleConfigurationStub,
...@@ -468,7 +468,7 @@ class StoreTest extends TestCase ...@@ -468,7 +468,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -479,8 +479,8 @@ class StoreTest extends TestCase ...@@ -479,8 +479,8 @@ class StoreTest extends TestCase
public function testResolveUserVersionIdThrowsOnInsertAndGetUserVersionFailure(): void public function testResolveUserVersionIdThrowsOnInsertAndGetUserVersionFailure(): void
{ {
$this->resultStub->method('fetchOne')->willReturn(false); $this->resultStub->method('fetchOne')->willReturn(false);
$this->repositoryStub->method('getUserVersion')->willReturn($this->resultStub); $this->repositoryMock->method('getUserVersion')->willReturn($this->resultStub);
$this->repositoryStub->method('insertUserVersion')->willThrowException(new \Exception('test')); $this->repositoryMock->method('insertUserVersion')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
...@@ -489,7 +489,7 @@ class StoreTest extends TestCase ...@@ -489,7 +489,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -500,7 +500,7 @@ class StoreTest extends TestCase ...@@ -500,7 +500,7 @@ class StoreTest extends TestCase
public function testResolveIdpSpUserVersionIdThrowsOnFirstGetIdpSpUserVersionFailure(): void public function testResolveIdpSpUserVersionIdThrowsOnFirstGetIdpSpUserVersionFailure(): void
{ {
$this->repositoryStub->method('getIdpSpUserVersion')->willThrowException(new \Exception('test')); $this->repositoryMock->method('getIdpSpUserVersion')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
$this->moduleConfigurationStub, $this->moduleConfigurationStub,
...@@ -508,7 +508,7 @@ class StoreTest extends TestCase ...@@ -508,7 +508,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -519,8 +519,8 @@ class StoreTest extends TestCase ...@@ -519,8 +519,8 @@ class StoreTest extends TestCase
public function testResolveIdpSpUserVersionIdThrowsOnInsertAndGetIdpSpUserVersionFailure(): void public function testResolveIdpSpUserVersionIdThrowsOnInsertAndGetIdpSpUserVersionFailure(): void
{ {
$this->resultStub->method('fetchOne')->willReturn(false); $this->resultStub->method('fetchOne')->willReturn(false);
$this->repositoryStub->method('getIdpSpUserVersion')->willReturn($this->resultStub); $this->repositoryMock->method('getIdpSpUserVersion')->willReturn($this->resultStub);
$this->repositoryStub->method('insertIdpSpUserVersion')->willThrowException(new \Exception('test')); $this->repositoryMock->method('insertIdpSpUserVersion')->willThrowException(new \Exception('test'));
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
...@@ -529,7 +529,7 @@ class StoreTest extends TestCase ...@@ -529,7 +529,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -540,7 +540,7 @@ class StoreTest extends TestCase ...@@ -540,7 +540,7 @@ class StoreTest extends TestCase
public function testGetConnectedOrganizationsReturnsEmptyBagIfNoResults(): void public function testGetConnectedOrganizationsReturnsEmptyBagIfNoResults(): void
{ {
$this->repositoryStub->method('getConnectedServiceProviders')->willReturn([]); $this->repositoryMock->method('getConnectedServiceProviders')->willReturn([]);
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
...@@ -549,7 +549,7 @@ class StoreTest extends TestCase ...@@ -549,7 +549,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$connectedServiceProviderBag = $store->getConnectedOrganizations('test'); $connectedServiceProviderBag = $store->getConnectedOrganizations('test');
...@@ -559,7 +559,7 @@ class StoreTest extends TestCase ...@@ -559,7 +559,7 @@ class StoreTest extends TestCase
public function testCanGetConnectedOrganizationsBag(): void public function testCanGetConnectedOrganizationsBag(): void
{ {
$this->repositoryStub->method('getConnectedServiceProviders') $this->repositoryMock->method('getConnectedServiceProviders')
->willReturn([RawRowResult::CONNECTED_ORGANIZATION]); ->willReturn([RawRowResult::CONNECTED_ORGANIZATION]);
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
...@@ -569,7 +569,7 @@ class StoreTest extends TestCase ...@@ -569,7 +569,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$connectedServiceProviderBag = $store->getConnectedOrganizations('test'); $connectedServiceProviderBag = $store->getConnectedOrganizations('test');
...@@ -582,7 +582,7 @@ class StoreTest extends TestCase ...@@ -582,7 +582,7 @@ class StoreTest extends TestCase
$rawResult = RawRowResult::CONNECTED_ORGANIZATION; $rawResult = RawRowResult::CONNECTED_ORGANIZATION;
unset($rawResult[TableConstants::ENTITY_CONNECTED_ORGANIZATION_COLUMN_NAME_NUMBER_OF_AUTHENTICATIONS]); unset($rawResult[TableConstants::ENTITY_CONNECTED_ORGANIZATION_COLUMN_NAME_NUMBER_OF_AUTHENTICATIONS]);
$this->repositoryStub->method('getConnectedServiceProviders') $this->repositoryMock->method('getConnectedServiceProviders')
->willReturn([$rawResult]); ->willReturn([$rawResult]);
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
...@@ -592,7 +592,7 @@ class StoreTest extends TestCase ...@@ -592,7 +592,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
...@@ -601,7 +601,7 @@ class StoreTest extends TestCase ...@@ -601,7 +601,7 @@ class StoreTest extends TestCase
public function testGetActivityReturnsEmptyBagIfNoResults(): void public function testGetActivityReturnsEmptyBagIfNoResults(): void
{ {
$this->repositoryStub->method('getActivity')->willReturn([]); $this->repositoryMock->method('getActivity')->willReturn([]);
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
$store = new Store( $store = new Store(
...@@ -610,7 +610,7 @@ class StoreTest extends TestCase ...@@ -610,7 +610,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$activityBag = $store->getActivity('test', 10, 0); $activityBag = $store->getActivity('test', 10, 0);
...@@ -620,7 +620,7 @@ class StoreTest extends TestCase ...@@ -620,7 +620,7 @@ class StoreTest extends TestCase
public function testCanGetActivityBag(): void public function testCanGetActivityBag(): void
{ {
$this->repositoryStub->method('getActivity') $this->repositoryMock->method('getActivity')
->willReturn([RawRowResult::ACTIVITY]); ->willReturn([RawRowResult::ACTIVITY]);
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
...@@ -630,7 +630,7 @@ class StoreTest extends TestCase ...@@ -630,7 +630,7 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$activityBag = $store->getActivity('test', 10, 0); $activityBag = $store->getActivity('test', 10, 0);
...@@ -643,7 +643,7 @@ class StoreTest extends TestCase ...@@ -643,7 +643,7 @@ class StoreTest extends TestCase
$rawResult = RawRowResult::ACTIVITY; $rawResult = RawRowResult::ACTIVITY;
unset($rawResult[TableConstants::ENTITY_ACTIVITY_COLUMN_NAME_HAPPENED_AT]); unset($rawResult[TableConstants::ENTITY_ACTIVITY_COLUMN_NAME_HAPPENED_AT]);
$this->repositoryStub->method('getActivity') $this->repositoryMock->method('getActivity')
->willReturn([$rawResult]); ->willReturn([$rawResult]);
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
...@@ -653,10 +653,31 @@ class StoreTest extends TestCase ...@@ -653,10 +653,31 @@ class StoreTest extends TestCase
null, null,
ModuleConfiguration\ConnectionType::MASTER, ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub, $this->factoryStub,
$this->repositoryStub $this->repositoryMock
); );
$this->expectException(StoreException::class); $this->expectException(StoreException::class);
$store->getActivity('test', 10, 0); $store->getActivity('test', 10, 0);
} }
public function testCanDeleteDataOlderThan(): void
{
$dateTime = new \DateTimeImmutable();
$this->repositoryMock->expects($this->once())
->method('deleteAuthenticationEventsOlderThan')
->with($dateTime);
/** @psalm-suppress InvalidArgument */
$store = new Store(
$this->moduleConfigurationStub,
$this->loggerMock,
null,
ModuleConfiguration\ConnectionType::MASTER,
$this->factoryStub,
$this->repositoryMock
);
$store->deleteDataOlderThan($dateTime);
}
} }
...@@ -8,6 +8,7 @@ use Psr\Log\LoggerInterface; ...@@ -8,6 +8,7 @@ use Psr\Log\LoggerInterface;
use SimpleSAML\Module\accounting\Entities\Activity; use SimpleSAML\Module\accounting\Entities\Activity;
use SimpleSAML\Module\accounting\Entities\Authentication\Event; use SimpleSAML\Module\accounting\Entities\Authentication\Event;
use SimpleSAML\Module\accounting\Entities\ConnectedServiceProvider; use SimpleSAML\Module\accounting\Entities\ConnectedServiceProvider;
use SimpleSAML\Module\accounting\Exceptions\InvalidConfigurationException;
use SimpleSAML\Module\accounting\ModuleConfiguration; use SimpleSAML\Module\accounting\ModuleConfiguration;
use SimpleSAML\Module\accounting\Services\HelpersManager; use SimpleSAML\Module\accounting\Services\HelpersManager;
use SimpleSAML\Module\accounting\Stores\Data\Authentication\DoctrineDbal\Versioned\Store; use SimpleSAML\Module\accounting\Stores\Data\Authentication\DoctrineDbal\Versioned\Store;
...@@ -194,4 +195,22 @@ class TrackerTest extends TestCase ...@@ -194,4 +195,22 @@ class TrackerTest extends TestCase
$tracker->getActivity('test', 10, 0) $tracker->getActivity('test', 10, 0)
); );
} }
public function testCanEnforceDataRetentionPolicy(): void
{
$retentionPolicy = new \DateInterval('P10D');
$this->dataStoreMock->expects($this->once())
->method('deleteDataOlderThan');
$tracker = new Tracker(
$this->moduleConfigurationStub,
$this->loggerMock,
ModuleConfiguration\ConnectionType::MASTER,
$this->helpersManagerStub,
$this->dataStoreMock
);
$tracker->enforceDataRetentionPolicy($retentionPolicy);
}
} }
...@@ -64,6 +64,10 @@ class AuthenticationDataTrackerBuilderTest extends TestCase ...@@ -64,6 +64,10 @@ class AuthenticationDataTrackerBuilderTest extends TestCase
public function runSetup(): void public function runSetup(): void
{ {
} }
public function enforceDataRetentionPolicy(\DateInterval $retentionPolicy): void
{
}
}; };
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment