Skip to content

Commit

Permalink
Ensure the Coin VO handles the TOS correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
MKodde committed Jul 1, 2024
1 parent 9d44f0f commit c96ba2b
Show file tree
Hide file tree
Showing 18 changed files with 197 additions and 44 deletions.
11 changes: 10 additions & 1 deletion assets/Resources/metadata/sp_dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,14 @@
"urns": [
"coin:eula"
]
},
{
"id": "typeOfService",
"getterName": "getTypeOfService",
"friendlyName": "TypeOfService",
"urns": [
"coin:ss:type_of_service:en",
"coin:ss:type_of_service:nl"
]
}
]
]
6 changes: 3 additions & 3 deletions assets/type_of_service.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
},
{
"typeEn" : "Recommended",
"typeNl" : "Productiviteit"
"typeNl" : "Aangeraden"
},
{
"typeEn" : "Productivity",
"typeNl" : "Aangeraden"
"typeNl" : "Productiviteit"
},
{
"typeEn" : "Management of education/research",
Expand All @@ -41,7 +41,7 @@
},
{
"typeEn" : "Medical",
"typeNl" : "Medical"
"typeNl" : "Medisch"
},
{
"typeEn" : "eCommerce",
Expand Down
15 changes: 5 additions & 10 deletions ci/qa/phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -1081,16 +1081,6 @@
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Application/Metadata/JsonGenerator/PrivacyQuestionsMetadataGenerator.php',
];
$ignoreErrors[] = [
'message' => '#^Cannot call method getCoin\\(\\) on Surfnet\\\\ServiceProviderDashboard\\\\Domain\\\\Entity\\\\Entity\\\\MetaData\\|null\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Application/Metadata/JsonGenerator/SpDashboardMetadataGenerator.php',
];
$ignoreErrors[] = [
'message' => '#^Left side of && is always true\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Application/Metadata/JsonGenerator/SpDashboardMetadataGenerator.php',
];
$ignoreErrors[] = [
'message' => '#^Method Surfnet\\\\ServiceProviderDashboard\\\\Application\\\\Metadata\\\\JsonGenerator\\\\SpDashboardMetadataGenerator\\:\\:build\\(\\) return type has no value type specified in iterable type array\\.$#',
'count' => 1,
Expand Down Expand Up @@ -2921,6 +2911,11 @@
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Domain/ValueObject/Ticket.php',
];
$ignoreErrors[] = [
'message' => '#^Method Surfnet\\\\ServiceProviderDashboard\\\\Domain\\\\ValueObject\\\\TypeOfServiceCollection\\:\\:createFromManageResponse\\(\\) has parameter \\$metaDataFields with no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Domain/ValueObject/TypeOfServiceCollection.php',
];
$ignoreErrors[] = [
'message' => '#^Method Surfnet\\\\ServiceProviderDashboard\\\\Infrastructure\\\\DashboardBundle\\\\Command\\\\Entity\\\\ChooseEntityTypeCommand\\:\\:__construct\\(\\) has parameter \\$type with no type specified\\.$#',
'count' => 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
use Surfnet\ServiceProviderDashboard\Application\Command\Command;
use Surfnet\ServiceProviderDashboard\Domain\Entity\Service;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\Contact;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\TypeOfService;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\TypeOfServiceCollection;

interface SaveEntityCommandInterface extends Command
{
Expand Down Expand Up @@ -68,4 +70,9 @@ public function getComments(): ?string;
public function getEnvironment(): ?string;

public function getProtocol(): string;

/**
* @return array<TypeOfService>
*/
public function getTypeOfService(): array;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\Contact;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\OidcGrantType;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\TypeOfService;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\TypeOfServiceCollection;
use Surfnet\ServiceProviderDashboard\Infrastructure\DashboardBundle\Validator\Constraints as SpDashboardAssert;
use Symfony\Component\Validator\Constraints as Assert;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,4 +444,9 @@ public function getLogoUrl(): ?string
{
return null;
}

public function getTypeOfService(): array
{
return [];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class SaveSamlEntityCommand implements SaveEntityCommandInterface
minMessage: 'validator.type-of-service.min',
maxMessage: 'validator.type-of-service.max',
)]
private array $typeOfService;
private array $typeOfService = [];

#[Assert\Url]
private ?string $eulaUrl = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,19 @@ public function build(ManageEntity $entity): array
case $attribute->id === 'originalMetadataUrl':
case $attribute->id === 'applicationUrl':
case $attribute->id === 'eula':
$coin = $entity->getMetaData()->getCoin();
$coin = $entity->getMetaData()?->getCoin();
if ($coin && $coin->$getterName()) {
$attributes[$attribute->urns[0]] = $coin->$getterName();
}
break;
case $attribute->id === 'typeOfService':
$coin = $entity->getMetaData()?->getCoin();
if ($coin && $coin->$getterName() && count($coin->getTypeOfService()->getArray()) > 0) {
// The nl and en attributes for the Type of service need to be set specifically
$attributes[$attribute->urns[0]] = $coin->getTypeOfService()->getServicesAsEnglishString();
$attributes[$attribute->urns[1]] = $coin->getTypeOfService()->getServicesAsDutchString();
}
break;
}
}
return $attributes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
use Surfnet\ServiceProviderDashboard\Domain\Entity\Entity\MetaData;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\NullSecret;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\Secret;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\TypeOfServiceCollection;
use function in_array;

