Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DAVPTA-1027 DAViD Integration #12

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
78 changes: 16 additions & 62 deletions Classes/Eel/Helper/FobiHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,19 @@

namespace CRON\DAV\Fobi\Eel\Helper;

use CRON\ObisIntegration\ObisException;
use CRON\DAV\Fobi\Service\TokenDataProviderInterface;
use DateInterval;
use DateTime;
use Exception;
use Firebase\JWT\JWT;
use Neos\Eel\ProtectedContextAwareInterface;
use Neos\Flow\Annotations as Flow;
use Firebase\JWT\JWT;
use Neos\Flow\Configuration\Exception\InvalidConfigurationException;
use Neos\Flow\Log\Utility\LogEnvironment;
use Neos\Flow\Security\Context;
use Neos\Flow\Session\Exception\SessionNotStartedException;
use Psr\Log\LoggerInterface;
use CRON\ObisIntegration\Service\DavUserService;

/** @noinspection PhpUnused */
class FobiHelper implements ProtectedContextAwareInterface
{
/**
* @Flow\Inject
* @var DavUserService
*/
protected $davUserService;

/**
* @Flow\Inject
* @var Context
*/
protected $securityContext;

/**
* @Flow\InjectConfiguration(package="CRON.DAV.Fobi")
* @var array
Expand All @@ -57,38 +41,29 @@ public function injectLogger(LoggerInterface $logger): void
* @return string A token identifying the user, or an empty string if there is no user
*
* @throws InvalidConfigurationException
* @throws \Neos\Flow\Exception
* @throws SessionNotStartedException
* @throws ObisException
* @throws Exception
*/
public function getToken(): string
{
$username = $this->davUserService->getCurrentUsername();
if (empty($username)) {
return '';
$tokenDataProviderClassName = $this->settings['tokenDataProvider']['className'];

if (empty($tokenDataProviderClassName)) {
throw new Exception('No tokenDataProvider configured.');
}

$davUser = $this->davUserService->getCurrentDavUser();
$obisRoles = $this->davUserService->getCurrentRoles();
$sessionRoles = $this->securityContext->getRoles();
$tokenDataProvider = new $tokenDataProviderClassName();

// We want only the roles from Neos which we need for Fobi
$mappedRoles = [];
foreach ($sessionRoles as $key => $value) {
if (isset($this->settings['rolesMapping'][$key])) {
$mappedRoles[] = $key;
}
if (!$tokenDataProvider instanceof TokenDataProviderInterface) {
throw new Exception(sprintf('Class "%s" should implement TokenDataProviderInterface but does not.', $tokenDataProviderClassName));
}

// Ensures after the arrays have been merged that the roles are always unique
$roles = array_unique($obisRoles + $mappedRoles);
$tokenData = $tokenDataProvider->getTokenData();

return $this->createToken(
$username, // in the latest versions the username is always the mail address
$davUser->getFirstName(),
$davUser->getLastName(),
$this->getFobiRoles($roles)
);
if (!$tokenData) {
return '';
}

return $this->createToken($tokenData['email'], $tokenData['firstName'], $tokenData['lastName'], $tokenData['roles']);
}

/**
Expand Down Expand Up @@ -144,27 +119,6 @@ protected function createToken(?string $email, ?string $firstName, ?string $last
return $jwt;
}

/**
* Map flow roles to strings to be used in DAV.Fobi
*
* Use the CRON.DAV.Fobi.rolesMapping setting
*
* @param array $roles A list of flow roles
* @return array
*/
protected function getFobiRoles(array $roles): array
{
if (empty($roles)) {
return [];
}
return array_map(function ($role) {
if (isset($this->settings['rolesMapping'][$role])) {
$role = $this->settings['rolesMapping'][$role];
}
return $role;
}, $roles);
}

/**
* Allow calling all public methods as Eel functions (only getToken)
*
Expand Down
14 changes: 14 additions & 0 deletions Classes/Service/TokenDataProviderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace CRON\DAV\Fobi\Service;

interface TokenDataProviderInterface
{
/**
* This method should return an associative array with "email", "firstName", "lastName" and "roles", containing
* the respective data.
*
* @return array|null
*/
public function getTokenData(): ?array;
}
6 changes: 2 additions & 4 deletions Configuration/Settings.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
CRON:
DAV:
Fobi:
tokenDataProvider:
className: ''
widgetLoaderUri: '%env:DAV_FOBI_URI%'
token:
# The issuer of the token
Expand All @@ -11,7 +13,3 @@ CRON:
secret: '%env:DAV_FOBI_SECRET%'
# Token expiration: a string which can be passed to the php DateInterval constructor
expiresAfter: '%env:DAV_FOBI_EXPIRESAFTER%'
rolesMapping:
# Map flow roles to strings used in Fobi, i.e.:
#'CRON.DazSite:DazSubscriber': 'DAZ-Abo'
#'CRON.DazSite:ELearningUser': 'eLearning-Benutzer'
12 changes: 0 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,3 @@ Use environment variables for the secrets:
`DAV_FOBI_AUDIENCE`: the target domain for which the token was issued.
`DAV_FOBI_SECRET`: the token shared passphrase
`DAV_FOBI_EXPIRESAFTER`: token expiration, as a string which can be passed to the php DateInterval constructor (i.e. `PT6H`)

Furthermore, configure a proper mapping between the Flow roles and the name of the ACLs for Fobi, i.e.:

```yaml
CRON:
DAV:
Fobi:
rolesMapping:
# Map flow roles to strings used in Fobi
'CRON.DazSite:DazSubscriber': 'DAZ-Abo'
'CRON.DazSite:ELearningUser': 'eLearning-Benutzer'
```