Skip to content

Commit

Permalink
Merge branch 'bugfix/remove-help-on-dpa-type-parent' into release/5.1
Browse files Browse the repository at this point in the history
  • Loading branch information
MKodde committed Aug 28, 2023
2 parents b9c6d5a + 1805fec commit 00bc417
Show file tree
Hide file tree
Showing 49 changed files with 290 additions and 88 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
- Introduce new privacy questions #591
- Push test metadata upon entity deletion #594

## 5.0.2
- Prevent team member double delete drama #600
- Render the custom unknown service error page #599

## 5.0.1
- Repair jira_enable_test_mode feature flag #592

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
align="right" />
</a>

[![Build status](https://img.shields.io/travis/SURFnet/sp-dashboard.svg)](https://travis-ci.com/SURFnet/sp-dashboard)
[![Build status](https://github.com/SURFnet/sp-dashboard/actions/workflows/test-integration.yml/badge.svg)](https://github.com/SURFnet/sp-dashboard/actions/workflows/test-integration.yml)
[![License](https://img.shields.io/github/license/SURFnet/sp-dashboard.svg)](https://github.com/SURFnet/sp-dashboard/blob/master/LICENSE.txt)

# Service Provider Dashboard
Expand Down Expand Up @@ -44,7 +44,7 @@ used in development to run the application.

Install database migrations
```
$ docker exec sp-dashboard_php-fpm_1 /var/www/html/bin/console doctrine:migrations:migrate
$ docker exec sp-dashboard-php-fpm-1 /var/www/html/bin/console doctrine:migrations:migrate
```

The application is now up and running and can be accessed at
Expand Down
3 changes: 2 additions & 1 deletion assets/js/components/change_member_role.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ $(() => {
const flashUl = document.querySelector('.teams__flashMessages') as HTMLUListElement;
const changeRoleLinks = document.querySelectorAll('.teams__changeMemberRole');
changeRoleLinks.forEach(item => {
item.addEventListener('mousedown', (event) => {
item.addEventListener('click', (event) => {
event.preventDefault();
const target = event.target as HTMLAnchorElement;
const roleName = target.getAttribute('data-role');
const parentElement = target.closest('div');
Expand Down
3 changes: 2 additions & 1 deletion assets/js/components/delete_member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ $(() => {

if (!!flashUl && !!deleteLinks) {
deleteLinks.forEach(item => {
item.addEventListener('mousedown', (event) => {
item.addEventListener('click', (event) => {
event.preventDefault();
event.stopImmediatePropagation();
const target = event.target as HTMLSelectElement;
if (!target.matches('.teams__deleteMemberLink')) return;
Expand Down
3 changes: 2 additions & 1 deletion assets/js/components/resend_invite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ $(() => {

if (!!flashUl && !!resendInviteLinks) {
resendInviteLinks.forEach(item => {
item.addEventListener('mousedown', (event) => {
item.addEventListener('click', (event) => {
event.preventDefault();
event.stopImmediatePropagation();
const target = event.target as HTMLSelectElement;
if (!target.matches('.teams__resendInviteLink')) return;
Expand Down
4 changes: 3 additions & 1 deletion assets/js/components/service_switcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ $(document).ready(function() {
}

$('select#service-switcher')
.select2()
.select2({
placeholder: ''
})
.change(submitFormOnSelectionChange);
});
4 changes: 2 additions & 2 deletions assets/scss/components/collection_widget.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@


display: inline-block;
padding: 5px 10px;
padding: 3px 10px;
text-transform: uppercase;
background-color: white;
color: $blue;
Expand All @@ -37,4 +37,4 @@

@include no-text-decoration;
}
}
}
4 changes: 2 additions & 2 deletions assets/scss/components/connection_request.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.connection-request-wrapper {
.button-small {
padding: 5px 10px;
top: 1.5rem;
padding: 3px 10px;
top: 25px;
}
.collection-list {
margin-bottom: 1rem;
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"symfony/security-bundle": "5.4.*",
"symfony/security-csrf": "5.4.*",
"symfony/translation": "5.4.*",
"symfony/twig-bridge": "5.4.*",
"symfony/twig-bundle": "5.4.*",
"symfony/validator": "5.4.*",
"symfony/yaml": "5.4.*",
Expand Down
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ security:
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
pattern: ^/(_(profiler|wdt|error)|css|images|js)/
security: false

login_firewall:
Expand Down
2 changes: 0 additions & 2 deletions config/packages/twig.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
twig:
default_path: '%kernel.project_dir%/templates'
paths:
'%kernel.project_dir%/templates': 'Dashboard'
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
exception_controller: null
globals:
locale: "%env(locale)%"
logout: "%env(logout_redirect_url)%"
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
_errors:
when@dev:
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error
prefix: /_error
4 changes: 0 additions & 4 deletions config/routes_dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,5 @@ _profiler:
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
prefix: /_profiler

_errors:
resource: '@TwigBundle/Resources/config/routing/errors.xml'
prefix: /_error

_main:
resource: routes.yaml
9 changes: 9 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,12 @@ services:

# This service is configured in the Jira IssueRepositoryCompilerPass
surfnet.dashboard.repository.issue: ~

Surfnet\SamlBundle\Security\Authentication\Handler\FailureHandler:
class: Surfnet\ServiceProviderDashboard\Infrastructure\DashboardBundle\Security\Authentication\Handler\FailureHandler
arguments:
- '@http_kernel'
- '@security.http_utils'
- []
- '@logger'
- '@twig'
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM ghcr.io/openconext/openconext-containers/openconext-phpfpm-dev:81 AS node-build
COPY . /var/www/html/
WORKDIR /var/www/html/
ENV SYMFONY_ENV=prod
ENV APP_ENV=prod
RUN composer install -n --prefer-dist -o --ignore-platform-reqs --no-dev

FROM node:14 AS js-build
Expand Down
Binary file modified public/favicon.ico
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,25 @@

class PublishEntityProductionCommand implements PublishProductionCommandInterface, Command
{
private bool $isClientReset = false;

public function __construct(
#[Assert\Type('\Surfnet\ServiceProviderDashboard\Domain\Entity\ManageEntity')]
private ManageEntity $manageEntity,
private Contact $applicant
) {
}

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

public function markPublishClientReset(): void
{
$this->isClientReset = true;
}

public function getManageEntity(): ManageEntity
{
return $this->manageEntity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ class SaveOidcngEntityCommand implements SaveEntityCommandInterface
private $supportContact;

/**
* @SpDashboardAssert\ValidAttribute()
* @SpDashboardAssert\ValidAttribute(type="oidcng")
*/
private $attributes = [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ class SaveSamlEntityCommand implements SaveEntityCommandInterface
private $supportContact;

/**
* @SpDashboardAssert\ValidAttribute()
* @SpDashboardAssert\ValidAttribute(type="saml20")
*/
private $attributes = [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function handle(DeletePublishedProductionEntityCommand $command)
}

if ($response !== DeleteManageEntityRepository::RESULT_SUCCESS) {
throw new EntityNotDeletedException('Deleting the entity yielded an non success response');
throw new EntityNotDeletedException('Deleting the entity yielded a non success response');
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public function handle(PublishProductionCommandInterface $command)
);

// No need to create a Jira ticket when resetting the client secret
if ($command instanceof PublishEntityProductionCommand) {
if ($command instanceof PublishEntityProductionCommand && !$command->isClientReset()) {
$this->ticketService->createJiraTicket(
$entity,
$command,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class ResetOidcSecretCommandHandler implements CommandHandler
public function __construct(
private readonly CommandBus $commandBus,
private readonly AuthorizationService $authorizationService,
private readonly PublishEntityClient $publishEntityClient
private readonly PublishEntityClient $publishProdEntityClient,
private readonly PublishEntityClient $publishTestEntityClient
) {
}

Expand All @@ -63,8 +64,9 @@ public function handle(ResetOidcSecretCommand $command)

$entity->updateClientSecret($secret);

if ($entity->getEnvironment() === Constants::ENVIRONMENT_PRODUCTION) {
if ($entity->isProduction()) {
$publishCommand = new PublishEntityProductionCommand($entity, $this->authorizationService->getContact());
$publishCommand->markPublishClientReset();
$this->commandBus->handle($publishCommand);
} else if ($entity->getEnvironment() === Constants::ENVIRONMENT_TEST) {
$publishCommand = new PublishEntityTestCommand($entity);
Expand All @@ -73,7 +75,11 @@ public function handle(ResetOidcSecretCommand $command)
if (!$entity->isExcludedFromPush()) {
// Push metadata (we push to production manage upon client secret resets)
// https://www.pivotaltracker.com/story/show/173009970
$this->publishEntityClient->pushMetadata();
if ($entity->isProduction()) {
$this->publishProdEntityClient->pushMetadata();
return;
}
$this->publishTestEntityClient->pushMetadata();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function build(ManageEntity $entity): array

$attributes = [];

if ($entity->getService()->isPrivacyQuestionsEnabled()) {
if ($privacyQuestionAnswers !== null && $entity->getService()->isPrivacyQuestionsEnabled()) {
foreach ($privacyQuestions as $question) {
if ($question->id === 'privacyStatementUrl') {
$privacyStatements = $privacyQuestionAnswers->privacyStatementUrls();
Expand All @@ -71,7 +71,7 @@ public function build(ManageEntity $entity): array
}

$getterName = $question->getterName;
if ($privacyQuestionAnswers !== null && method_exists($privacyQuestionAnswers, $getterName)) {
if (method_exists($privacyQuestionAnswers, $getterName)) {
$this->buildPrivacyQuestion(
$attributes,
$getterName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function getServiceNamesById()
*
* @param array $allowedServices The input should be service names keyed by service id.
* As provided by: AuthorizationService::getAllowedServiceNamesById
* @return array
* @return Service[]
*/
public function getServicesByAllowedServices(array $allowedServices)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\RouterInterface;
use function reset;

/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
Expand Down Expand Up @@ -83,8 +84,17 @@ public function overviewAction()
if (empty($services)) {
return $this->redirectToRoute('service_add');
}
// If only one service is available and you are admin, select that one
if ($this->isGranted('ROLE_ADMINISTRATOR') && count($services) === 1) {
$service = reset($services);
$this->authorizationService->changeActiveService($service->getId());
return $this->redirect(
$this->generateUrl('service_admin_overview', ['serviceId' => $service->getId()])
);
}

if ($this->isGranted('ROLE_ADMINISTRATOR')) {
// If more than one service and you are admin, the show the: select a service from the switcher message
if ($this->isGranted('ROLE_ADMINISTRATOR') && count($services) > 1) {
return $this->render("@Dashboard/Service/admin_overview.html.twig");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

/**
* Copyright 2023 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\Infrastructure\DashboardBundle\EventListener;

use Psr\Log\LoggerInterface;
use Surfnet\ServiceProviderDashboard\Infrastructure\DashboardSamlBundle\Security\Exception\UnknownServiceException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Twig\Environment;

class ExceptionListener
{
public function __construct(
private LoggerInterface $logger,
private Environment $templating,
) {
}

public function __invoke(ExceptionEvent $event): void
{
// You get the exception object from the received event
$exception = $event->getThrowable();
if ($exception instanceof UnknownServiceException) {
$responseBody = $this->templating->render(
'@Twig/Exception/unknownService.html.twig',
['teamNames' => $exception->getTeamNames()]
);

$event->setResponse(new Response($responseBody, Response::HTTP_UNAUTHORIZED));
}
}
}
Loading

0 comments on commit 00bc417

Please sign in to comment.