Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion ci/qa/phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,16 @@ parameters:
count: 1
path: ../../src/Surfnet/Stepup/Configuration/Event/SsoOn2faOptionChangedEvent.php

-
message: "#^Method Surfnet\\\\Stepup\\\\Configuration\\\\Event\\\\SsoRegistrationBypassOptionChangedEvent\\:\\:deserialize\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#"
count: 1
path: ../../src/Surfnet/Stepup/Configuration/Event/SsoRegistrationBypassOptionChangedEvent.php

-
message: "#^Method Surfnet\\\\Stepup\\\\Configuration\\\\Event\\\\SsoRegistrationBypassOptionChangedEvent\\:\\:serialize\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: ../../src/Surfnet/Stepup/Configuration/Event/SsoRegistrationBypassOptionChangedEvent.php

-
message: "#^Method Surfnet\\\\Stepup\\\\Configuration\\\\Event\\\\UseRaLocationsOptionChangedEvent\\:\\:deserialize\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#"
count: 1
Expand Down Expand Up @@ -1930,6 +1940,11 @@ parameters:
count: 1
path: ../../src/Surfnet/StepupMiddleware/ApiBundle/Configuration/Projector/InstitutionConfigurationOptionsProjector.php

-
message: "#^Cannot access property \\$ssoRegistrationBypassOption on Surfnet\\\\StepupMiddleware\\\\ApiBundle\\\\Configuration\\\\Entity\\\\InstitutionConfigurationOptions\\|null\\.$#"
count: 1
path: ../../src/Surfnet/StepupMiddleware/ApiBundle/Configuration/Projector/InstitutionConfigurationOptionsProjector.php

-
message: "#^Cannot access property \\$useRaLocationsOption on Surfnet\\\\StepupMiddleware\\\\ApiBundle\\\\Configuration\\\\Entity\\\\InstitutionConfigurationOptions\\|null\\.$#"
count: 1
Expand All @@ -1942,7 +1957,7 @@ parameters:

-
message: "#^Parameter \\#1 \\$institutionConfigurationOptions of method Surfnet\\\\StepupMiddleware\\\\ApiBundle\\\\Configuration\\\\Repository\\\\InstitutionConfigurationOptionsRepository\\:\\:save\\(\\) expects Surfnet\\\\StepupMiddleware\\\\ApiBundle\\\\Configuration\\\\Entity\\\\InstitutionConfigurationOptions, Surfnet\\\\StepupMiddleware\\\\ApiBundle\\\\Configuration\\\\Entity\\\\InstitutionConfigurationOptions\\|null given\\.$#"
count: 7
count: 8
path: ../../src/Surfnet/StepupMiddleware/ApiBundle/Configuration/Projector/InstitutionConfigurationOptionsProjector.php

-
Expand Down Expand Up @@ -3545,6 +3560,11 @@ parameters:
count: 1
path: ../../src/Surfnet/StepupMiddleware/ManagementBundle/Controller/InstitutionConfigurationController.php

-
message: "#^Cannot access offset 'sso_registration…' on mixed\\.$#"
count: 1
path: ../../src/Surfnet/StepupMiddleware/ManagementBundle/Controller/InstitutionConfigurationController.php

-
message: "#^Cannot access offset 'use_ra' on mixed\\.$#"
count: 1
Expand Down Expand Up @@ -3605,6 +3625,11 @@ parameters:
count: 1
path: ../../src/Surfnet/StepupMiddleware/ManagementBundle/Controller/InstitutionConfigurationController.php

-
message: "#^Property Surfnet\\\\StepupMiddleware\\\\CommandHandlingBundle\\\\Configuration\\\\Command\\\\ReconfigureInstitutionConfigurationOptionsCommand\\:\\:\\$ssoRegistrationBypassOption \\(bool\\|null\\) does not accept mixed\\.$#"
count: 1
path: ../../src/Surfnet/StepupMiddleware/ManagementBundle/Controller/InstitutionConfigurationController.php

