Skip to content

Commit

Permalink
Create role in invite when registering new service
Browse files Browse the repository at this point in the history
Prior to this change, the Service was registered in teams, which is
going to be removed.
This change registers the Service as a role in Invite, so an invite can
be sent later.

See https://www.pivotaltracker.com/story/show/188011488
  • Loading branch information
johanib committed Oct 29, 2024
1 parent d49eef5 commit fb02ff9
Show file tree
Hide file tree
Showing 26 changed files with 818 additions and 160 deletions.
11 changes: 9 additions & 2 deletions .env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ surfconext_representative_authorization='urn:mace:surfnet.nl:surfnet.nl:sab:role

## Manage test instance
manage_test_host='https://manage.dev.openconext.local'
manage_test_username=sp-portal
manage_test_username=sp-dashboard
manage_test_password=secret
manage_test_publication_status=testaccepted

## Manage production instance
manage_prod_host='https://manage.dev.openconext.local'
manage_prod_username=sp-portal
manage_prod_username=sp-dashboard
manage_prod_password=secret
manage_prod_publication_status=prodaccepted

Expand All @@ -48,6 +48,13 @@ teams_host='https://teams.dev.openconext.local'
teams_username=spdashboard
teams_password=secret

## Invite instance
invite_host='https://invite.dev.openconext.local'
invite_api_username='sp_dashboard'
invite_api_password='secret'
invite_landing_url='https://example.org'
invite_spdashboard_manage_id='4b0e422d-d0d0-4b9e-a521-fdd1ee5d2bad'

# Mail default settings
mail_from=[email protected]
mail_receiver=[email protected]
Expand Down
7 changes: 7 additions & 0 deletions .env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ teams_host='https://teams.dev.openconext.local'
teams_username=spdashboard
teams_password=secret

## Invite instance
invite_host='https://invite.dev.openconext.local'
invite_api_username='sp_dashboard'
invite_api_password='secret'
invite_landing_url='https://example.org'
invite_spdashboard_manage_id='4b0e422d-d0d0-4b9e-a521-fdd1ee5d2bad'

