Skip to content

Commit

Permalink
UHF-10826 Update ATV-profile after mandate has been requested (#1531)
Browse files Browse the repository at this point in the history
* UHF-10826: get rid of the unnecessary nesting

* UHF-10826: clean the old style properties

* UHF-10826: both traits are in base class

* UHF-10826: get company data after mandating user and send it to ATV

* UHF-10826: missing comment

* UHF-10826: Add single document query to HTTP

* UHF-10826: Small changes + handle new profile.

---------

Co-authored-by: Janne Suominen <[email protected]>
  • Loading branch information
rpnykanen and jiisuominen authored Oct 31, 2024
1 parent 17f2f19 commit 8f0fdcf
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,15 @@

namespace Drupal\grants_mandate\Controller;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Logger\LoggerChannel;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\grants_handler\Helpers;
use Drupal\grants_mandate\GrantsMandateRedirectService;
use Drupal\grants_mandate\GrantsMandateService;
use Drupal\grants_profile\GrantsProfileService;
use Drupal\grants_profile\ProfileConnector;
use Drupal\helfi_atv\AtvDocument;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
Expand All @@ -27,52 +23,6 @@
*/
class GrantsMandateController extends ControllerBase implements ContainerInjectionInterface {

use MessengerTrait;
use StringTranslationTrait;

/**
* The request stack used to access request globals.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected RequestStack $requestStack;

/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;

/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;

/**
* Mandate service.
*
* @var \Drupal\grants_mandate\GrantsMandateService
*/
protected GrantsMandateService $grantsMandateService;


/**
* Access to profile data.
*
* @var \Drupal\grants_profile\GrantsProfileService
*/
protected GrantsProfileService $grantsProfileService;

/**
* Logger access.
*
* @var \Drupal\Core\Logger\LoggerChannel|\Psr\Log\LoggerInterface
*/
protected LoggerChannel|LoggerInterface $logger;

/**
* Allowed roles.
*
Expand All @@ -81,75 +31,57 @@ class GrantsMandateController extends ControllerBase implements ContainerInjecti
protected array $allowedRoles;

/**
* The redirect service.
* The logger.
*
* @var \Drupal\grants_mandate\GrantsMandateRedirectService
* @var \Psr\Log\LoggerInterface
*/
protected $redirectService;
private LoggerInterface $logger;

/**
* Grants Mandate Controller constructor.
*
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
* The request stack.
* @param \Drupal\grants_mandate\GrantsMandateService $grantsMandateService
* The grants mandate service.
* @param \Drupal\grants_profile\GrantsProfileService $grantsProfileService
* The grants profile service.
* @param \Drupal\grants_mandate\GrantsMandateRedirectService $redirectService
* The grants mandate redirect service.
* @param \Drupal\grants_profile\ProfileConnector $profileConnector
* The profile connector.
*/
public function __construct(
RequestStack $requestStack,
AccountProxyInterface $current_user,
LanguageManagerInterface $language_manager,
GrantsMandateService $grantsMandateService,
GrantsProfileService $grantsProfileService,
ConfigFactoryInterface $configFactory,
GrantsMandateRedirectService $redirectService,
private RequestStack $requestStack,
private GrantsMandateService $grantsMandateService,
private GrantsProfileService $grantsProfileService,
private GrantsMandateRedirectService $redirectService,
private ProfileConnector $profileConnector,
) {
$this->requestStack = $requestStack;
$this->currentUser = $current_user;
$this->languageManager = $language_manager;
$this->grantsMandateService = $grantsMandateService;
$this->grantsProfileService = $grantsProfileService;
$this->redirectService = $redirectService;
$this->logger = $this->getLogger('grants_mandate');
$config = $this->config('grants_mandate.settings');

$extraRoles = is_array($config->get('extra_access_roles')) ? $config->get('extra_access_roles') : [];
$this->allowedRoles = [
'http://valtuusrekisteri.suomi.fi/avustushakemuksen_tekeminen',
'PJ',
'J',
...$extraRoles,
];
$config = $configFactory->get('grants_mandate.settings');
$extraRoles = $config->get('extra_access_roles');
if ($extraRoles && is_array($extraRoles)) {
$this->allowedRoles = array_merge($this->allowedRoles, $extraRoles);
}
}

/**
* Check if user has required role in their mandate.
*
* @param array $roles
* Array of user's roles.
*
* @return bool
* Is user allowed to use this mandate.
*/
protected function hasAllowedRole(array $roles) {
$allowedRoles = $this->allowedRoles;
foreach ($roles as $role) {
if (in_array($role, $allowedRoles)) {
return TRUE;
}
}
return FALSE;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container): GrantsMandateController|static {
return new static(
$controller = new static(
$container->get('request_stack'),
$container->get('current_user'),
$container->get('language_manager'),
$container->get('grants_mandate.service'),
$container->get('grants_profile.service'),
$container->get('config.factory'),
$container->get('grants_mandate_redirect.service'),
$container->get('grants_profile.profile_connector'),
);
return $controller->setLoggerFactory($container->get('logger.factory'));
}

/**
Expand All @@ -161,81 +93,159 @@ public static function create(ContainerInterface $container): GrantsMandateContr
*
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \Drupal\grants_mandate\GrantsMandateException
* @throws \Drupal\grants_profile\GrantsProfileException
*/
public function mandateCallbackYpa(): RedirectResponse {
$tOpts = ['context' => 'grants_mandate'];

$code = $this->requestStack->getMainRequest()->query->get('code');
$state = $this->requestStack->getMainRequest()->query->get('state');

$callbackUrl = Url::fromRoute('grants_mandate.callback_ypa', [], ['absolute' => TRUE])
->toString();

$appEnv = Helpers::getAppEnv();

if (is_string($code) && $code != '') {
$this->grantsMandateService->changeCodeToToken($code, $callbackUrl);
$roles = $this->grantsMandateService->getRoles();
$isAllowed = FALSE;
if ($roles && isset($roles[0]) && $roles[0]['roles']) {
$rolesArray = $roles[0]['roles'];
$isAllowed = $this->hasAllowedRole($rolesArray);
}
if (!$isAllowed && !str_contains($appEnv, 'LOCAL')) {
$this->messenger()->addError($this->t('Your mandate does not allow you to use this service.', [], $tOpts));
// Redirect user to grants profile page.
$redirectUrl = Url::fromRoute('grants_mandate.mandateform');
return new RedirectResponse($redirectUrl->toString());
}

$roles = reset($roles);
$roles['type'] = 'registered_community';
$this->grantsProfileService->setSelectedRoleData($roles);
// We need to exchange the code to token that can be used to authorize
// the user in oAuth calls.
$code = $this->requestStack->getMainRequest()->query->get('code');
if (!is_string($code) || !$code) {
// If code is not set, we need to handle the error and not allow
// user to progress.
return $this->handleNoCode($tOpts);
}
else {

$error = $this->requestStack->getMainRequest()->query->get('error');
$error_description = $this->requestStack->getMainRequest()->query->get('error_description');
$error_uri = $this->requestStack->getMainRequest()->query->get('error_uri');

$msg = $this->t('Code exchange error. @error: @error_desc. State: @state, Error URI: @error_uri',
[
'@error' => $error,
'@error_description' => $error_description,
'@state' => $state,
'@error_uri' => $error_uri,
], $tOpts);

$this->logger->error('Error: %error', ['%error' => $msg->render()]);

$this->messenger()->addError($this->t('Mandate process was interrupted or there was an error. Please try again.', [], $tOpts));
// If we have code, we can then exchange it to token.
$this->grantsMandateService->changeCodeToToken($code, $callbackUrl);
$roles = $this->grantsMandateService->getRoles();
$isAllowed = FALSE;
if ($roles && isset($roles[0]) && $roles[0]['roles']) {
$rolesArray = $roles[0]['roles'];
$isAllowed = $this->hasAllowedRole($rolesArray);
}
if (!$isAllowed && !str_contains($appEnv, 'LOCAL')) {
$this->messenger()
->addError($this->t('Your mandate does not allow you to use this service.', [], $tOpts));
// Redirect user to grants profile page.
$redirectUrl = Url::fromRoute('grants_mandate.mandateform');
return new RedirectResponse($redirectUrl->toString());
}

$roles = reset($roles);
$roles['type'] = 'registered_community';
$this->grantsProfileService->setSelectedRoleData($roles);

$selectedRoleData = $this->grantsProfileService->getSelectedRoleData();

// Load grants profile.
/** @var \Drupal\helfi_atv\AtvDocument $grantsProfile */
$grantsProfile = $this->grantsProfileService->getGrantsProfile($selectedRoleData, TRUE);

if ($grantsProfile) {
$this->updateProfileWithRecentData($selectedRoleData['identifier'], $grantsProfile);
}

// Redirect user based on if the user has a profile.
$redirectUrl = $grantsProfile ? Url::fromRoute('grants_oma_asiointi.front') : Url::fromRoute('grants_profile.edit');
$defaultRedirect = new RedirectResponse($redirectUrl->toString());

return $this->redirectService->getRedirect($defaultRedirect);
}

/**
* Api did not return a valid code.
*
* @param array $tOpts
* The options.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* Redirect in case of bad code.
*/
private function handleNoCode(array $tOpts): RedirectResponse {
$state = $this->requestStack->getMainRequest()->query->get('state');

$error = $this->requestStack->getMainRequest()->query->get('error');
$error_description = $this->requestStack->getMainRequest()->query->get('error_description');
$error_uri = $this->requestStack->getMainRequest()->query->get('error_uri');

$msg = $this->t('Code exchange error. @error: @error_desc. State: @state, Error URI: @error_uri',
[
'@error' => $error,
'@error_description' => $error_description,
'@state' => $state,
'@error_uri' => $error_uri,
], $tOpts);

$this->logger->error('Error: %error', ['%error' => $msg->render()]);

$this->messenger()
->addError($this->t('Mandate process was interrupted or there was an error. Please try again.', [], $tOpts));
// Redirect user to grants profile page.
$redirectUrl = Url::fromRoute('grants_mandate.mandateform');
return new RedirectResponse($redirectUrl->toString());
}

/**
* Check if user has required role in their mandate.
*
* @param array $roles
* Array of user's roles.
*
* @return bool
* Is user allowed to use this mandate.
*/
protected function hasAllowedRole(array $roles) {
$allowedRoles = $this->allowedRoles;
foreach ($roles as $role) {
if (in_array($role, $allowedRoles)) {
return TRUE;
}
}
return FALSE;
}

/**
* Callback for user mandates.
*/
public function mandateCallbackHpa() {
throw new \Exception('Called a function which has no implementation');
}

/**
* Callback for hpa listing.
*/
public function mandateCallbackHpaList() {
throw new \Exception('Called a function which has no implementation');
}

/**
* Update user profile data from ytj/yrtti and save it.
*
* @param string $identifier
* Business to get data for.
* @param \Drupal\helfi_atv\AtvDocument $grantsProfile
* Grants profile to update.
*
* @return void
* No return.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function updateProfileWithRecentData(
string $identifier,
AtvDocument $grantsProfile,
): void {

$grantsProfileContent = $grantsProfile->getContent();
try {
$companyData = $this->profileConnector
->getRegisteredCompanyDataFromYdjhClient($identifier);

$grantsProfileContent['businessId'] = $companyData['businessId'];
$grantsProfileContent['companyHome'] = $companyData['companyHome'];
$grantsProfileContent['registrationDate'] = $companyData['registrationDate'];

$this->grantsProfileService->saveGrantsProfile($grantsProfileContent);
}
catch (\Exception $e) {
// Failing at this point does not matter, the execution can continue.
$this->logger
->error('Failed to update grants profile after getting the mandate.');
}
}

}
7 changes: 6 additions & 1 deletion tools/http/ATV.http
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Get single document by transaction_id
# Get single document by document id
GET {{atvUrl}}/v1/documents/{{document_id}}
Accept-Encoding: utf8
X-Api-Key: {{atvApiKey}}

#### Get single document by transaction_id
GET {{atvUrl}}/v1/documents/?
transaction_id={{transaction_id}}
Accept-Encoding: utf8
Expand Down

0 comments on commit 8f0fdcf

Please sign in to comment.