Skip to content
Open
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
10 changes: 10 additions & 0 deletions ProcessMaker/Http/Controllers/HomeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ public function redirectToIntended()
return redirect($url)->withCookie(\Cookie::forget('processmaker_intended'));
}

// No intended URL. Honor the tenant's package-dynamic-ui home page
// if it's installed, so admins'configured landing pages are still
// respected, before falling back to /requests.
if (Auth::check() && class_exists(\ProcessMaker\Package\PackageDynamicUI\Models\DynamicUI::class)) {
$homePage = \ProcessMaker\Package\PackageDynamicUI\Models\DynamicUI::getHomePage(Auth::user());
if (!empty($homePage)) {
return redirect($homePage);
}
}

return redirect()->route('requests.index');
}
}
88 changes: 83 additions & 5 deletions tests/Feature/HomeControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

namespace Tests\Feature;

use Tests\TestCase;
use ProcessMaker\Models\User;
use ProcessMaker\Models\Group;
use ProcessMaker\Models\User;
use ProcessMaker\Package\PackageDynamicUI\Models\DynamicUI;
use Tests\Feature\Shared\RequestHelper;
use Tests\TestCase;

class HomeControllerTest extends TestCase
{
use RequestHelper;

/**
* Sample deep-link URL used as the "originally requested" page for the
* redirect-to-intended tests.
*/
private const INTENDED_DEEP_LINK = '/designer/scripts/123/edit';

protected function setUp(): void
{
parent::setUp();
Expand All @@ -32,7 +38,7 @@ public function testRedirectsToLoginWhenNotAuthenticated()
public function testRedirectsToCustomDashboardWhenUserHasDashboard()
{
$user = User::factory()->create();

// Create a custom dashboard for the user
DynamicUI::create([
'type' => 'DASHBOARD',
Expand Down Expand Up @@ -68,7 +74,7 @@ public function testRedirectsToCustomDashboardWhenGroupHasDashboard()
public function testRedirectsToTasksOnMobileWithoutCustomDashboard()
{
$user = User::factory()->create();

// Mock MobileHelper to return true
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1';
$_COOKIE['isMobile'] = 'true';
Expand All @@ -84,7 +90,7 @@ public function testRedirectsToTasksOnMobileWithoutCustomDashboard()
public function testRedirectsToInboxOnDesktopWithoutCustomDashboard()
{
$user = User::factory()->create();

// Mock MobileHelper to return false
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36';
$_COOKIE['isMobile'] = 'false';
Expand Down Expand Up @@ -131,4 +137,76 @@ public function testRedirectsToGroupUrlRedirect()
$response = $this->actingAs($user)->get('/');
$response->assertRedirect('https://processmaker.com/home');
}

/** @test */
public function testRedirectToIntendedHonorsCookie()
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->withCookie('processmaker_intended', self::INTENDED_DEEP_LINK)
->get(route('redirect_to_intended'));
$response->assertRedirect(self::INTENDED_DEEP_LINK);
}

/**
* Regression test for the SAML "land on home instead of intended URL"
* bug: when the user comes back from the SSO callback through the
* /redirect-to-intended recovery hop with a valid `processmaker_intended`
* cookie, the cookie wins -- the configured Dynamic UI home page does
* not preempt it.
*
* @test
*/
public function testRedirectToIntendedCookieTakesPrecedenceOverDynamicUiHome()
{
$user = User::factory()->create();

DynamicUI::create([
'type' => 'URL',
'assignable_id' => $user->id,
'assignable_type' => User::class,
'homepage' => 'https://processmaker.com/configured-landing',
]);

$response = $this->actingAs($user)
->withCookie('processmaker_intended', self::INTENDED_DEEP_LINK)
->get(route('redirect_to_intended'));

$response->assertRedirect(self::INTENDED_DEEP_LINK);
}

/**
* The intended-URL cookie is single-use: once we've consumed it we must
* tell the browser to drop it, otherwise it would keep deflecting every
* subsequent SSO callback to the same stale URL.
*
* @test
*/
public function testRedirectToIntendedClearsCookieAfterUse()
{
$user = User::factory()->create();

$response = $this->actingAs($user)
->withCookie('processmaker_intended', self::INTENDED_DEEP_LINK)
->get(route('redirect_to_intended'));

$response->assertRedirect(self::INTENDED_DEEP_LINK);
$response->assertCookieExpired('processmaker_intended');
}

/**
* When there's no intended URL at all we still need to send the user somewhere.
* With no dashboard configured, DynamicUI::getHomePage() falls through to route('home')
* which HomeController::index() will then re-route to /inbox (or /tasks on mobile) on the next request.
*
* @test
*/
public function testRedirectToIntendedFallsBackToHomeWhenNoCookieAndNoDashboard()
{
$user = User::factory()->create();

$response = $this->actingAs($user)->get(route('redirect_to_intended'));

$response->assertRedirect(route('home'));
}
}
Loading