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

[FEATURE] [AUT-3574] Change User Perspective according to the login flow #406

Merged
merged 18 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 16 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
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"oat-sa/lib-lti1p3-ags": "^1.2",
"oat-sa/lib-lti1p3-core": "^6.0.0",
"oat-sa/generis" : ">=15.22",
"oat-sa/tao-core" : ">=54.8.0"
"oat-sa/tao-core" : "dev-feature/AUT-3574/replace-tao-as-tool-ff-by-lti-session-verification as 50.24.4"
bartlomiejmarszal marked this conversation as resolved.
Show resolved Hide resolved
},
"autoload" : {
"psr-4" : {
Expand Down
21 changes: 0 additions & 21 deletions controller/AuthoringTool.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
use helpers_Random;
use InterruptedActionException;
use OAT\Library\Lti1p3Core\Message\Payload\LtiMessagePayloadInterface;
use oat\tao\model\featureFlag\FeatureFlagChecker;
use oat\tao\model\featureFlag\FeatureFlagCheckerInterface;
use oat\taoLti\models\classes\LtiException;
use oat\taoLti\models\classes\LtiMessages\LtiErrorMessage;
use oat\taoLti\models\classes\LtiService;
Expand Down Expand Up @@ -106,18 +104,6 @@ public function launch(): void
$this->forward('run', null, null, $_GET);
}

/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function isFeatureTaoAsToolEnabled(): bool
{
return $this->getServiceManager()
->getContainer()
->get(FeatureFlagChecker::class)
->isEnabled(FeatureFlagCheckerInterface::FEATURE_FLAG_TAO_AS_A_TOOL);
}

bartlomiejmarszal marked this conversation as resolved.
Show resolved Hide resolved
/**
* @throws ContainerExceptionInterface
* @throws InterruptedActionException
Expand All @@ -126,13 +112,6 @@ private function isFeatureTaoAsToolEnabled(): bool
*/
private function getLtiMessageOrRedirectToLogin(): LtiMessagePayloadInterface
{
if (!$this->isFeatureTaoAsToolEnabled()) {
$this->getLogger()->info(
'TAO as tool feature is disabled. The user will be redirected to the login page.'
);
$this->redirect(_url('login', 'Main', 'tao'));
}

try {
$message = $this->getValidatedLtiMessagePayload();
} catch (LtiException $exception) {
Expand Down
88 changes: 88 additions & 0 deletions models/classes/DynamicConfig/LtiConfigProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2024 (original work) Open Assessment Technologies SA;
*/

declare(strict_types=1);

namespace oat\taoLti\models\classes\DynamicConfig;

use oat\oatbox\session\SessionService;
use oat\tao\model\DynamicConfig\DynamicConfigProviderInterface;
use oat\taoLti\models\classes\LtiLaunchData;
use oat\taoLti\models\classes\TaoLtiSession;
use Psr\Log\LoggerInterface;
use Throwable;

class LtiConfigProvider implements DynamicConfigProviderInterface
{
private DynamicConfigProviderInterface $configFallback;

private SessionService $session;
private LoggerInterface $logger;

public function __construct(
DynamicConfigProviderInterface $configFallback,
SessionService $session,
LoggerInterface $logger
) {
$this->configFallback = $configFallback;
$this->session = $session;
$this->logger = $logger;
}

public function getConfigByName(string $name): ?string
{
return $this->getConfigByLtiClaimName($name) ?? $this->configFallback->getConfigByName($name);
}

public function hasConfig(string $name): bool
{
return $this->getConfigByName($name) !== null;
}

private function getConfigByLtiClaimName(string $name): ?string
{
$currentSession = $this->session->getCurrentSession();

if (!$currentSession instanceof TaoLtiSession) {
return null;
}

$ltiLaunchData = $currentSession->getLaunchData();

if ($name === self::LOGIN_URL_CONFIG_NAME) {
return $ltiLaunchData->getCustomParameter(LtiLaunchData::LTI_TAO_LOGIN_URL);
}
if ($name === self::LOGOUT_URL_CONFIG_NAME) {
return $ltiLaunchData->getCustomParameter(LtiLaunchData::LTI_REDIRECT_AFTER_LOGOUT_URL);
}

try {
if ($name === self::PORTAL_URL_CONFIG_NAME && $ltiLaunchData->hasReturnUrl()) {
return $ltiLaunchData->getReturnUrl();
}
} catch (Throwable $exception) {
$this->logger->warning(
sprintf('It was not possible to recover return url claim. Exception: %s', $exception)
);
}

return null;
}
}
10 changes: 7 additions & 3 deletions models/classes/LtiLaunchData.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
use OAT\Library\Lti1p3Core\Message\Payload\Claim\AgsClaim;
use OAT\Library\Lti1p3Core\Message\Payload\LtiMessagePayloadInterface;
use OAT\Library\Lti1p3Core\Platform\PlatformInterface;
use oat\taoLti\models\classes\LtiMessages\LtiErrorMessage;
use tao_helpers_Request;
use oat\oatbox\log\LoggerAwareTrait;
use oat\taoLti\models\classes\LtiMessages\LtiErrorMessage;
use Psr\Http\Message\ServerRequestInterface;
use tao_helpers_Request;

class LtiLaunchData implements \JsonSerializable
{
Expand Down Expand Up @@ -66,6 +66,10 @@ class LtiLaunchData implements \JsonSerializable
public const LTI_SHOW_SCORE = 'custom_show_score';
public const LTI_SHOW_CORRECT = 'custom_show_correct';

public const LTI_REDIRECT_AFTER_LOGOUT_URL = 'authoringSettings.redirectAfterLogoutUrl';
Comment on lines 68 to +69
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public const LTI_REDIRECT_AFTER_LOGOUT_URL = 'authoringSettings.redirectAfterLogoutUrl';
public const LTI_REDIRECT_AFTER_LOGOUT_URL = 'authoringSettings.redirectAfterLogoutUrl';


public const LTI_TAO_LOGIN_URL = 'authoringSettings.taoLoginUrl';

andreluizmachado marked this conversation as resolved.
Show resolved Hide resolved
// for user claim
private const LTI_FOR_USER_ID = 'lti_for_user_id';
private const LTI_FOR_USER_EMAIL = 'lti_for_user_email';
Expand Down Expand Up @@ -242,7 +246,7 @@ private static function getParametersFromUrl(string $url): array
// encoded in url
$parts = explode('/', tao_helpers_Request::getRelativeUrl($url), 4);
if (count($parts) == 4) {
list($extension, $module, $action, $codedUri) = $parts;
bartlomiejmarszal marked this conversation as resolved.
Show resolved Hide resolved
[$extension, $module, $action, $codedUri] = $parts;
$base64String = base64_decode($codedUri);
if ($base64String !== false) {
// old serialised url
Expand Down
19 changes: 17 additions & 2 deletions models/classes/ServiceProvider/LtiServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@
use oat\oatbox\cache\factory\CacheItemPoolFactory;
use oat\oatbox\cache\ItemPoolSimpleCacheAdapter;
use oat\oatbox\log\LoggerService;
use oat\oatbox\session\SessionService;
use oat\tao\model\DynamicConfig\DynamicConfigProviderInterface;
use oat\taoLti\models\classes\Client\LtiClientFactory;
use oat\taoLti\models\classes\DynamicConfig\LtiConfigProvider;
use oat\taoLti\models\classes\LtiAgs\LtiAgsScoreService;
use oat\taoLti\models\classes\LtiAgs\LtiAgsScoreServiceInterface;
use oat\taoLti\models\classes\LtiRoles;
Expand All @@ -64,10 +67,10 @@
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

use function Symfony\Component\DependencyInjection\Loader\Configurator\inline_service;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
use function Symfony\Component\DependencyInjection\Loader\Configurator\env;
use function Symfony\Component\DependencyInjection\Loader\Configurator\inline_service;
use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

class LtiServiceProvider implements ContainerServiceProviderInterface
{
Expand Down Expand Up @@ -259,5 +262,17 @@ public function __invoke(ContainerConfigurator $configurator): void
param('rolesAllowed')
]
);

$services
->set(LtiConfigProvider::class)
->decorate(DynamicConfigProviderInterface::class)
->public()
->args(
[
service(LtiConfigProvider::class . '.inner'),
service(SessionService::SERVICE_ID),
service(LoggerService::SERVICE_ID),
]
);
}
}
126 changes: 126 additions & 0 deletions test/unit/models/classes/DynamicConfig/LtiConfigProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2024 (original work) Open Assessment Technologies SA;
*/

declare(strict_types=1);

namespace oat\taoLti\test\unit\models\classes\DynamicConfig;

use oat\oatbox\session\SessionService;
use oat\tao\model\DynamicConfig\DynamicConfigProviderInterface;
use oat\taoLti\models\classes\DynamicConfig\LtiConfigProvider;
use oat\taoLti\models\classes\LtiLaunchData;
use oat\taoLti\models\classes\TaoLtiSession;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;

class LtiConfigProviderTest extends TestCase
{
public function testGetConfigByName(): void
{
$ltiLaunchData = $this->createMock(LtiLaunchData::class);
$ltiLaunchData->method('getCustomParameter')
->will(
$this->returnCallback(function ($param) {
switch ($param) {
case LtiLaunchData::LTI_TAO_LOGIN_URL:
return 'https://example.com/login';
case LtiLaunchData::LTI_REDIRECT_AFTER_LOGOUT_URL:
return 'https://example.com/logout';
default:
return null;
}
})
);

$taoLtiSession = $this->createMock(TaoLtiSession::class);
$taoLtiSession->method('getLaunchData')
->willReturn($ltiLaunchData);

$session = $this->createMock(SessionService::class);
$session->method('getCurrentSession')
->willReturn($taoLtiSession);

$fallbackConfigProvider = $this->createMock(DynamicConfigProviderInterface::class);
$fallbackConfigProvider->method('getConfigByName')
->willReturnMap([
[LtiConfigProvider::LOGOUT_URL_CONFIG_NAME, 'https://fallback.com/logout'],
[LtiConfigProvider::PORTAL_URL_CONFIG_NAME, null], // Simulating no value from fallback
[LtiConfigProvider::LOGIN_URL_CONFIG_NAME, 'https://fallback.com/login'],
]);

$logger = $this->createMock(LoggerInterface::class);
$logger->expects($this->never())->method('warning');

$ltiConfigProvider = new LtiConfigProvider($fallbackConfigProvider, $session, $logger);

// Test LTI-specific configurations
$this->assertSame(
'https://example.com/logout',
$ltiConfigProvider->getConfigByName(LtiConfigProvider::LOGOUT_URL_CONFIG_NAME)
);
$this->assertSame(
'https://example.com/login',
$ltiConfigProvider->getConfigByName(LtiConfigProvider::LOGIN_URL_CONFIG_NAME)
);
$this->assertNull(
$ltiConfigProvider->getConfigByName(LtiConfigProvider::PORTAL_URL_CONFIG_NAME)
);
}

public function testHasConfig(): void
{
// Simulating LTI environment where portal URL is provided
$ltiLaunchData = $this->createMock(LtiLaunchData::class);
$ltiLaunchData->method('hasReturnUrl')->willReturn(true);

$taoLtiSession = $this->createMock(TaoLtiSession::class);
$taoLtiSession->method('getLaunchData')->willReturn($ltiLaunchData);

$session = $this->createMock(SessionService::class);
$session->method('getCurrentSession')->willReturn($taoLtiSession);

$fallbackConfigProvider = $this->createMock(DynamicConfigProviderInterface::class);
$fallbackConfigProvider->method('getConfigByName')->willReturnMap([
[LtiConfigProvider::LOGOUT_URL_CONFIG_NAME, null],
[LtiConfigProvider::PORTAL_URL_CONFIG_NAME, 'https://example.com/portal'],
[LtiConfigProvider::LOGIN_URL_CONFIG_NAME, null],
]);

$logger = $this->createMock(LoggerInterface::class);

$ltiConfigProvider = new LtiConfigProvider($fallbackConfigProvider, $session, $logger);
$this->assertTrue($ltiConfigProvider->hasConfig(DynamicConfigProviderInterface::PORTAL_URL_CONFIG_NAME));

// Simulating non-LTI environment
$session = $this->createMock(SessionService::class);
$session->method('getCurrentSession')->willReturn(null);

$fallbackConfigProvider = $this->createMock(DynamicConfigProviderInterface::class);
$fallbackConfigProvider->method('getConfigByName')->willReturnMap([
[LtiConfigProvider::LOGOUT_URL_CONFIG_NAME, null],
[LtiConfigProvider::PORTAL_URL_CONFIG_NAME, null],
[LtiConfigProvider::LOGIN_URL_CONFIG_NAME, null],
]);


$ltiConfigProvider = new LtiConfigProvider($fallbackConfigProvider, $session, $logger);
$this->assertFalse($ltiConfigProvider->hasConfig(DynamicConfigProviderInterface::PORTAL_URL_CONFIG_NAME));
}
}
Loading