/**
Expand Down Expand Up @@ -211,12 +212,18 @@ private function buildOrganizationFromCommand(SaveEntityCommandInterface $comman

private function buildCoinFromCommand(SaveEntityCommandInterface $command): Coin
{
$typesOfService = new TypeOfServiceCollection();
foreach ($command->getTypeOfService() as $typeOfService) {
$typesOfService->add($typeOfService);
}

return new Coin(
null,
null,
null,
null,
$command->getApplicationUrl(),
$typesOfService,
$command->getEulaUrl(),
null
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
namespace Surfnet\ServiceProviderDashboard\Domain\Entity\Entity;

use Surfnet\ServiceProviderDashboard\Domain\Entity\Comparable;
use Surfnet\ServiceProviderDashboard\Domain\Exception\TypeOfServiceException;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\TypeOfServiceCollection;
use Webmozart\Assert\Assert;

Expand Down Expand Up @@ -66,7 +67,7 @@ public function __construct(
private ?string $originalMetadataUrl,
private null|string|int $excludeFromPush,
private ?string $applicationUrl,
private TypeOfServiceCollection $typeOfService,
private ?TypeOfServiceCollection $typeOfService,
private ?string $eula,
private ?int $oidcClient,
) {
Expand Down Expand Up @@ -107,8 +108,11 @@ public function getOidcClient(): ?int
return $this->oidcClient;
}

public function getTypeOfService(): array
public function getTypeOfService(): TypeOfServiceCollection
{
if ($this->typeOfService === null) {
throw new TypeOfServiceException('Type of service is not set on the Coin');
}
return $this->typeOfService;
}
/**
Expand All @@ -126,6 +130,7 @@ public function merge(Coin $coin): void
$this->applicationUrl = is_null($coin->getApplicationUrl()) ? null : $coin->getApplicationUrl();
$this->eula = is_null($coin->getEula()) ? null : $coin->getEula();
$this->oidcClient = is_null($coin->getOidcClient()) ? null : $coin->getOidcClient();
$this->typeOfService = $coin->getTypeOfService();
}

public function asArray(): array
Expand All @@ -136,8 +141,8 @@ public function asArray(): array
'metaDataFields.coin:exclude_from_push' => $this->getExcludeFromPush(),
'metaDataFields.coin:oidc_client' => $this->getOidcClient(),
'metaDataFields.coin:original_metadata_url' => $this->getOriginalMetadataUrl(),
// TODO: TOS needs to be pulled apart in dutch/english parts
'metaDataFields.coin:ss:type_of_service:en' => implode(',', $this->getTypeOfService()->getArray()),
'metaDataFields.coin:ss:type_of_service:en' => $this->getTypeOfService()->getServicesAsEnglishString(),
'metaDataFields.coin:ss:type_of_service:nl' => $this->getTypeOfService()->getServicesAsDutchString(),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,28 @@
class TypeOfServiceRepositoryFromConfig implements TypeOfServiceRepository
{
private TypeOfServiceCollection $collection;
private string $typeOfServiceLocation = Constants::TYPE_OF_SERVICE_LOCATION;

public function __construct(?string $typeOfServiceLocation = null)
{
// Allow overwriting the default typeOfService location. This is particularly useful for testing
if ($typeOfServiceLocation !== null) {
$this->typeOfServiceLocation = $typeOfServiceLocation;
}
$this->load();
}

private function load(): void
{
$typeOfServiceLocation = Constants::TYPE_OF_SERVICE_LOCATION;
if (!file_exists($typeOfServiceLocation)) {
if (!file_exists($this->typeOfServiceLocation)) {
throw new TypeOfServiceException(
sprintf(
'Please review the file location of the type of services json blob. %s',
$typeOfServiceLocation
$this->typeOfServiceLocation
)
);
}
$fileContents = file_get_contents($typeOfServiceLocation);
$fileContents = file_get_contents($this->typeOfServiceLocation);
if (!$fileContents) {
throw new TypeOfServiceException('Unable to load the type of service json file.');
}
Expand All @@ -60,7 +69,14 @@ private function load(): void
*/
public function getTypesOfServiceChoices(): array
{
$this->load();
return $this->collection->getArray();
}