# Mail default settings
[email protected]
[email protected]
Expand Down
35 changes: 5 additions & 30 deletions ci/qa/phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -451,21 +451,6 @@
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Application/CommandHandler/PrivacyQuestions/PrivacyQuestionsCommandHandler.php',
];
$ignoreErrors[] = [
'message' => '#^Call to an undefined method Surfnet\\\\ServiceProviderDashboard\\\\Domain\\\\Repository\\\\PublishTeamsRepository\\:\\:createTeam\\(\\)\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Application/CommandHandler/Service/CreateServiceCommandHandler.php',
];
$ignoreErrors[] = [
'message' => '#^Method Surfnet\\\\ServiceProviderDashboard\\\\Application\\\\CommandHandler\\\\Service\\\\CreateServiceCommandHandler\\:\\:createEmailsArray\\(\\) return type has no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Application/CommandHandler/Service/CreateServiceCommandHandler.php',
];
$ignoreErrors[] = [
'message' => '#^Method Surfnet\\\\ServiceProviderDashboard\\\\Application\\\\CommandHandler\\\\Service\\\\CreateServiceCommandHandler\\:\\:createTeamData\\(\\) return type has no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Application/CommandHandler/Service/CreateServiceCommandHandler.php',
];
$ignoreErrors[] = [
'message' => '#^Parameter \\#1 \\$organizationNameEn of method Surfnet\\\\ServiceProviderDashboard\\\\Domain\\\\Entity\\\\Service\\:\\:setOrganizationNameEn\\(\\) expects string, string\\|null given\\.$#',
'count' => 1,
Expand All @@ -476,11 +461,6 @@
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Application/CommandHandler/Service/CreateServiceCommandHandler.php',
];
$ignoreErrors[] = [
'message' => '#^Parameter \\#3 \\$email of method Surfnet\\\\ServiceProviderDashboard\\\\Application\\\\CommandHandler\\\\Service\\\\CreateServiceCommandHandler\\:\\:createTeamData\\(\\) expects string, string\\|null given\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Application/CommandHandler/Service/CreateServiceCommandHandler.php',
];
$ignoreErrors[] = [
'message' => '#^Cannot call method getName\\(\\) on Surfnet\\\\ServiceProviderDashboard\\\\Domain\\\\Entity\\\\Service\\|null\\.$#',
'count' => 1,
Expand Down Expand Up @@ -4186,6 +4166,11 @@
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Infrastructure/HttpClient/ResourcePathFormatter.php',
];
$ignoreErrors[] = [
'message' => '#^Method Surfnet\\\\ServiceProviderDashboard\\\\Infrastructure\\\\Invite\\\\InviteHttpClient\\:\\:post\\(\\) has parameter \\$payload with no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Infrastructure/Invite/InviteHttpClient.php',
];
$ignoreErrors[] = [
'message' => '#^Expression on left side of \\?\\? is not nullable\\.$#',
'count' => 1,
Expand Down Expand Up @@ -4786,11 +4771,6 @@
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Infrastructure/Teams/Client/DeleteEntityClient.php',
];
$ignoreErrors[] = [
'message' => '#^Cannot access offset \'id\' on mixed\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Infrastructure/Teams/Client/PublishEntityClient.php',
];
$ignoreErrors[] = [
'message' => '#^Cannot call method getReasonPhrase\\(\\) on mixed\\.$#',
'count' => 1,
Expand All @@ -4801,11 +4781,6 @@
'count' => 2,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Infrastructure/Teams/Client/PublishEntityClient.php',
];
$ignoreErrors[] = [
'message' => '#^Method Surfnet\\\\ServiceProviderDashboard\\\\Infrastructure\\\\Teams\\\\Client\\\\PublishEntityClient\\:\\:createTeam\\(\\) has parameter \\$team with no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/../../src/Surfnet/ServiceProviderDashboard/Infrastructure/Teams/Client/PublishEntityClient.php',
];
$ignoreErrors[] = [
'message' => '#^Method Surfnet\\\\ServiceProviderDashboard\\\\Infrastructure\\\\Teams\\\\Client\\\\PublishEntityClient\\:\\:inviteMember\\(\\) has parameter \\$inviteObject with no value type specified in iterable type array\\.$#',
'count' => 1,
Expand Down
31 changes: 31 additions & 0 deletions migrations/Version20241029125655.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace Surfnet\ServiceProviderDashboard\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20241029125655 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE service ADD invite_role_id INT DEFAULT NULL, DROP invite_urn');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE service DROP invite_role_id');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,6 @@ public function setOrganizationNameNl(string $organizationNameNl): void
$this->organizationNameNl = $organizationNameNl;
}