-
message: "#^Property Surfnet\\\\StepupMiddleware\\\\CommandHandlingBundle\\\\Configuration\\\\Command\\\\ReconfigureInstitutionConfigurationOptionsCommand\\:\\:\\$useRaLocationsOption \\(bool\\) does not accept mixed\\.$#"
count: 1
Expand Down
3 changes: 3 additions & 0 deletions config/packages/doctrine.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ doctrine:
stepup_sso_on_2fa_option:
class: Surfnet\StepupMiddleware\ApiBundle\Doctrine\Type\SsoOn2faOptionType
commented: false
stepup_sso_registration_bypass_option:
class: Surfnet\StepupMiddleware\ApiBundle\Doctrine\Type\SsoRegistrationBypassOptionType
commented: false
stepup_institution_role:
class: Surfnet\StepupMiddleware\ApiBundle\Doctrine\Type\InstitutionRoleType
commented: false
Expand Down
2 changes: 1 addition & 1 deletion config/packages/monolog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ when@dev: &override
main_syslog:
type: stream
path: php://stderr
level: error
level: debug
channels: ["!event", "!doctrine", "!deprecation", "!console"]
console:
type: console
Expand Down
62 changes: 62 additions & 0 deletions src/Surfnet/Migrations/Version20250501121457.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/**
* Copyright 2025 SURFnet bv
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace Surfnet\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use Surfnet\Stepup\MigrationsFactory\ConfigurationAwareMigrationInterface;
use Surfnet\Stepup\MigrationsFactory\ConfigurationAwareMigrationTrait;

final class Version20250501121457 extends AbstractMigration implements ConfigurationAwareMigrationInterface
{
use ConfigurationAwareMigrationTrait;

public function up(Schema $schema): void
{
$this->abortIf(
$this->connection->getDatabasePlatform()->getName() !== 'mysql',
'Migration can only be executed safely on \'mysql\'.',
);
// Create the new sso_on_2fa option, note the name conversion 'error' made by doctrine.
$this->addSql('ALTER TABLE institution_configuration_options ADD sso_registration_bypass_option INT DEFAULT \'0\' NOT NULL');
// Create the institution_configuration gateway schema
$gatewaySchema = $this->getGatewaySchema();
$this->addSql(
sprintf(
'ALTER TABLE %s.institution_configuration ADD sso_registration_bypass TINYINT(1) NOT NULL',
$gatewaySchema,
),
);
}

public function down(Schema $schema): void
{
$this->abortIf(
$this->connection->getDatabasePlatform()->getName() !== 'mysql',
'Migration can only be executed safely on \'mysql\'.',
);
// Down the Middleware schema change
$this->addSql('ALTER TABLE institution_configuration_options DROP sso_registration_bypass_option');
// Gateway schema change (remove the institution_configuration)
$gatewaySchema = $this->getGatewaySchema();
$this->addSql(sprintf('ALTER TABLE %s.institution_configuration DROP sso_registration_bypass', $gatewaySchema));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Surfnet\Stepup\Configuration\Value\SelfVetOption;
use Surfnet\Stepup\Configuration\Value\ShowRaaContactInformationOption;
use Surfnet\Stepup\Configuration\Value\SsoOn2faOption;
use Surfnet\Stepup\Configuration\Value\SsoRegistrationBypassOption;
use Surfnet\Stepup\Configuration\Value\UseRaLocationsOption;
use Surfnet\Stepup\Configuration\Value\VerifyEmailOption;

Expand All @@ -35,6 +36,10 @@
*/
class NewInstitutionConfigurationCreatedEvent implements SerializableInterface
{

/**
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
public InstitutionConfigurationId $institutionConfigurationId,
public Institution $institution,
Expand All @@ -43,6 +48,7 @@ public function __construct(
public VerifyEmailOption $verifyEmailOption,
public NumberOfTokensPerIdentityOption $numberOfTokensPerIdentityOption,
public SsoOn2faOption $ssoOn2faOption,
public SsoRegistrationBypassOption $ssoRegistrationBypassOption,
public SelfVetOption $selfVetOption,
public SelfAssertedTokensOption $selfAssertedTokensOption
) {
Expand All @@ -60,6 +66,10 @@ public static function deserialize(array $data): self
if (!isset($data['sso_on_2fa_option'])) {
$data['sso_on_2fa_option'] = false;
}
// If sso registration bypass option is not yet present, default to false
if (!isset($data['sso_registration_bypass_option'])) {
$data['sso_registration_bypass_option'] = false;
}
// If self vet option is not yet present, default to false
if (!isset($data['self_vet_option'])) {
$data['self_vet_option'] = false;
Expand All @@ -76,6 +86,7 @@ public static function deserialize(array $data): self
new VerifyEmailOption($data['verify_email_option']),
new NumberOfTokensPerIdentityOption($data['number_of_tokens_per_identity_option']),
new SsoOn2faOption($data['sso_on_2fa_option']),
new SsoRegistrationBypassOption($data['sso_registration_bypass_option']),
new SelfVetOption($data['self_vet_option']),
new SelfAssertedTokensOption($data['self_asserted_tokens_option']),
);
Expand All @@ -91,6 +102,7 @@ public function serialize(): array
'verify_email_option' => $this->verifyEmailOption->isEnabled(),
'number_of_tokens_per_identity_option' => $this->numberOfTokensPerIdentityOption->getNumberOfTokensPerIdentity(),
'sso_on_2fa_option' => $this->ssoOn2faOption->isEnabled(),
'sso_registration_bypass_option' => $this->ssoRegistrationBypassOption->isEnabled(),
'self_vet_option' => $this->selfVetOption->isEnabled(),
'self_asserted_tokens_option' => $this->selfAssertedTokensOption->isEnabled(),
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

/**
* Copyright 2025 SURFnet B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace Surfnet\Stepup\Configuration\Event;

use Broadway\Serializer\Serializable as SerializableInterface;
use Surfnet\Stepup\Configuration\Value\Institution;
use Surfnet\Stepup\Configuration\Value\InstitutionConfigurationId;
use Surfnet\Stepup\Configuration\Value\SsoRegistrationBypassOption;

final class SsoRegistrationBypassOptionChangedEvent implements SerializableInterface
{
public function __construct(
public InstitutionConfigurationId $institutionConfigurationId,
public Institution $institution,
public SsoRegistrationBypassOption $ssoRegistrationBypassOption,
) {
}

public static function deserialize(array $data): self
{
return new self(
new InstitutionConfigurationId($data['institution_configuration_id']),
new Institution($data['institution']),
new SsoRegistrationBypassOption($data['sso_registration_bypass_option']),
);
}

public function serialize(): array
{
return [
'institution_configuration_id' => $this->institutionConfigurationId->getInstitutionConfigurationId(),
'institution' => $this->institution->getInstitution(),
'sso_registration_bypass_option' => $this->ssoRegistrationBypassOption->isEnabled(),
];
}
}
30 changes: 30 additions & 0 deletions src/Surfnet/Stepup/Configuration/InstitutionConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use Surfnet\Stepup\Configuration\Event\SelfVetOptionChangedEvent;
use Surfnet\Stepup\Configuration\Event\ShowRaaContactInformationOptionChangedEvent;
use Surfnet\Stepup\Configuration\Event\SsoOn2faOptionChangedEvent;
use Surfnet\Stepup\Configuration\Event\SsoRegistrationBypassOptionChangedEvent;
use Surfnet\Stepup\Configuration\Event\UseRaaOptionChangedEvent;
use Surfnet\Stepup\Configuration\Event\UseRaLocationsOptionChangedEvent;
use Surfnet\Stepup\Configuration\Event\UseRaOptionChangedEvent;
Expand All @@ -54,6 +55,7 @@
use Surfnet\Stepup\Configuration\Value\SelfVetOption;
use Surfnet\Stepup\Configuration\Value\ShowRaaContactInformationOption;
use Surfnet\Stepup\Configuration\Value\SsoOn2faOption;
use Surfnet\Stepup\Configuration\Value\SsoRegistrationBypassOption;
use Surfnet\Stepup\Configuration\Value\UseRaLocationsOption;
use Surfnet\Stepup\Configuration\Value\VerifyEmailOption;
use Surfnet\Stepup\Exception\DomainException;
Expand All @@ -72,6 +74,7 @@
* @SuppressWarnings(PHPMD.TooManyMethods) AggregateRoot
* @SuppressWarnings(PHPMD.TooManyPublicMethods) AggregateRoot
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity) AggregateRoot
* @SuppressWarnings(PHPMD.TooManyFields) AggregateRoot
*/
class InstitutionConfiguration extends EventSourcedAggregateRoot implements InstitutionConfigurationInterface
{
Expand All @@ -93,6 +96,8 @@ class InstitutionConfiguration extends EventSourcedAggregateRoot implements Inst

private ?SsoOn2faOption $ssoOn2faOption = null;

private ?SsoRegistrationBypassOption $ssoRegistrationBypassOption = null;

private ?SelfAssertedTokensOption $selfAssertedTokensOption = null;

private ?InstitutionAuthorizationOption $useRaOption = null;
Expand All @@ -119,6 +124,7 @@ public static function create(
VerifyEmailOption::getDefault(),
NumberOfTokensPerIdentityOption::getDefault(),
SsoOn2faOption::getDefault(),
SsoRegistrationBypassOption::getDefault(),
SelfVetOption::getDefault(),
SelfAssertedTokensOption::getDefault(),
),
Expand Down Expand Up @@ -171,6 +177,7 @@ public function rebuild(): self
VerifyEmailOption::getDefault(),
NumberOfTokensPerIdentityOption::getDefault(),
SsoOn2faOption::getDefault(),
SsoRegistrationBypassOption::getDefault(),
SelfVetOption::getDefault(),
SelfAssertedTokensOption::getDefault(),
),
Expand Down Expand Up @@ -320,6 +327,22 @@ public function configureSsoOn2faOption(SsoOn2faOption $ssoOn2faOption): void
);
}