public function findByEnglishTypeOfService(string $enTos): ?TypeOfService
{
if ($this->collection->has($enTos)) {
return $this->collection->get($enTos);
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

namespace Surfnet\ServiceProviderDashboard\Domain\ValueObject;

use Surfnet\ServiceProviderDashboard\Domain\Exception\TypeOfServiceException;
use Surfnet\ServiceProviderDashboard\Domain\Repository\TypeOfServiceRepositoryFromConfig;
use function implode;

class TypeOfServiceCollection
{
/** @var array<TypeOfService> */
Expand All @@ -28,12 +32,19 @@ class TypeOfServiceCollection
public static function createFromManageResponse(array $metaDataFields): TypeOfServiceCollection
{
$collection = new TypeOfServiceCollection();
$repository = new TypeOfServiceRepositoryFromConfig();
$englishEntry = $metaDataFields['coin:ss:type_of_service:en'] ?? '';
if ($englishEntry === '') {
return $collection;
}
$englishEnties = explode(',', $englishEntry);
foreach ($englishEnties as $singleEntity) {
// When loading the entities from manage, we only load the english types of service.
// The Dutch translations are only relevant when writing to Manage
$collection->add(new TypeOfService($singleEntity));
$searchResult = $repository->findByEnglishTypeOfService($singleEntity);
if ($searchResult !== null) {
$collection->add($searchResult);
}
}
return $collection;
}
Expand All @@ -50,4 +61,47 @@ public function getArray(): array
{
return $this->types;
}

public function has(string $englishTypeOfService): bool
{
foreach ($this->types as $type) {
if ($type->typeEn === $englishTypeOfService) {
return true;
}
}
return false;
}

public function get(string $englishTypeOfService): TypeOfService
{
foreach ($this->types as $type) {
if ($type->typeEn === $englishTypeOfService) {
return $type;
}
}
throw new TypeOfServiceException(
sprintf(
'Type of Service with English name %s could not be located',
$englishTypeOfService
)
);
}

public function getServicesAsDutchString(): string
{
$commasSeperated = [];
foreach ($this->types as $type) {
$commasSeperated[] = $type->typeNl;
}
return implode(',', $commasSeperated);
}

public function getServicesAsEnglishString(): string
{
$commasSeperated = [];
foreach ($this->types as $type) {
$commasSeperated[] = $type->typeEn;
}
return implode(',', $commasSeperated);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public function buildSamlCommandByManageEntity(
$command->setApplicationUrl($coins->getApplicationUrl());
$command->setEulaUrl($coins->getEula());
$command->setImportUrl($coins->getOriginalMetadataUrl());
$command->setTypeOfService($coins->getTypeOfService()->getArray());

// Attributes
$this->setAttributes($command, $manageEntity->getAttributes());
Expand Down Expand Up @@ -111,6 +112,7 @@ public function buildOidcngCommandByManageEntity(
// Coin data
$command->setApplicationUrl($coins->getApplicationUrl());
$command->setEulaUrl($coins->getEula());
$command->setTypeOfService($coins->getTypeOfService()->getArray());

// Attributes
$this->setAttributes($command, $manageEntity->getAttributes());
Expand Down Expand Up @@ -208,6 +210,8 @@ public function buildOauthCccCommandByManageEntity(

// Coin data
$command->setApplicationUrl($coins->getApplicationUrl());
$command->setTypeOfService($coins->getTypeOfService()->getArray());

$command->setEulaUrl($coins->getEula());

$command->setAdministrativeContact(Contact::from($metaData->getContacts()->findAdministrativeContact()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Surfnet\ServiceProviderDashboard\Domain\Entity\Entity\Coin;
use Surfnet\ServiceProviderDashboard\Domain\Entity\ManageEntity;
use Surfnet\ServiceProviderDashboard\Domain\Entity\Service;
use Surfnet\ServiceProviderDashboard\Domain\ValueObject\TypeOfServiceCollection;
use Surfnet\ServiceProviderDashboard\Legacy\Repository\AttributesMetadataRepository;

class SpDashboardMetadataGeneratorTest extends MockeryTestCase
Expand All @@ -39,6 +40,7 @@ public function test_it_can_build_sp_dashboard_metadata()
$coin->shouldReceive('getOriginalMetadataUrl')->andReturn('http://the-a-team.com/saml/metadata');
$coin->shouldReceive('getApplicationUrl')->andReturn(null);
$coin->shouldReceive('getEula')->andReturn(null);
$coin->shouldReceive('getTypeOfService')->andReturn(new TypeOfServiceCollection());
$entity->shouldReceive('getMetaData->getCoin')->andReturn($coin);

$entity->setService($service);
Expand Down
Loading

0 comments on commit c96ba2b

Please sign in to comment.