<?php declare(strict_types=1); namespace SimpleSAML\Module\accounting\Http\Controllers\User; use Psr\Log\LoggerInterface; use SimpleSAML\Auth\Simple; use SimpleSAML\Configuration as SspConfiguration; use SimpleSAML\HTTP\RunnableResponse; use SimpleSAML\Module\accounting\Exceptions\Exception; use SimpleSAML\Module\accounting\Helpers\AttributesHelper; use SimpleSAML\Module\accounting\ModuleConfiguration; use SimpleSAML\Module\accounting\ModuleConfiguration\ConnectionType; use SimpleSAML\Module\accounting\Providers\Builders\AuthenticationDataProviderBuilder; use SimpleSAML\Module\accounting\Providers\Interfaces\AuthenticationDataProviderInterface; use SimpleSAML\Module\accounting\Services\HelpersManager; use SimpleSAML\Session; use SimpleSAML\XHTML\Template; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class Profile { protected ModuleConfiguration $moduleConfiguration; protected SspConfiguration $sspConfiguration; protected Session $session; protected LoggerInterface $logger; protected string $defaultAuthenticationSource; protected Simple $authSimple; protected AuthenticationDataProviderBuilder $authenticationDataProviderBuilder; protected HelpersManager $helpersManager; /** * @param ModuleConfiguration $moduleConfiguration * @param SspConfiguration $sspConfiguration * @param Session $session The current user session. * @param LoggerInterface $logger * @param Simple|null $authSimple * @param AuthenticationDataProviderBuilder|null $authenticationDataProviderBuilder * @param HelpersManager|null $helpersManager */ public function __construct( ModuleConfiguration $moduleConfiguration, SspConfiguration $sspConfiguration, Session $session, LoggerInterface $logger, Simple $authSimple = null, AuthenticationDataProviderBuilder $authenticationDataProviderBuilder = null, HelpersManager $helpersManager = null ) { $this->moduleConfiguration = $moduleConfiguration; $this->sspConfiguration = $sspConfiguration; $this->session = $session; $this->logger = $logger; $this->defaultAuthenticationSource = $moduleConfiguration->getDefaultAuthenticationSource(); $this->authSimple = $authSimple ?? new Simple($this->defaultAuthenticationSource, $sspConfiguration, $session); $this->helpersManager = $helpersManager ?? new HelpersManager(); $this->authenticationDataProviderBuilder = $authenticationDataProviderBuilder ?? new AuthenticationDataProviderBuilder($this->moduleConfiguration, $this->logger, $this->helpersManager); // Make sure the end user is authenticated. $this->authSimple->requireAuth(); } public function personalData(Request $request): Response { $normalizedAttributes = []; $toNameAttributeMap = $this->prepareToNameAttributeMap(); /** * @var string $name * @var string[] $value */ foreach ($this->authSimple->getAttributes() as $name => $value) { // Convert attribute names to user-friendly names. if (array_key_exists($name, $toNameAttributeMap)) { $name = (string)$toNameAttributeMap[$name]; } $normalizedAttributes[$name] = implode('; ', $value); } $template = $this->resolveTemplate('accounting:user/personal-data.twig'); $template->data = compact('normalizedAttributes'); return $template; } public function connectedOrganizations(Request $request): Template { $userIdentifier = $this->resolveUserIdentifier(); $authenticationDataProvider = $this->resolveAuthenticationDataProvider(); $this->removeDebugDisplayLimits(); $connectedServiceProviderBag = $authenticationDataProvider->getConnectedServiceProviders($userIdentifier); $template = $this->resolveTemplate('accounting:user/connected-organizations.twig'); $template->data = compact('connectedServiceProviderBag'); return $template; } public function activity(Request $request): Template { $userIdentifier = $this->resolveUserIdentifier(); $authenticationDataProvider = $this->resolveAuthenticationDataProvider(); $page = ($page = (int)$request->query->get('page', 1)) > 0 ? $page : 1; $maxResults = 10; $firstResult = ($page - 1) * $maxResults; $this->removeDebugDisplayLimits(); $activityBag = $authenticationDataProvider->getActivity($userIdentifier, $maxResults, $firstResult); $template = $this->resolveTemplate('accounting:user/activity.twig'); $template->data = compact('activityBag', 'page', 'maxResults'); return $template; } protected function resolveUserIdentifier(): string { $attributes = $this->authSimple->getAttributes(); $idAttributeName = $this->moduleConfiguration->getUserIdAttributeName(); if (empty($attributes[$idAttributeName]) || !is_array($attributes[$idAttributeName])) { $message = sprintf('No identifier %s present in user attributes.', $idAttributeName); throw new Exception($message); } return (string)reset($attributes[$idAttributeName]); } /** * @throws Exception */ protected function resolveAuthenticationDataProvider(): AuthenticationDataProviderInterface { return $this->authenticationDataProviderBuilder ->build( $this->moduleConfiguration->getDefaultDataTrackerAndProviderClass(), ConnectionType::SLAVE ); } public function logout(): Response { // TODO mivanci make logout button available using HTTP POST return new RunnableResponse([$this->authSimple, 'logout'], [$this->getLogoutUrl()]); } protected function getLogoutUrl(): string { return $this->sspConfiguration->getBasePath() . 'logout.php'; } /** * Load all attribute map files which translate attribute names to user-friendly name format. */ protected function prepareToNameAttributeMap(): array { return $this->helpersManager->getAttributesHelper()->getMergedAttributeMapForFiles( $this->sspConfiguration->getBaseDir(), AttributesHelper::MAP_FILES_TO_NAME ); } /** TODO mivanci remove after debugging */ protected function removeDebugDisplayLimits(): void { ini_set('xdebug.var_display_max_depth', '-1'); ini_set('xdebug.var_display_max_children', '-1'); ini_set('xdebug.var_display_max_data', '-1'); } protected function resolveTemplate(string $template): Template { $templateInstance = new Template($this->sspConfiguration, $template); $templateInstance->getLocalization()->addModuleDomain(ModuleConfiguration::MODULE_NAME); $templateInstance->getLocalization()->addAttributeDomains(); return $templateInstance; } }