/**
* @return string
*/
public function getOrganizationNameEn(): ?string
{
return $this->organizationNameEn;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
use Surfnet\ServiceProviderDashboard\Application\Command\Service\CreateServiceCommand;
use Surfnet\ServiceProviderDashboard\Application\CommandHandler\CommandHandler;
use Surfnet\ServiceProviderDashboard\Domain\Entity\Service;
use Surfnet\ServiceProviderDashboard\Domain\Repository\PublishTeamsRepository;
use Surfnet\ServiceProviderDashboard\Domain\Repository\InviteRepository;
use Surfnet\ServiceProviderDashboard\Domain\Repository\ServiceRepository;
use Surfnet\ServiceProviderDashboard\Infrastructure\HttpClient\Exceptions\RuntimeException\CreateTeamsException;
use Symfony\Contracts\Translation\TranslatorInterface;
Expand All @@ -32,33 +32,33 @@ class CreateServiceCommandHandler implements CommandHandler
{
public function __construct(
private readonly ServiceRepository $serviceRepository,
private readonly PublishTeamsRepository $publishEntityClient,
private readonly InviteRepository $inviteRepository,
private readonly TranslatorInterface $translator,
private readonly string $prefixPart1,
private readonly string $prefixPart2,
private readonly string $spDashboardManageId,
private readonly string $landingUrl,
) {
}

/**
* @throws CreateTeamsException
*/
public function handle(CreateServiceCommand $command): void
{
$name = $command->getName();
$serviceName = $command->getName();
$teamName = strtolower($command->getTeamName());
$fullTeamName = $this->prefixPart1 . $this->prefixPart2 . $teamName;
$roleDescription = $this->translator->trans(
'invite.role_create.description',
[
'%serviceName%' => $serviceName,
'%organisationName%' => $command->getOrganizationNameEn()
]
);

/**
* create team
**/
$team = $this->createTeamData($name, $teamName, $command->getTeamManagerEmail());
$this->publishEntityClient->createTeam($team);

/**
* create service
**/
* create service
**/
$service = new Service();
$service->setName($name);
$service->setName($serviceName);
$service->setGuid($command->getGuid());
$service->setTeamName($fullTeamName);
$service->setPrivacyQuestionsEnabled($command->isPrivacyQuestionsEnabled());
Expand All @@ -71,37 +71,17 @@ public function handle(CreateServiceCommand $command): void
$service->setOrganizationNameEn($command->getOrganizationNameEn());
$service->setOrganizationNameNl($command->getOrganizationNameNl());
$this->serviceRepository->isUnique($service);
$this->serviceRepository->save($service);
}

private function createTeamData(string $name, string $teamName, string $email): array
{
$emails = $this->createEmailsArray($email);
$response = $this->inviteRepository->createRole(
"$serviceName {$command->getOrganizationNameEn()}",
"$serviceName {$command->getOrganizationNameEn()}",
$roleDescription,
$this->landingUrl,
$this->spDashboardManageId,
);

return [
'name' => $teamName,
'description' => $this->translator->trans(
'teams.create.description',
[
'%teamName%' => $name,
]
),
'personalNote' => $this->translator->trans('teams.create.personalNote'),
'viewable' => false,
'emails' => $emails,
'roleOfCurrentUser' => 'MANAGER',
'invitationMessage' => $this->translator->trans('teams.create.invitationMessage'),
'language' => 'ENGLISH',
];
}

private function createEmailsArray(string $email): array
{
$emails = [];
foreach (explode(',', $email) as $mail) {
$emails[trim($mail)] = 'MANAGER';
}
$service->registerInvite($response->urn, $response->id);

return $emails;
$this->serviceRepository->save($service);
}
}
14 changes: 14 additions & 0 deletions src/Surfnet/ServiceProviderDashboard/Domain/Entity/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ class Service
#[ORM\Column(length: 255, nullable: false)]
private ?string $organizationNameEn = null;

#[ORM\Column(nullable: true)]
private ?int $inviteRoleId = null;

public function __construct()
{
$this->contacts = new ArrayCollection();
Expand Down Expand Up @@ -321,4 +324,15 @@ public function setOrganizationNameEn(string $organizationNameEn): void
{
$this->organizationNameEn = $organizationNameEn;
}

public function getInviteRoleId(): ?int
{
return $this->inviteRoleId;
}

public function registerInvite(string $urn, int $roleId): void
{
$this->teamName = $urn;
$this->inviteRoleId = $roleId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

/**
* Copyright 2017 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\ServiceProviderDashboard\Domain\Repository;

use Surfnet\ServiceProviderDashboard\Domain\ValueObject\CreateRoleResponse;
use Surfnet\ServiceProviderDashboard\Infrastructure\HttpClient\Exceptions\RuntimeException\InviteException;

interface InviteRepository
{
/**
* @throws InviteException
*/
public function createRole(
string $name,
string $shortName,
string $description,
string $landingPage,
string $manageId,
): CreateRoleResponse;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,6 @@

interface PublishTeamsRepository
{
/**
* Create a new team in Teams.
*
* Expects an array with the following structure:
*
{
"name": "Champions ",
"description": "Team champions",
"personalNote": "Team created by SP Dashboard",
"viewable": true,
"emails": {
"[email protected]": "ADMIN"
},
"roleOfCurrentUser": "ADMIN",
"invitationMessage": "Please..",
"language": "DUTCH"
}
public function createTeam(array $team): mixed;
/**
* Change the membership role for a given id with a given role.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/**
* Copyright 2017 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\ServiceProviderDashboard\Domain\ValueObject;

class CreateRoleResponse
{
public function __construct(
public readonly int $id,
public readonly string $name,
public readonly string $shortName,
public readonly string $description,
public readonly string $urn
) {
}
}
Loading

0 comments on commit fb02ff9

Please sign in to comment.