public function configureSsoRegistrationBypassOption(SsoRegistrationBypassOption $ssoRegistrationBypassOption): void
{
if ($this->ssoRegistrationBypassOption instanceof SsoRegistrationBypassOption
&& $this->ssoRegistrationBypassOption->equals($ssoRegistrationBypassOption)) {
return;
}

$this->apply(
new SsoRegistrationBypassOptionChangedEvent(
$this->institutionConfigurationId,
$this->institution,
$ssoRegistrationBypassOption
)
);
}

public function updateUseRaOption(InstitutionAuthorizationOption $useRaOption): void
{
if ($this->useRaOption instanceof \Surfnet\Stepup\Configuration\Value\InstitutionAuthorizationOption
Expand Down Expand Up @@ -526,6 +549,7 @@ protected function applyNewInstitutionConfigurationCreatedEvent(NewInstitutionCo
$this->verifyEmailOption = $event->verifyEmailOption;
$this->selfVetOption = $event->selfVetOption;
$this->ssoOn2faOption = $event->ssoOn2faOption;
$this->ssoRegistrationBypassOption = $event->ssoRegistrationBypassOption;
$this->selfAssertedTokensOption = $event->selfAssertedTokensOption;
$this->numberOfTokensPerIdentityOption = $event->numberOfTokensPerIdentityOption;
$this->raLocations = new RaLocationList([]);
Expand Down Expand Up @@ -592,6 +616,12 @@ protected function applySsoOn2faOptionChangedEvent(
$this->ssoOn2faOption = $event->ssoOn2faOption;
}

protected function applySsoRegistrationBypassOptionChangedEvent(
SsoRegistrationBypassOptionChangedEvent $event,
): void {
$this->ssoRegistrationBypassOption = $event->ssoRegistrationBypassOption;
}

protected function applyNumberOfTokensPerIdentityOptionChangedEvent(
NumberOfTokensPerIdentityOptionChangedEvent $event,
): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

/**
* Copyright 2025 SURFnet B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace Surfnet\Stepup\Configuration\Value;

use JsonSerializable;

final readonly class SsoRegistrationBypassOption implements JsonSerializable
{
public static function getDefault(): self
{
return new self(false);
}
Comment thread
parijke marked this conversation as resolved.

public function __construct(
private bool $ssoRegistrationBypass
) {
}

public function equals(SsoRegistrationBypassOption $other): bool
{
return $this->ssoRegistrationBypass === $other->isEnabled();
}

public function isEnabled(): bool
{
return $this->ssoRegistrationBypass;
}

public function jsonSerialize(): bool
{
return $this->ssoRegistrationBypass;
}
}
Loading